mirror of
https://github.com/golang/go
synced 2024-11-11 21:20:21 -07:00
cmd/compile: emit more compact 386 instructions
ADDL/SUBL/ANDL/ORL/XORL can have a memory operand as destination, and this CL optimize the compiler to emit such instructions on 386 for more compact binary. Here is test report: 1. The total size of pkg/linux_386/ and pkg/tool/linux_386/ decreases about 14KB. (pkg/linux_386/cmd/compile/ and pkg/tool/linux_386/compile are excluded) 2. The go1 benchmark shows little change, excluding ±2% noise. name old time/op new time/op delta BinaryTree17-4 3.34s ± 2% 3.38s ± 2% +1.27% (p=0.000 n=40+39) Fannkuch11-4 3.55s ± 1% 3.51s ± 1% -1.33% (p=0.000 n=40+40) FmtFprintfEmpty-4 46.3ns ± 3% 46.9ns ± 4% +1.41% (p=0.002 n=40+40) FmtFprintfString-4 80.8ns ± 3% 80.4ns ± 6% -0.54% (p=0.044 n=40+40) FmtFprintfInt-4 93.0ns ± 3% 92.2ns ± 4% -0.88% (p=0.007 n=39+40) FmtFprintfIntInt-4 144ns ± 5% 145ns ± 2% +0.78% (p=0.015 n=40+40) FmtFprintfPrefixedInt-4 184ns ± 2% 182ns ± 2% -1.06% (p=0.004 n=40+40) FmtFprintfFloat-4 415ns ± 4% 419ns ± 4% ~ (p=0.434 n=40+40) FmtManyArgs-4 615ns ± 3% 619ns ± 3% ~ (p=0.100 n=40+40) GobDecode-4 7.30ms ± 6% 7.36ms ± 6% ~ (p=0.074 n=40+40) GobEncode-4 7.10ms ± 6% 7.21ms ± 5% ~ (p=0.082 n=40+39) Gzip-4 364ms ± 3% 362ms ± 6% -0.71% (p=0.020 n=40+40) Gunzip-4 42.4ms ± 3% 42.2ms ± 3% ~ (p=0.303 n=40+40) HTTPClientServer-4 62.9µs ± 1% 62.9µs ± 1% ~ (p=0.768 n=38+39) JSONEncode-4 21.4ms ± 4% 21.5ms ± 5% ~ (p=0.210 n=40+40) JSONDecode-4 67.7ms ± 3% 67.9ms ± 4% ~ (p=0.713 n=40+40) Mandelbrot200-4 5.18ms ± 3% 5.21ms ± 3% +0.59% (p=0.021 n=40+40) GoParse-4 3.35ms ± 3% 3.34ms ± 2% ~ (p=0.996 n=40+40) RegexpMatchEasy0_32-4 98.5ns ± 5% 96.3ns ± 4% -2.15% (p=0.001 n=40+40) RegexpMatchEasy0_1K-4 851ns ± 4% 850ns ± 5% ~ (p=0.700 n=40+40) RegexpMatchEasy1_32-4 105ns ± 7% 107ns ± 4% +1.50% (p=0.017 n=40+40) RegexpMatchEasy1_1K-4 1.03µs ± 5% 1.03µs ± 4% ~ (p=0.992 n=40+40) RegexpMatchMedium_32-4 130ns ± 6% 128ns ± 4% -1.66% (p=0.012 n=40+40) RegexpMatchMedium_1K-4 44.0µs ± 5% 43.6µs ± 3% ~ (p=0.704 n=40+40) RegexpMatchHard_32-4 2.29µs ± 3% 2.23µs ± 4% -2.38% (p=0.000 n=40+40) RegexpMatchHard_1K-4 69.0µs ± 3% 68.1µs ± 3% -1.28% (p=0.003 n=40+40) Revcomp-4 1.85s ± 2% 1.87s ± 3% +1.11% (p=0.000 n=40+40) Template-4 69.8ms ± 3% 69.6ms ± 3% ~ (p=0.125 n=40+40) TimeParse-4 442ns ± 5% 440ns ± 3% ~ (p=0.585 n=40+40) TimeFormat-4 419ns ± 3% 420ns ± 3% ~ (p=0.824 n=40+40) [Geo mean] 67.3µs 67.2µs -0.11% name old speed new speed delta GobDecode-4 105MB/s ± 6% 104MB/s ± 6% ~ (p=0.074 n=40+40) GobEncode-4 108MB/s ± 7% 107MB/s ± 5% ~ (p=0.080 n=40+39) Gzip-4 53.3MB/s ± 3% 53.7MB/s ± 6% +0.73% (p=0.021 n=40+40) Gunzip-4 458MB/s ± 3% 460MB/s ± 3% ~ (p=0.301 n=40+40) JSONEncode-4 90.8MB/s ± 4% 90.3MB/s ± 4% ~ (p=0.213 n=40+40) JSONDecode-4 28.7MB/s ± 3% 28.6MB/s ± 4% ~ (p=0.679 n=40+40) GoParse-4 17.3MB/s ± 3% 17.3MB/s ± 2% ~ (p=1.000 n=40+40) RegexpMatchEasy0_32-4 325MB/s ± 5% 333MB/s ± 4% +2.44% (p=0.000 n=40+38) RegexpMatchEasy0_1K-4 1.20GB/s ± 4% 1.21GB/s ± 5% ~ (p=0.684 n=40+40) RegexpMatchEasy1_32-4 303MB/s ± 7% 298MB/s ± 4% -1.52% (p=0.022 n=40+40) RegexpMatchEasy1_1K-4 995MB/s ± 5% 996MB/s ± 4% ~ (p=0.996 n=40+40) RegexpMatchMedium_32-4 7.67MB/s ± 6% 7.80MB/s ± 4% +1.68% (p=0.011 n=40+40) RegexpMatchMedium_1K-4 23.3MB/s ± 5% 23.5MB/s ± 3% ~ (p=0.697 n=40+40) RegexpMatchHard_32-4 14.0MB/s ± 3% 14.3MB/s ± 4% +2.43% (p=0.000 n=40+40) RegexpMatchHard_1K-4 14.8MB/s ± 3% 15.0MB/s ± 3% +1.30% (p=0.003 n=40+40) Revcomp-4 137MB/s ± 2% 136MB/s ± 3% -1.10% (p=0.000 n=40+40) Template-4 27.8MB/s ± 3% 27.9MB/s ± 3% ~ (p=0.128 n=40+40) [Geo mean] 79.6MB/s 79.9MB/s +0.28% Change-Id: I02a3efc125dc81e18fc8495eb2bf1bba59ab8733 Reviewed-on: https://go-review.googlesource.com/110157 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Ilya Tocar <ilya.tocar@intel.com>
This commit is contained in:
parent
c8915a0696
commit
098ca846c7
@ -641,6 +641,8 @@
|
||||
((ADD|SUB|MUL)SSmem [off1+off2] {sym} val base mem)
|
||||
((ADD|SUB|MUL)SDmem [off1] {sym} val (ADDLconst [off2] base) mem) && is32Bit(off1+off2) ->
|
||||
((ADD|SUB|MUL)SDmem [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)
|
||||
|
||||
// Fold constants into stores.
|
||||
(MOVLstore [off] {sym} ptr (MOVLconst [c]) mem) && validOff(off) ->
|
||||
@ -763,6 +765,9 @@
|
||||
((ADD|SUB|MUL)SDmem [off1] {sym1} val (LEAL [off2] {sym2} base) mem)
|
||||
&& is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared) ->
|
||||
((ADD|SUB|MUL)SDmem [off1+off2] {mergeSym(sym1,sym2)} val base mem)
|
||||
((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)
|
||||
|
||||
(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)
|
||||
@ -839,10 +844,13 @@
|
||||
(MOVSDstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSDstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
(MOVSDstoreidx8 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSDstoreidx8 [int64(int32(c+8*d))] {sym} ptr idx val mem)
|
||||
|
||||
// Merge load to op
|
||||
// Merge load/store to op
|
||||
((ADD|AND|OR|XOR|SUB)L x l:(MOVLload [off] {sym} ptr mem)) && canMergeLoad(v, l, x) && clobber(l) -> ((ADD|AND|OR|XOR|SUB)Lmem x [off] {sym} ptr mem)
|
||||
((ADD|SUB|MUL)SD x l:(MOVSDload [off] {sym} ptr mem)) && canMergeLoad(v, l, x) && !config.use387 && clobber(l) -> ((ADD|SUB|MUL)SDmem x [off] {sym} ptr mem)
|
||||
((ADD|SUB|MUL)SS x l:(MOVSSload [off] {sym} ptr mem)) && canMergeLoad(v, l, x) && !config.use387 && clobber(l) -> ((ADD|SUB|MUL)SSmem x [off] {sym} ptr mem)
|
||||
(MOVLstore {sym} [off] ptr y:((ADD|AND|OR|XOR)Lmem 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)
|
||||
|
||||
(MOVBstoreconstidx1 [x] {sym} (ADDLconst [c] ptr) idx mem) ->
|
||||
(MOVBstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem)
|
||||
|
@ -345,6 +345,13 @@ func init() {
|
||||
{name: "MOVWstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes in arg1 to arg0+auxint+aux. arg2=mem
|
||||
{name: "MOVLstore", argLength: 3, reg: gpstore, asm: "MOVL", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem
|
||||
|
||||
// direct binary-op on memory (read-modify-write)
|
||||
{name: "ADDLmodify", argLength: 3, reg: gpstore, asm: "ADDL", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // *(arg0+auxint+aux) += arg1, arg2=mem
|
||||
{name: "SUBLmodify", argLength: 3, reg: gpstore, asm: "SUBL", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // *(arg0+auxint+aux) -= arg1, arg2=mem
|
||||
{name: "ANDLmodify", argLength: 3, reg: gpstore, asm: "ANDL", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // *(arg0+auxint+aux) &= arg1, arg2=mem
|
||||
{name: "ORLmodify", argLength: 3, reg: gpstore, asm: "ORL", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // *(arg0+auxint+aux) |= arg1, arg2=mem
|
||||
{name: "XORLmodify", argLength: 3, reg: gpstore, asm: "XORL", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // *(arg0+auxint+aux) ^= arg1, arg2=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
|
||||
|
@ -380,6 +380,11 @@ const (
|
||||
Op386MOVBstore
|
||||
Op386MOVWstore
|
||||
Op386MOVLstore
|
||||
Op386ADDLmodify
|
||||
Op386SUBLmodify
|
||||
Op386ANDLmodify
|
||||
Op386ORLmodify
|
||||
Op386XORLmodify
|
||||
Op386MOVBloadidx1
|
||||
Op386MOVWloadidx1
|
||||
Op386MOVWloadidx2
|
||||
@ -4418,6 +4423,76 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ADDLmodify",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymWrite,
|
||||
asm: x86.AADDL,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 255}, // AX CX DX BX SP BP SI DI
|
||||
{0, 65791}, // AX CX DX BX SP BP SI DI SB
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "SUBLmodify",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymWrite,
|
||||
asm: x86.ASUBL,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 255}, // AX CX DX BX SP BP SI DI
|
||||
{0, 65791}, // AX CX DX BX SP BP SI DI SB
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ANDLmodify",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymWrite,
|
||||
asm: x86.AANDL,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 255}, // AX CX DX BX SP BP SI DI
|
||||
{0, 65791}, // AX CX DX BX SP BP SI DI SB
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ORLmodify",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymWrite,
|
||||
asm: x86.AORL,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 255}, // AX CX DX BX SP BP SI DI
|
||||
{0, 65791}, // AX CX DX BX SP BP SI DI SB
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "XORLmodify",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymWrite,
|
||||
asm: x86.AXORL,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 255}, // AX CX DX BX SP BP SI DI
|
||||
{0, 65791}, // AX CX DX BX SP BP SI DI SB
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVBloadidx1",
|
||||
auxType: auxSymOff,
|
||||
|
@ -25,6 +25,8 @@ func rewriteValue386(v *Value) bool {
|
||||
return rewriteValue386_Op386ADDLconst_0(v)
|
||||
case Op386ADDLmem:
|
||||
return rewriteValue386_Op386ADDLmem_0(v)
|
||||
case Op386ADDLmodify:
|
||||
return rewriteValue386_Op386ADDLmodify_0(v)
|
||||
case Op386ADDSD:
|
||||
return rewriteValue386_Op386ADDSD_0(v)
|
||||
case Op386ADDSDmem:
|
||||
@ -39,6 +41,8 @@ func rewriteValue386(v *Value) bool {
|
||||
return rewriteValue386_Op386ANDLconst_0(v)
|
||||
case Op386ANDLmem:
|
||||
return rewriteValue386_Op386ANDLmem_0(v)
|
||||
case Op386ANDLmodify:
|
||||
return rewriteValue386_Op386ANDLmodify_0(v)
|
||||
case Op386CMPB:
|
||||
return rewriteValue386_Op386CMPB_0(v)
|
||||
case Op386CMPBconst:
|
||||
@ -86,7 +90,7 @@ func rewriteValue386(v *Value) bool {
|
||||
case Op386MOVLloadidx4:
|
||||
return rewriteValue386_Op386MOVLloadidx4_0(v)
|
||||
case Op386MOVLstore:
|
||||
return rewriteValue386_Op386MOVLstore_0(v)
|
||||
return rewriteValue386_Op386MOVLstore_0(v) || rewriteValue386_Op386MOVLstore_10(v)
|
||||
case Op386MOVLstoreconst:
|
||||
return rewriteValue386_Op386MOVLstoreconst_0(v)
|
||||
case Op386MOVLstoreconstidx1:
|
||||
@ -171,6 +175,8 @@ func rewriteValue386(v *Value) bool {
|
||||
return rewriteValue386_Op386ORLconst_0(v)
|
||||
case Op386ORLmem:
|
||||
return rewriteValue386_Op386ORLmem_0(v)
|
||||
case Op386ORLmodify:
|
||||
return rewriteValue386_Op386ORLmodify_0(v)
|
||||
case Op386ROLBconst:
|
||||
return rewriteValue386_Op386ROLBconst_0(v)
|
||||
case Op386ROLLconst:
|
||||
@ -237,6 +243,8 @@ func rewriteValue386(v *Value) bool {
|
||||
return rewriteValue386_Op386SUBLconst_0(v)
|
||||
case Op386SUBLmem:
|
||||
return rewriteValue386_Op386SUBLmem_0(v)
|
||||
case Op386SUBLmodify:
|
||||
return rewriteValue386_Op386SUBLmodify_0(v)
|
||||
case Op386SUBSD:
|
||||
return rewriteValue386_Op386SUBSD_0(v)
|
||||
case Op386SUBSDmem:
|
||||
@ -251,6 +259,8 @@ func rewriteValue386(v *Value) bool {
|
||||
return rewriteValue386_Op386XORLconst_0(v)
|
||||
case Op386XORLmem:
|
||||
return rewriteValue386_Op386XORLmem_0(v)
|
||||
case Op386XORLmodify:
|
||||
return rewriteValue386_Op386XORLmodify_0(v)
|
||||
case OpAdd16:
|
||||
return rewriteValue386_OpAdd16_0(v)
|
||||
case OpAdd32:
|
||||
@ -1589,6 +1599,66 @@ func rewriteValue386_Op386ADDLmem_0(v *Value) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValue386_Op386ADDLmodify_0(v *Value) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
config := b.Func.Config
|
||||
_ = config
|
||||
// match: (ADDLmodify [off1] {sym} (ADDLconst [off2] base) val mem)
|
||||
// cond: is32Bit(off1+off2)
|
||||
// result: (ADDLmodify [off1+off2] {sym} base val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
sym := v.Aux
|
||||
_ = v.Args[2]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != Op386ADDLconst {
|
||||
break
|
||||
}
|
||||
off2 := v_0.AuxInt
|
||||
base := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !(is32Bit(off1 + off2)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386ADDLmodify)
|
||||
v.AuxInt = off1 + off2
|
||||
v.Aux = sym
|
||||
v.AddArg(base)
|
||||
v.AddArg(val)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
// match: (ADDLmodify [off1] {sym1} (LEAL [off2] {sym2} base) val mem)
|
||||
// cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
|
||||
// result: (ADDLmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
sym1 := v.Aux
|
||||
_ = v.Args[2]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != Op386LEAL {
|
||||
break
|
||||
}
|
||||
off2 := v_0.AuxInt
|
||||
sym2 := v_0.Aux
|
||||
base := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386ADDLmodify)
|
||||
v.AuxInt = off1 + off2
|
||||
v.Aux = mergeSym(sym1, sym2)
|
||||
v.AddArg(base)
|
||||
v.AddArg(val)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValue386_Op386ADDSD_0(v *Value) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
@ -2047,6 +2117,66 @@ func rewriteValue386_Op386ANDLmem_0(v *Value) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValue386_Op386ANDLmodify_0(v *Value) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
config := b.Func.Config
|
||||
_ = config
|
||||
// match: (ANDLmodify [off1] {sym} (ADDLconst [off2] base) val mem)
|
||||
// cond: is32Bit(off1+off2)
|
||||
// result: (ANDLmodify [off1+off2] {sym} base val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
sym := v.Aux
|
||||
_ = v.Args[2]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != Op386ADDLconst {
|
||||
break
|
||||
}
|
||||
off2 := v_0.AuxInt
|
||||
base := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !(is32Bit(off1 + off2)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386ANDLmodify)
|
||||
v.AuxInt = off1 + off2
|
||||
v.Aux = sym
|
||||
v.AddArg(base)
|
||||
v.AddArg(val)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
// match: (ANDLmodify [off1] {sym1} (LEAL [off2] {sym2} base) val mem)
|
||||
// cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
|
||||
// result: (ANDLmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
sym1 := v.Aux
|
||||
_ = v.Args[2]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != Op386LEAL {
|
||||
break
|
||||
}
|
||||
off2 := v_0.AuxInt
|
||||
sym2 := v_0.Aux
|
||||
base := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386ANDLmodify)
|
||||
v.AuxInt = off1 + off2
|
||||
v.Aux = mergeSym(sym1, sym2)
|
||||
v.AddArg(base)
|
||||
v.AddArg(val)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValue386_Op386CMPB_0(v *Value) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
@ -5297,6 +5427,548 @@ func rewriteValue386_Op386MOVLstore_0(v *Value) bool {
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
// match: (MOVLstore {sym} [off] ptr y:(ADDLmem x [off] {sym} ptr mem) mem)
|
||||
// cond: y.Uses==1 && clobber(y)
|
||||
// result: (ADDLmodify [off] {sym} ptr x mem)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
_ = v.Args[2]
|
||||
ptr := v.Args[0]
|
||||
y := v.Args[1]
|
||||
if y.Op != Op386ADDLmem {
|
||||
break
|
||||
}
|
||||
if y.AuxInt != off {
|
||||
break
|
||||
}
|
||||
if y.Aux != sym {
|
||||
break
|
||||
}
|
||||
_ = y.Args[2]
|
||||
x := y.Args[0]
|
||||
if ptr != y.Args[1] {
|
||||
break
|
||||
}
|
||||
mem := y.Args[2]
|
||||
if mem != v.Args[2] {
|
||||
break
|
||||
}
|
||||
if !(y.Uses == 1 && clobber(y)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386ADDLmodify)
|
||||
v.AuxInt = off
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(x)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
// match: (MOVLstore {sym} [off] ptr y:(ANDLmem x [off] {sym} ptr mem) mem)
|
||||
// cond: y.Uses==1 && clobber(y)
|
||||
// result: (ANDLmodify [off] {sym} ptr x mem)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
_ = v.Args[2]
|
||||
ptr := v.Args[0]
|
||||
y := v.Args[1]
|
||||
if y.Op != Op386ANDLmem {
|
||||
break
|
||||
}
|
||||
if y.AuxInt != off {
|
||||
break
|
||||
}
|
||||
if y.Aux != sym {
|
||||
break
|
||||
}
|
||||
_ = y.Args[2]
|
||||
x := y.Args[0]
|
||||
if ptr != y.Args[1] {
|
||||
break
|
||||
}
|
||||
mem := y.Args[2]
|
||||
if mem != v.Args[2] {
|
||||
break
|
||||
}
|
||||
if !(y.Uses == 1 && clobber(y)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386ANDLmodify)
|
||||
v.AuxInt = off
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(x)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
// match: (MOVLstore {sym} [off] ptr y:(ORLmem x [off] {sym} ptr mem) mem)
|
||||
// cond: y.Uses==1 && clobber(y)
|
||||
// result: (ORLmodify [off] {sym} ptr x mem)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
_ = v.Args[2]
|
||||
ptr := v.Args[0]
|
||||
y := v.Args[1]
|
||||
if y.Op != Op386ORLmem {
|
||||
break
|
||||
}
|
||||
if y.AuxInt != off {
|
||||
break
|
||||
}
|
||||
if y.Aux != sym {
|
||||
break
|
||||
}
|
||||
_ = y.Args[2]
|
||||
x := y.Args[0]
|
||||
if ptr != y.Args[1] {
|
||||
break
|
||||
}
|
||||
mem := y.Args[2]
|
||||
if mem != v.Args[2] {
|
||||
break
|
||||
}
|
||||
if !(y.Uses == 1 && clobber(y)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386ORLmodify)
|
||||
v.AuxInt = off
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(x)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
// match: (MOVLstore {sym} [off] ptr y:(XORLmem x [off] {sym} ptr mem) mem)
|
||||
// cond: y.Uses==1 && clobber(y)
|
||||
// result: (XORLmodify [off] {sym} ptr x mem)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
_ = v.Args[2]
|
||||
ptr := v.Args[0]
|
||||
y := v.Args[1]
|
||||
if y.Op != Op386XORLmem {
|
||||
break
|
||||
}
|
||||
if y.AuxInt != off {
|
||||
break
|
||||
}
|
||||
if y.Aux != sym {
|
||||
break
|
||||
}
|
||||
_ = y.Args[2]
|
||||
x := y.Args[0]
|
||||
if ptr != y.Args[1] {
|
||||
break
|
||||
}
|
||||
mem := y.Args[2]
|
||||
if mem != v.Args[2] {
|
||||
break
|
||||
}
|
||||
if !(y.Uses == 1 && clobber(y)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386XORLmodify)
|
||||
v.AuxInt = off
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(x)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValue386_Op386MOVLstore_10(v *Value) bool {
|
||||
// match: (MOVLstore {sym} [off] ptr y:(ADDL l:(MOVLload [off] {sym} ptr mem) x) mem)
|
||||
// cond: y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l)
|
||||
// result: (ADDLmodify [off] {sym} ptr x mem)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
_ = v.Args[2]
|
||||
ptr := v.Args[0]
|
||||
y := v.Args[1]
|
||||
if y.Op != Op386ADDL {
|
||||
break
|
||||
}
|
||||
_ = y.Args[1]
|
||||
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]
|
||||
x := y.Args[1]
|
||||
if mem != v.Args[2] {
|
||||
break
|
||||
}
|
||||
if !(y.Uses == 1 && l.Uses == 1 && clobber(y) && clobber(l)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386ADDLmodify)
|
||||
v.AuxInt = off
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(x)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
// match: (MOVLstore {sym} [off] ptr y:(ADDL x l:(MOVLload [off] {sym} ptr mem)) mem)
|
||||
// cond: y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l)
|
||||
// result: (ADDLmodify [off] {sym} ptr x mem)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
_ = v.Args[2]
|
||||
ptr := v.Args[0]
|
||||
y := v.Args[1]
|
||||
if y.Op != Op386ADDL {
|
||||
break
|
||||
}
|
||||
_ = y.Args[1]
|
||||
x := y.Args[0]
|
||||
l := y.Args[1]
|
||||
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)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386ADDLmodify)
|
||||
v.AuxInt = off
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(x)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
// match: (MOVLstore {sym} [off] ptr y:(SUBL l:(MOVLload [off] {sym} ptr mem) x) mem)
|
||||
// cond: y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l)
|
||||
// result: (SUBLmodify [off] {sym} ptr x mem)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
_ = v.Args[2]
|
||||
ptr := v.Args[0]
|
||||
y := v.Args[1]
|
||||
if y.Op != Op386SUBL {
|
||||
break
|
||||
}
|
||||
_ = y.Args[1]
|
||||
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]
|
||||
x := y.Args[1]
|
||||
if mem != v.Args[2] {
|
||||
break
|
||||
}
|
||||
if !(y.Uses == 1 && l.Uses == 1 && clobber(y) && clobber(l)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386SUBLmodify)
|
||||
v.AuxInt = off
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(x)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
// match: (MOVLstore {sym} [off] ptr y:(ANDL l:(MOVLload [off] {sym} ptr mem) x) mem)
|
||||
// cond: y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l)
|
||||
// result: (ANDLmodify [off] {sym} ptr x mem)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
_ = v.Args[2]
|
||||
ptr := v.Args[0]
|
||||
y := v.Args[1]
|
||||
if y.Op != Op386ANDL {
|
||||
break
|
||||
}
|
||||
_ = y.Args[1]
|
||||
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]
|
||||
x := y.Args[1]
|
||||
if mem != v.Args[2] {
|
||||
break
|
||||
}
|
||||
if !(y.Uses == 1 && l.Uses == 1 && clobber(y) && clobber(l)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386ANDLmodify)
|
||||
v.AuxInt = off
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(x)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
// match: (MOVLstore {sym} [off] ptr y:(ANDL x l:(MOVLload [off] {sym} ptr mem)) mem)
|
||||
// cond: y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l)
|
||||
// result: (ANDLmodify [off] {sym} ptr x mem)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
_ = v.Args[2]
|
||||
ptr := v.Args[0]
|
||||
y := v.Args[1]
|
||||
if y.Op != Op386ANDL {
|
||||
break
|
||||
}
|
||||
_ = y.Args[1]
|
||||
x := y.Args[0]
|
||||
l := y.Args[1]
|
||||
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)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386ANDLmodify)
|
||||
v.AuxInt = off
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(x)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
// match: (MOVLstore {sym} [off] ptr y:(ORL l:(MOVLload [off] {sym} ptr mem) x) mem)
|
||||
// cond: y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l)
|
||||
// result: (ORLmodify [off] {sym} ptr x mem)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
_ = v.Args[2]
|
||||
ptr := v.Args[0]
|
||||
y := v.Args[1]
|
||||
if y.Op != Op386ORL {
|
||||
break
|
||||
}
|
||||
_ = y.Args[1]
|
||||
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]
|
||||
x := y.Args[1]
|
||||
if mem != v.Args[2] {
|
||||
break
|
||||
}
|
||||
if !(y.Uses == 1 && l.Uses == 1 && clobber(y) && clobber(l)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386ORLmodify)
|
||||
v.AuxInt = off
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(x)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
// match: (MOVLstore {sym} [off] ptr y:(ORL x l:(MOVLload [off] {sym} ptr mem)) mem)
|
||||
// cond: y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l)
|
||||
// result: (ORLmodify [off] {sym} ptr x mem)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
_ = v.Args[2]
|
||||
ptr := v.Args[0]
|
||||
y := v.Args[1]
|
||||
if y.Op != Op386ORL {
|
||||
break
|
||||
}
|
||||
_ = y.Args[1]
|
||||
x := y.Args[0]
|
||||
l := y.Args[1]
|
||||
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)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386ORLmodify)
|
||||
v.AuxInt = off
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(x)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
// match: (MOVLstore {sym} [off] ptr y:(XORL l:(MOVLload [off] {sym} ptr mem) x) mem)
|
||||
// cond: y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l)
|
||||
// result: (XORLmodify [off] {sym} ptr x mem)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
_ = v.Args[2]
|
||||
ptr := v.Args[0]
|
||||
y := v.Args[1]
|
||||
if y.Op != Op386XORL {
|
||||
break
|
||||
}
|
||||
_ = y.Args[1]
|
||||
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]
|
||||
x := y.Args[1]
|
||||
if mem != v.Args[2] {
|
||||
break
|
||||
}
|
||||
if !(y.Uses == 1 && l.Uses == 1 && clobber(y) && clobber(l)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386XORLmodify)
|
||||
v.AuxInt = off
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(x)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
// match: (MOVLstore {sym} [off] ptr y:(XORL x l:(MOVLload [off] {sym} ptr mem)) mem)
|
||||
// cond: y.Uses==1 && l.Uses==1 && clobber(y) && clobber(l)
|
||||
// result: (XORLmodify [off] {sym} ptr x mem)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
_ = v.Args[2]
|
||||
ptr := v.Args[0]
|
||||
y := v.Args[1]
|
||||
if y.Op != Op386XORL {
|
||||
break
|
||||
}
|
||||
_ = y.Args[1]
|
||||
x := y.Args[0]
|
||||
l := y.Args[1]
|
||||
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)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386XORLmodify)
|
||||
v.AuxInt = off
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(x)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValue386_Op386MOVLstoreconst_0(v *Value) bool {
|
||||
@ -13508,6 +14180,66 @@ func rewriteValue386_Op386ORLmem_0(v *Value) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValue386_Op386ORLmodify_0(v *Value) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
config := b.Func.Config
|
||||
_ = config
|
||||
// match: (ORLmodify [off1] {sym} (ADDLconst [off2] base) val mem)
|
||||
// cond: is32Bit(off1+off2)
|
||||
// result: (ORLmodify [off1+off2] {sym} base val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
sym := v.Aux
|
||||
_ = v.Args[2]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != Op386ADDLconst {
|
||||
break
|
||||
}
|
||||
off2 := v_0.AuxInt
|
||||
base := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !(is32Bit(off1 + off2)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386ORLmodify)
|
||||
v.AuxInt = off1 + off2
|
||||
v.Aux = sym
|
||||
v.AddArg(base)
|
||||
v.AddArg(val)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
// match: (ORLmodify [off1] {sym1} (LEAL [off2] {sym2} base) val mem)
|
||||
// cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
|
||||
// result: (ORLmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
sym1 := v.Aux
|
||||
_ = v.Args[2]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != Op386LEAL {
|
||||
break
|
||||
}
|
||||
off2 := v_0.AuxInt
|
||||
sym2 := v_0.Aux
|
||||
base := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386ORLmodify)
|
||||
v.AuxInt = off1 + off2
|
||||
v.Aux = mergeSym(sym1, sym2)
|
||||
v.AddArg(base)
|
||||
v.AddArg(val)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValue386_Op386ROLBconst_0(v *Value) bool {
|
||||
// match: (ROLBconst [c] (ROLBconst [d] x))
|
||||
// cond:
|
||||
@ -15016,6 +15748,66 @@ func rewriteValue386_Op386SUBLmem_0(v *Value) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValue386_Op386SUBLmodify_0(v *Value) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
config := b.Func.Config
|
||||
_ = config
|
||||
// match: (SUBLmodify [off1] {sym} (ADDLconst [off2] base) val mem)
|
||||
// cond: is32Bit(off1+off2)
|
||||
// result: (SUBLmodify [off1+off2] {sym} base val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
sym := v.Aux
|
||||
_ = v.Args[2]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != Op386ADDLconst {
|
||||
break
|
||||
}
|
||||
off2 := v_0.AuxInt
|
||||
base := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !(is32Bit(off1 + off2)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386SUBLmodify)
|
||||
v.AuxInt = off1 + off2
|
||||
v.Aux = sym
|
||||
v.AddArg(base)
|
||||
v.AddArg(val)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
// match: (SUBLmodify [off1] {sym1} (LEAL [off2] {sym2} base) val mem)
|
||||
// cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
|
||||
// result: (SUBLmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
sym1 := v.Aux
|
||||
_ = v.Args[2]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != Op386LEAL {
|
||||
break
|
||||
}
|
||||
off2 := v_0.AuxInt
|
||||
sym2 := v_0.Aux
|
||||
base := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386SUBLmodify)
|
||||
v.AuxInt = off1 + off2
|
||||
v.Aux = mergeSym(sym1, sym2)
|
||||
v.AddArg(base)
|
||||
v.AddArg(val)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValue386_Op386SUBSD_0(v *Value) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
@ -15578,6 +16370,66 @@ func rewriteValue386_Op386XORLmem_0(v *Value) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValue386_Op386XORLmodify_0(v *Value) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
config := b.Func.Config
|
||||
_ = config
|
||||
// match: (XORLmodify [off1] {sym} (ADDLconst [off2] base) val mem)
|
||||
// cond: is32Bit(off1+off2)
|
||||
// result: (XORLmodify [off1+off2] {sym} base val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
sym := v.Aux
|
||||
_ = v.Args[2]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != Op386ADDLconst {
|
||||
break
|
||||
}
|
||||
off2 := v_0.AuxInt
|
||||
base := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !(is32Bit(off1 + off2)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386XORLmodify)
|
||||
v.AuxInt = off1 + off2
|
||||
v.Aux = sym
|
||||
v.AddArg(base)
|
||||
v.AddArg(val)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
// match: (XORLmodify [off1] {sym1} (LEAL [off2] {sym2} base) val mem)
|
||||
// cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
|
||||
// result: (XORLmodify [off1+off2] {mergeSym(sym1,sym2)} base val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
sym1 := v.Aux
|
||||
_ = v.Args[2]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != Op386LEAL {
|
||||
break
|
||||
}
|
||||
off2 := v_0.AuxInt
|
||||
sym2 := v_0.Aux
|
||||
base := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386XORLmodify)
|
||||
v.AuxInt = off1 + off2
|
||||
v.Aux = mergeSym(sym1, sym2)
|
||||
v.AddArg(base)
|
||||
v.AddArg(val)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValue386_OpAdd16_0(v *Value) bool {
|
||||
// match: (Add16 x y)
|
||||
// cond:
|
||||
|
@ -521,7 +521,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||
if v.Reg() != v.Args[0].Reg() {
|
||||
v.Fatalf("input[0] and output not in same register %s", v.LongString())
|
||||
}
|
||||
case ssa.Op386MOVSSstore, ssa.Op386MOVSDstore, ssa.Op386MOVLstore, ssa.Op386MOVWstore, ssa.Op386MOVBstore:
|
||||
case ssa.Op386MOVSSstore, ssa.Op386MOVSDstore, ssa.Op386MOVLstore, ssa.Op386MOVWstore, ssa.Op386MOVBstore,
|
||||
ssa.Op386ADDLmodify, ssa.Op386SUBLmodify, ssa.Op386ANDLmodify, ssa.Op386ORLmodify, ssa.Op386XORLmodify:
|
||||
p := s.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = v.Args[1].Reg()
|
||||
|
@ -14,7 +14,11 @@ package codegen
|
||||
// Subtraction //
|
||||
// ----------------- //
|
||||
|
||||
func SubMem(arr []int) int {
|
||||
func SubMem(arr []int, b int) int {
|
||||
// 386:`SUBL\s[A-Z]+,\s8\([A-Z]+\)`
|
||||
arr[2] -= b
|
||||
// 386:`SUBL\s[A-Z]+,\s12\([A-Z]+\)`
|
||||
arr[3] -= b
|
||||
// 386:"SUBL\t4"
|
||||
// amd64:"SUBQ\t8"
|
||||
return arr[0] - arr[1]
|
||||
|
Loading…
Reference in New Issue
Block a user