1
0
mirror of https://github.com/golang/go synced 2024-11-23 05:00:07 -07:00

cmd/compile: implement "OPC $imm, (mem)" for 386

New read-modify-write operations are introduced in this CL for 386.

1. The total size of pkg/linux_386 decreases about 10KB (excluding
cmd/compile).

2. The go1 benchmark shows little regression.
name                     old time/op    new time/op    delta
BinaryTree17-4              3.32s ± 4%     3.29s ± 2%    ~     (p=0.059 n=30+30)
Fannkuch11-4                3.49s ± 1%     3.46s ± 1%  -0.92%  (p=0.001 n=30+30)
FmtFprintfEmpty-4          47.7ns ± 2%    46.8ns ± 5%  -1.93%  (p=0.011 n=25+30)
FmtFprintfString-4         79.5ns ± 7%    80.2ns ± 3%  +0.89%  (p=0.001 n=28+29)
FmtFprintfInt-4            90.5ns ± 2%    92.1ns ± 2%  +1.82%  (p=0.014 n=22+30)
FmtFprintfIntInt-4          141ns ± 1%     144ns ± 3%  +2.23%  (p=0.013 n=22+30)
FmtFprintfPrefixedInt-4     183ns ± 2%     184ns ± 3%    ~     (p=0.080 n=21+30)
FmtFprintfFloat-4           409ns ± 3%     412ns ± 3%  +0.83%  (p=0.040 n=30+30)
FmtManyArgs-4               597ns ± 6%     607ns ± 4%  +1.71%  (p=0.006 n=30+30)
GobDecode-4                7.21ms ± 5%    7.18ms ± 6%    ~     (p=0.665 n=30+30)
GobEncode-4                7.17ms ± 6%    7.09ms ± 7%    ~     (p=0.117 n=29+30)
Gzip-4                      413ms ± 4%     399ms ± 4%  -3.48%  (p=0.000 n=30+30)
Gunzip-4                   41.3ms ± 4%    41.7ms ± 3%  +1.05%  (p=0.011 n=30+30)
HTTPClientServer-4         63.5µs ± 3%    62.9µs ± 2%  -0.97%  (p=0.017 n=30+27)
JSONEncode-4               20.3ms ± 5%    20.1ms ± 5%  -1.16%  (p=0.004 n=30+30)
JSONDecode-4               66.2ms ± 4%    67.7ms ± 4%  +2.21%  (p=0.000 n=30+30)
Mandelbrot200-4            5.16ms ± 3%    5.18ms ± 3%    ~     (p=0.123 n=30+30)
GoParse-4                  3.23ms ± 2%    3.27ms ± 2%  +1.08%  (p=0.006 n=30+30)
RegexpMatchEasy0_32-4      98.9ns ± 5%    97.1ns ± 4%  -1.83%  (p=0.006 n=30+30)
RegexpMatchEasy0_1K-4       842ns ± 3%     842ns ± 3%    ~     (p=0.550 n=30+30)
RegexpMatchEasy1_32-4       107ns ± 4%     105ns ± 4%  -1.93%  (p=0.012 n=30+30)
RegexpMatchEasy1_1K-4      1.03µs ± 4%    1.04µs ± 4%    ~     (p=0.304 n=30+30)
RegexpMatchMedium_32-4      132ns ± 2%     129ns ± 4%  -2.02%  (p=0.000 n=21+30)
RegexpMatchMedium_1K-4     44.1µs ± 4%    43.8µs ± 3%    ~     (p=0.641 n=30+30)
RegexpMatchHard_32-4       2.26µs ± 4%    2.23µs ± 4%  -1.28%  (p=0.023 n=30+30)
RegexpMatchHard_1K-4       68.1µs ± 3%    68.6µs ± 4%    ~     (p=0.089 n=30+30)
Revcomp-4                   1.85s ± 2%     1.84s ± 2%    ~     (p=0.072 n=30+30)
Template-4                 69.2ms ± 3%    68.5ms ± 3%  -1.04%  (p=0.012 n=30+30)
TimeParse-4                 441ns ± 3%     446ns ± 4%  +1.21%  (p=0.001 n=30+30)
TimeFormat-4                415ns ± 3%     415ns ± 3%    ~     (p=0.436 n=30+30)
[Geo mean]                 67.0µs         66.9µs       -0.17%

name                     old speed      new speed      delta
GobDecode-4               107MB/s ± 5%   107MB/s ± 6%    ~     (p=0.663 n=30+30)
GobEncode-4               107MB/s ± 6%   108MB/s ± 7%    ~     (p=0.117 n=29+30)
Gzip-4                   47.0MB/s ± 4%  48.7MB/s ± 4%  +3.61%  (p=0.000 n=30+30)
Gunzip-4                  470MB/s ± 4%   466MB/s ± 4%  -1.05%  (p=0.011 n=30+30)
JSONEncode-4             95.6MB/s ± 5%  96.7MB/s ± 5%  +1.16%  (p=0.005 n=30+30)
JSONDecode-4             29.3MB/s ± 4%  28.7MB/s ± 4%  -2.17%  (p=0.000 n=30+30)
GoParse-4                17.9MB/s ± 2%  17.7MB/s ± 2%  -1.06%  (p=0.007 n=30+30)
RegexpMatchEasy0_32-4     323MB/s ± 5%   329MB/s ± 4%  +1.93%  (p=0.006 n=30+30)
RegexpMatchEasy0_1K-4    1.22GB/s ± 3%  1.22GB/s ± 3%    ~     (p=0.496 n=30+30)
RegexpMatchEasy1_32-4     298MB/s ± 4%   303MB/s ± 4%  +1.84%  (p=0.017 n=30+30)
RegexpMatchEasy1_1K-4     995MB/s ± 4%   989MB/s ± 4%    ~     (p=0.307 n=30+30)
RegexpMatchMedium_32-4   7.56MB/s ± 4%  7.74MB/s ± 4%  +2.46%  (p=0.000 n=22+30)
RegexpMatchMedium_1K-4   23.2MB/s ± 4%  23.4MB/s ± 3%    ~     (p=0.651 n=30+30)
RegexpMatchHard_32-4     14.2MB/s ± 4%  14.3MB/s ± 4%  +1.29%  (p=0.021 n=30+30)
RegexpMatchHard_1K-4     15.0MB/s ± 3%  14.9MB/s ± 4%    ~     (p=0.069 n=30+29)
Revcomp-4                 138MB/s ± 2%   138MB/s ± 2%    ~     (p=0.072 n=30+30)
Template-4               28.1MB/s ± 3%  28.4MB/s ± 3%  +1.05%  (p=0.012 n=30+30)
[Geo mean]               79.7MB/s       80.2MB/s       +0.60%

Change-Id: I44a1dfc942c9a385904553c4fe1fa8e509c8aa31
Reviewed-on: https://go-review.googlesource.com/120916
Run-TryBot: Ben Shi <powerman1st@163.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Ben Shi 2018-06-26 02:58:54 +00:00
parent de16b32233
commit a0a7e9fc0c
6 changed files with 505 additions and 1 deletions

View File

@ -644,6 +644,8 @@
((ADD|SUB|MUL|DIV)SDload [off1+off2] {sym} val base mem)
((ADD|SUB|AND|OR|XOR)Lmodify [off1] {sym} (ADDLconst [off2] base) val mem) && is32Bit(off1+off2) ->
((ADD|SUB|AND|OR|XOR)Lmodify [off1+off2] {sym} base val mem)
((ADD|AND|OR|XOR)Lconstmodify [valoff1] {sym} (ADDLconst [off2] base) mem) && ValAndOff(valoff1).canAdd(off2) ->
((ADD|AND|OR|XOR)Lconstmodify [ValAndOff(valoff1).add(off2)] {sym} base mem)
// Fold constants into stores.
(MOVLstore [off] {sym} ptr (MOVLconst [c]) mem) && validOff(off) ->
@ -769,6 +771,9 @@
((ADD|SUB|AND|OR|XOR)Lmodify [off1] {sym1} (LEAL [off2] {sym2} base) val mem)
&& is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) ->
((ADD|SUB|AND|OR|XOR)Lmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
((ADD|AND|OR|XOR)Lconstmodify [valoff1] {sym1} (LEAL [off2] {sym2} base) mem)
&& ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) ->
((ADD|AND|OR|XOR)Lconstmodify [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base mem)
(MOVBload [off] {sym} (ADDL ptr idx) mem) && ptr.Op != OpSB -> (MOVBloadidx1 [off] {sym} ptr idx mem)
(MOVWload [off] {sym} (ADDL ptr idx) mem) && ptr.Op != OpSB -> (MOVWloadidx1 [off] {sym} ptr idx mem)
@ -852,6 +857,9 @@
(MOVLstore {sym} [off] ptr y:((ADD|AND|OR|XOR)Lload x [off] {sym} ptr mem) mem) && y.Uses==1 && clobber(y) -> ((ADD|AND|OR|XOR)Lmodify [off] {sym} ptr x mem)
(MOVLstore {sym} [off] ptr y:((ADD|SUB|AND|OR|XOR)L l:(MOVLload [off] {sym} ptr mem) x) mem) && y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l) ->
((ADD|SUB|AND|OR|XOR)Lmodify [off] {sym} ptr x mem)
(MOVLstore {sym} [off] ptr y:((ADD|AND|OR|XOR)Lconst [c] l:(MOVLload [off] {sym} ptr mem)) mem)
&& y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l) && validValAndOff(c,off) ->
((ADD|AND|OR|XOR)Lconstmodify [makeValAndOff(c,off)] {sym} ptr mem)
(MOVBstoreconstidx1 [x] {sym} (ADDLconst [c] ptr) idx mem) ->
(MOVBstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem)

View File

@ -367,6 +367,12 @@ func init() {
{name: "ORLmodify", argLength: 3, reg: gpstore, asm: "ORL", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+auxint+aux) |= arg1, arg2=mem
{name: "XORLmodify", argLength: 3, reg: gpstore, asm: "XORL", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, clobberFlags: true, symEffect: "Read,Write"}, // *(arg0+auxint+aux) ^= arg1, arg2=mem
// direct binary-op on memory with a constant (read-modify-write)
{name: "ADDLconstmodify", argLength: 2, reg: gpstoreconst, asm: "ADDL", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // add ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
{name: "ANDLconstmodify", argLength: 2, reg: gpstoreconst, asm: "ANDL", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // and ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
{name: "ORLconstmodify", argLength: 2, reg: gpstoreconst, asm: "ORL", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // or ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
{name: "XORLconstmodify", argLength: 2, reg: gpstoreconst, asm: "XORL", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read,Write"}, // xor ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux, arg1=mem
// indexed loads/stores
{name: "MOVBloadidx1", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVBLZX", aux: "SymOff", symEffect: "Read"}, // load a byte from arg0+arg1+auxint+aux. arg2=mem
{name: "MOVWloadidx1", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVWLZX", aux: "SymOff", symEffect: "Read"}, // load 2 bytes from arg0+arg1+auxint+aux. arg2=mem

View File

@ -394,6 +394,10 @@ const (
Op386ANDLmodify
Op386ORLmodify
Op386XORLmodify
Op386ADDLconstmodify
Op386ANDLconstmodify
Op386ORLconstmodify
Op386XORLconstmodify
Op386MOVBloadidx1
Op386MOVWloadidx1
Op386MOVWloadidx2
@ -4660,6 +4664,62 @@ var opcodeTable = [...]opInfo{
},
},
},
{
name: "ADDLconstmodify",
auxType: auxSymValAndOff,
argLen: 2,
clobberFlags: true,
faultOnNilArg0: true,
symEffect: SymRead | SymWrite,
asm: x86.AADDL,
reg: regInfo{
inputs: []inputInfo{
{0, 65791}, // AX CX DX BX SP BP SI DI SB
},
},
},
{
name: "ANDLconstmodify",
auxType: auxSymValAndOff,
argLen: 2,
clobberFlags: true,
faultOnNilArg0: true,
symEffect: SymRead | SymWrite,
asm: x86.AANDL,
reg: regInfo{
inputs: []inputInfo{
{0, 65791}, // AX CX DX BX SP BP SI DI SB
},
},
},
{
name: "ORLconstmodify",
auxType: auxSymValAndOff,
argLen: 2,
clobberFlags: true,
faultOnNilArg0: true,
symEffect: SymRead | SymWrite,
asm: x86.AORL,
reg: regInfo{
inputs: []inputInfo{
{0, 65791}, // AX CX DX BX SP BP SI DI SB
},
},
},
{
name: "XORLconstmodify",
auxType: auxSymValAndOff,
argLen: 2,
clobberFlags: true,
faultOnNilArg0: true,
symEffect: SymRead | SymWrite,
asm: x86.AXORL,
reg: regInfo{
inputs: []inputInfo{
{0, 65791}, // AX CX DX BX SP BP SI DI SB
},
},
},
{
name: "MOVBloadidx1",
auxType: auxSymOff,

View File

@ -23,6 +23,8 @@ func rewriteValue386(v *Value) bool {
return rewriteValue386_Op386ADDLcarry_0(v)
case Op386ADDLconst:
return rewriteValue386_Op386ADDLconst_0(v)
case Op386ADDLconstmodify:
return rewriteValue386_Op386ADDLconstmodify_0(v)
case Op386ADDLload:
return rewriteValue386_Op386ADDLload_0(v)
case Op386ADDLmodify:
@ -39,6 +41,8 @@ func rewriteValue386(v *Value) bool {
return rewriteValue386_Op386ANDL_0(v)
case Op386ANDLconst:
return rewriteValue386_Op386ANDLconst_0(v)
case Op386ANDLconstmodify:
return rewriteValue386_Op386ANDLconstmodify_0(v)
case Op386ANDLload:
return rewriteValue386_Op386ANDLload_0(v)
case Op386ANDLmodify:
@ -104,7 +108,7 @@ func rewriteValue386(v *Value) bool {
case Op386MOVLloadidx4:
return rewriteValue386_Op386MOVLloadidx4_0(v)
case Op386MOVLstore:
return rewriteValue386_Op386MOVLstore_0(v) || rewriteValue386_Op386MOVLstore_10(v)
return rewriteValue386_Op386MOVLstore_0(v) || rewriteValue386_Op386MOVLstore_10(v) || rewriteValue386_Op386MOVLstore_20(v)
case Op386MOVLstoreconst:
return rewriteValue386_Op386MOVLstoreconst_0(v)
case Op386MOVLstoreconstidx1:
@ -189,6 +193,8 @@ func rewriteValue386(v *Value) bool {
return rewriteValue386_Op386ORL_0(v) || rewriteValue386_Op386ORL_10(v) || rewriteValue386_Op386ORL_20(v) || rewriteValue386_Op386ORL_30(v) || rewriteValue386_Op386ORL_40(v) || rewriteValue386_Op386ORL_50(v)
case Op386ORLconst:
return rewriteValue386_Op386ORLconst_0(v)
case Op386ORLconstmodify:
return rewriteValue386_Op386ORLconstmodify_0(v)
case Op386ORLload:
return rewriteValue386_Op386ORLload_0(v)
case Op386ORLmodify:
@ -273,6 +279,8 @@ func rewriteValue386(v *Value) bool {
return rewriteValue386_Op386XORL_0(v) || rewriteValue386_Op386XORL_10(v)
case Op386XORLconst:
return rewriteValue386_Op386XORLconst_0(v)
case Op386XORLconstmodify:
return rewriteValue386_Op386XORLconstmodify_0(v)
case Op386XORLload:
return rewriteValue386_Op386XORLload_0(v)
case Op386XORLmodify:
@ -1557,6 +1565,62 @@ func rewriteValue386_Op386ADDLconst_0(v *Value) bool {
}
return false
}
func rewriteValue386_Op386ADDLconstmodify_0(v *Value) bool {
b := v.Block
_ = b
config := b.Func.Config
_ = config
// match: (ADDLconstmodify [valoff1] {sym} (ADDLconst [off2] base) mem)
// cond: ValAndOff(valoff1).canAdd(off2)
// result: (ADDLconstmodify [ValAndOff(valoff1).add(off2)] {sym} base mem)
for {
valoff1 := v.AuxInt
sym := v.Aux
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != Op386ADDLconst {
break
}
off2 := v_0.AuxInt
base := v_0.Args[0]
mem := v.Args[1]
if !(ValAndOff(valoff1).canAdd(off2)) {
break
}
v.reset(Op386ADDLconstmodify)
v.AuxInt = ValAndOff(valoff1).add(off2)
v.Aux = sym
v.AddArg(base)
v.AddArg(mem)
return true
}
// match: (ADDLconstmodify [valoff1] {sym1} (LEAL [off2] {sym2} base) mem)
// cond: ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
// result: (ADDLconstmodify [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base mem)
for {
valoff1 := v.AuxInt
sym1 := v.Aux
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != Op386LEAL {
break
}
off2 := v_0.AuxInt
sym2 := v_0.Aux
base := v_0.Args[0]
mem := v.Args[1]
if !(ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
break
}
v.reset(Op386ADDLconstmodify)
v.AuxInt = ValAndOff(valoff1).add(off2)
v.Aux = mergeSym(sym1, sym2)
v.AddArg(base)
v.AddArg(mem)
return true
}
return false
}
func rewriteValue386_Op386ADDLload_0(v *Value) bool {
b := v.Block
_ = b
@ -2075,6 +2139,62 @@ func rewriteValue386_Op386ANDLconst_0(v *Value) bool {
}
return false
}
func rewriteValue386_Op386ANDLconstmodify_0(v *Value) bool {
b := v.Block
_ = b
config := b.Func.Config
_ = config
// match: (ANDLconstmodify [valoff1] {sym} (ADDLconst [off2] base) mem)
// cond: ValAndOff(valoff1).canAdd(off2)
// result: (ANDLconstmodify [ValAndOff(valoff1).add(off2)] {sym} base mem)
for {
valoff1 := v.AuxInt
sym := v.Aux
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != Op386ADDLconst {
break
}
off2 := v_0.AuxInt
base := v_0.Args[0]
mem := v.Args[1]
if !(ValAndOff(valoff1).canAdd(off2)) {
break
}
v.reset(Op386ANDLconstmodify)
v.AuxInt = ValAndOff(valoff1).add(off2)
v.Aux = sym
v.AddArg(base)
v.AddArg(mem)
return true
}
// match: (ANDLconstmodify [valoff1] {sym1} (LEAL [off2] {sym2} base) mem)
// cond: ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
// result: (ANDLconstmodify [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base mem)
for {
valoff1 := v.AuxInt
sym1 := v.Aux
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != Op386LEAL {
break
}
off2 := v_0.AuxInt
sym2 := v_0.Aux
base := v_0.Args[0]
mem := v.Args[1]
if !(ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
break
}
v.reset(Op386ANDLconstmodify)
v.AuxInt = ValAndOff(valoff1).add(off2)
v.Aux = mergeSym(sym1, sym2)
v.AddArg(base)
v.AddArg(mem)
return true
}
return false
}
func rewriteValue386_Op386ANDLload_0(v *Value) bool {
b := v.Block
_ = b
@ -6506,6 +6626,173 @@ func rewriteValue386_Op386MOVLstore_10(v *Value) bool {
v.AddArg(mem)
return true
}
// match: (MOVLstore {sym} [off] ptr y:(ADDLconst [c] l:(MOVLload [off] {sym} ptr mem)) mem)
// cond: y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l) && validValAndOff(c,off)
// result: (ADDLconstmodify [makeValAndOff(c,off)] {sym} ptr mem)
for {
off := v.AuxInt
sym := v.Aux
_ = v.Args[2]
ptr := v.Args[0]
y := v.Args[1]
if y.Op != Op386ADDLconst {
break
}
c := y.AuxInt
l := y.Args[0]
if l.Op != Op386MOVLload {
break
}
if l.AuxInt != off {
break
}
if l.Aux != sym {
break
}
_ = l.Args[1]
if ptr != l.Args[0] {
break
}
mem := l.Args[1]
if mem != v.Args[2] {
break
}
if !(y.Uses == 1 && l.Uses == 1 && clobber(y) && clobber(l) && validValAndOff(c, off)) {
break
}
v.reset(Op386ADDLconstmodify)
v.AuxInt = makeValAndOff(c, off)
v.Aux = sym
v.AddArg(ptr)
v.AddArg(mem)
return true
}
return false
}
func rewriteValue386_Op386MOVLstore_20(v *Value) bool {
// match: (MOVLstore {sym} [off] ptr y:(ANDLconst [c] l:(MOVLload [off] {sym} ptr mem)) mem)
// cond: y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l) && validValAndOff(c,off)
// result: (ANDLconstmodify [makeValAndOff(c,off)] {sym} ptr mem)
for {
off := v.AuxInt
sym := v.Aux
_ = v.Args[2]
ptr := v.Args[0]
y := v.Args[1]
if y.Op != Op386ANDLconst {
break
}
c := y.AuxInt
l := y.Args[0]
if l.Op != Op386MOVLload {
break
}
if l.AuxInt != off {
break
}
if l.Aux != sym {
break
}
_ = l.Args[1]
if ptr != l.Args[0] {
break
}
mem := l.Args[1]
if mem != v.Args[2] {
break
}
if !(y.Uses == 1 && l.Uses == 1 && clobber(y) && clobber(l) && validValAndOff(c, off)) {
break
}
v.reset(Op386ANDLconstmodify)
v.AuxInt = makeValAndOff(c, off)
v.Aux = sym
v.AddArg(ptr)
v.AddArg(mem)
return true
}
// match: (MOVLstore {sym} [off] ptr y:(ORLconst [c] l:(MOVLload [off] {sym} ptr mem)) mem)
// cond: y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l) && validValAndOff(c,off)
// result: (ORLconstmodify [makeValAndOff(c,off)] {sym} ptr mem)
for {
off := v.AuxInt
sym := v.Aux
_ = v.Args[2]
ptr := v.Args[0]
y := v.Args[1]
if y.Op != Op386ORLconst {
break
}
c := y.AuxInt
l := y.Args[0]
if l.Op != Op386MOVLload {
break
}
if l.AuxInt != off {
break
}
if l.Aux != sym {
break
}
_ = l.Args[1]
if ptr != l.Args[0] {
break
}
mem := l.Args[1]
if mem != v.Args[2] {
break
}
if !(y.Uses == 1 && l.Uses == 1 && clobber(y) && clobber(l) && validValAndOff(c, off)) {
break
}
v.reset(Op386ORLconstmodify)
v.AuxInt = makeValAndOff(c, off)
v.Aux = sym
v.AddArg(ptr)
v.AddArg(mem)
return true
}
// match: (MOVLstore {sym} [off] ptr y:(XORLconst [c] l:(MOVLload [off] {sym} ptr mem)) mem)
// cond: y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l) && validValAndOff(c,off)
// result: (XORLconstmodify [makeValAndOff(c,off)] {sym} ptr mem)
for {
off := v.AuxInt
sym := v.Aux
_ = v.Args[2]
ptr := v.Args[0]
y := v.Args[1]
if y.Op != Op386XORLconst {
break
}
c := y.AuxInt
l := y.Args[0]
if l.Op != Op386MOVLload {
break
}
if l.AuxInt != off {
break
}
if l.Aux != sym {
break
}
_ = l.Args[1]
if ptr != l.Args[0] {
break
}
mem := l.Args[1]
if mem != v.Args[2] {
break
}
if !(y.Uses == 1 && l.Uses == 1 && clobber(y) && clobber(l) && validValAndOff(c, off)) {
break
}
v.reset(Op386XORLconstmodify)
v.AuxInt = makeValAndOff(c, off)
v.Aux = sym
v.AddArg(ptr)
v.AddArg(mem)
return true
}
return false
}
func rewriteValue386_Op386MOVLstoreconst_0(v *Value) bool {
@ -14769,6 +15056,62 @@ func rewriteValue386_Op386ORLconst_0(v *Value) bool {
}
return false
}
func rewriteValue386_Op386ORLconstmodify_0(v *Value) bool {
b := v.Block
_ = b
config := b.Func.Config
_ = config
// match: (ORLconstmodify [valoff1] {sym} (ADDLconst [off2] base) mem)
// cond: ValAndOff(valoff1).canAdd(off2)
// result: (ORLconstmodify [ValAndOff(valoff1).add(off2)] {sym} base mem)
for {
valoff1 := v.AuxInt
sym := v.Aux
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != Op386ADDLconst {
break
}
off2 := v_0.AuxInt
base := v_0.Args[0]
mem := v.Args[1]
if !(ValAndOff(valoff1).canAdd(off2)) {
break
}
v.reset(Op386ORLconstmodify)
v.AuxInt = ValAndOff(valoff1).add(off2)
v.Aux = sym
v.AddArg(base)
v.AddArg(mem)
return true
}
// match: (ORLconstmodify [valoff1] {sym1} (LEAL [off2] {sym2} base) mem)
// cond: ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
// result: (ORLconstmodify [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base mem)
for {
valoff1 := v.AuxInt
sym1 := v.Aux
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != Op386LEAL {
break
}
off2 := v_0.AuxInt
sym2 := v_0.Aux
base := v_0.Args[0]
mem := v.Args[1]
if !(ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
break
}
v.reset(Op386ORLconstmodify)
v.AuxInt = ValAndOff(valoff1).add(off2)
v.Aux = mergeSym(sym1, sym2)
v.AddArg(base)
v.AddArg(mem)
return true
}
return false
}
func rewriteValue386_Op386ORLload_0(v *Value) bool {
b := v.Block
_ = b
@ -16959,6 +17302,62 @@ func rewriteValue386_Op386XORLconst_0(v *Value) bool {
}
return false
}
func rewriteValue386_Op386XORLconstmodify_0(v *Value) bool {
b := v.Block
_ = b
config := b.Func.Config
_ = config
// match: (XORLconstmodify [valoff1] {sym} (ADDLconst [off2] base) mem)
// cond: ValAndOff(valoff1).canAdd(off2)
// result: (XORLconstmodify [ValAndOff(valoff1).add(off2)] {sym} base mem)
for {
valoff1 := v.AuxInt
sym := v.Aux
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != Op386ADDLconst {
break
}
off2 := v_0.AuxInt
base := v_0.Args[0]
mem := v.Args[1]
if !(ValAndOff(valoff1).canAdd(off2)) {
break
}
v.reset(Op386XORLconstmodify)
v.AuxInt = ValAndOff(valoff1).add(off2)
v.Aux = sym
v.AddArg(base)
v.AddArg(mem)
return true
}
// match: (XORLconstmodify [valoff1] {sym1} (LEAL [off2] {sym2} base) mem)
// cond: ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
// result: (XORLconstmodify [ValAndOff(valoff1).add(off2)] {mergeSym(sym1,sym2)} base mem)
for {
valoff1 := v.AuxInt
sym1 := v.Aux
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != Op386LEAL {
break
}
off2 := v_0.AuxInt
sym2 := v_0.Aux
base := v_0.Args[0]
mem := v.Args[1]
if !(ValAndOff(valoff1).canAdd(off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
break
}
v.reset(Op386XORLconstmodify)
v.AuxInt = ValAndOff(valoff1).add(off2)
v.Aux = mergeSym(sym1, sym2)
v.AddArg(base)
v.AddArg(mem)
return true
}
return false
}
func rewriteValue386_Op386XORLload_0(v *Value) bool {
b := v.Block
_ = b

View File

@ -546,6 +546,33 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.To.Type = obj.TYPE_MEM
p.To.Reg = v.Args[0].Reg()
gc.AddAux(&p.To, v)
case ssa.Op386ADDLconstmodify:
var p *obj.Prog = nil
sc := v.AuxValAndOff()
off := sc.Off()
val := sc.Val()
if val == 1 {
p = s.Prog(x86.AINCL)
} else if val == -1 {
p = s.Prog(x86.ADECL)
} else {
p = s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_CONST
p.From.Offset = val
}
p.To.Type = obj.TYPE_MEM
p.To.Reg = v.Args[0].Reg()
gc.AddAux2(&p.To, v, off)
case ssa.Op386ANDLconstmodify, ssa.Op386ORLconstmodify, ssa.Op386XORLconstmodify:
sc := v.AuxValAndOff()
off := sc.Off()
val := sc.Val()
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_CONST
p.From.Offset = val
p.To.Type = obj.TYPE_MEM
p.To.Reg = v.Args[0].Reg()
gc.AddAux2(&p.To, v, off)
case ssa.Op386MOVSDstoreidx8:
p := s.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG

View File

@ -19,6 +19,10 @@ func SubMem(arr []int, b int) int {
arr[2] -= b
// 386:`SUBL\s[A-Z]+,\s12\([A-Z]+\)`
arr[3] -= b
// 386:`DECL\s16\([A-Z]+\)`
arr[4]--
// 386:`ADDL\s[$]-20,\s20\([A-Z]+\)`
arr[5] -= 20
// 386:"SUBL\t4"
// amd64:"SUBQ\t8"
return arr[0] - arr[1]