package ssa
+// When breaking up a combined load-compare to separated load and compare operations,
+// opLoad specifies the load operation, and opCmp specifies the compare operation.
+type typeCmdLoadMap struct {
+ opLoad Op
+ opCmp Op
+}
+
+var opCmpLoadMap = map[Op]typeCmdLoadMap{
+ OpAMD64CMPQload: {OpAMD64MOVQload, OpAMD64CMPQ},
+ OpAMD64CMPLload: {OpAMD64MOVLload, OpAMD64CMPL},
+ OpAMD64CMPWload: {OpAMD64MOVWload, OpAMD64CMPW},
+ OpAMD64CMPBload: {OpAMD64MOVBload, OpAMD64CMPB},
+ Op386CMPLload: {Op386MOVLload, Op386CMPL},
+ Op386CMPWload: {Op386MOVWload, Op386CMPW},
+ Op386CMPBload: {Op386MOVBload, Op386CMPB},
+ OpAMD64CMPQconstload: {OpAMD64MOVQload, OpAMD64CMPQconst},
+ OpAMD64CMPLconstload: {OpAMD64MOVLload, OpAMD64CMPLconst},
+ OpAMD64CMPWconstload: {OpAMD64MOVWload, OpAMD64CMPWconst},
+ OpAMD64CMPBconstload: {OpAMD64MOVBload, OpAMD64CMPBconst},
+ Op386CMPLconstload: {Op386MOVLload, Op386CMPLconst},
+ Op386CMPWconstload: {Op386MOVWload, Op386CMPWconst},
+ Op386CMPBconstload: {Op386MOVBload, Op386CMPBconst},
+}
+
// flagalloc allocates the flag register among all the flag-generating
// instructions. Flag values are recomputed if they need to be
// spilled/restored.
if spill[v.ID] && v.MemoryArg() != nil {
switch v.Op {
case OpAMD64CMPQload:
- load := b.NewValue2IA(v.Pos, OpAMD64MOVQload, f.Config.Types.UInt64, v.AuxInt, v.Aux, v.Args[0], v.Args[2])
- v.Op = OpAMD64CMPQ
+ load := b.NewValue2IA(v.Pos, opCmpLoadMap[v.Op].opLoad, f.Config.Types.UInt64, v.AuxInt, v.Aux, v.Args[0], v.Args[2])
+ v.Op = opCmpLoadMap[v.Op].opCmp
v.AuxInt = 0
v.Aux = nil
v.SetArgs2(load, v.Args[1])
- case OpAMD64CMPLload:
- load := b.NewValue2IA(v.Pos, OpAMD64MOVLload, f.Config.Types.UInt32, v.AuxInt, v.Aux, v.Args[0], v.Args[2])
- v.Op = OpAMD64CMPL
+ case OpAMD64CMPLload, Op386CMPLload:
+ load := b.NewValue2IA(v.Pos, opCmpLoadMap[v.Op].opLoad, f.Config.Types.UInt32, v.AuxInt, v.Aux, v.Args[0], v.Args[2])
+ v.Op = opCmpLoadMap[v.Op].opCmp
v.AuxInt = 0
v.Aux = nil
v.SetArgs2(load, v.Args[1])
- case OpAMD64CMPWload:
- load := b.NewValue2IA(v.Pos, OpAMD64MOVWload, f.Config.Types.UInt16, v.AuxInt, v.Aux, v.Args[0], v.Args[2])
- v.Op = OpAMD64CMPW
+ case OpAMD64CMPWload, Op386CMPWload:
+ load := b.NewValue2IA(v.Pos, opCmpLoadMap[v.Op].opLoad, f.Config.Types.UInt16, v.AuxInt, v.Aux, v.Args[0], v.Args[2])
+ v.Op = opCmpLoadMap[v.Op].opCmp
v.AuxInt = 0
v.Aux = nil
v.SetArgs2(load, v.Args[1])
- case OpAMD64CMPBload:
- load := b.NewValue2IA(v.Pos, OpAMD64MOVBload, f.Config.Types.UInt8, v.AuxInt, v.Aux, v.Args[0], v.Args[2])
- v.Op = OpAMD64CMPB
+ case OpAMD64CMPBload, Op386CMPBload:
+ load := b.NewValue2IA(v.Pos, opCmpLoadMap[v.Op].opLoad, f.Config.Types.UInt8, v.AuxInt, v.Aux, v.Args[0], v.Args[2])
+ v.Op = opCmpLoadMap[v.Op].opCmp
v.AuxInt = 0
v.Aux = nil
v.SetArgs2(load, v.Args[1])
case OpAMD64CMPQconstload:
vo := v.AuxValAndOff()
- load := b.NewValue2IA(v.Pos, OpAMD64MOVQload, f.Config.Types.UInt64, vo.Off(), v.Aux, v.Args[0], v.Args[1])
- v.Op = OpAMD64CMPQconst
+ load := b.NewValue2IA(v.Pos, opCmpLoadMap[v.Op].opLoad, f.Config.Types.UInt64, vo.Off(), v.Aux, v.Args[0], v.Args[1])
+ v.Op = opCmpLoadMap[v.Op].opCmp
v.AuxInt = vo.Val()
v.Aux = nil
v.SetArgs1(load)
- case OpAMD64CMPLconstload:
+ case OpAMD64CMPLconstload, Op386CMPLconstload:
vo := v.AuxValAndOff()
- load := b.NewValue2IA(v.Pos, OpAMD64MOVLload, f.Config.Types.UInt32, vo.Off(), v.Aux, v.Args[0], v.Args[1])
- v.Op = OpAMD64CMPLconst
+ load := b.NewValue2IA(v.Pos, opCmpLoadMap[v.Op].opLoad, f.Config.Types.UInt32, vo.Off(), v.Aux, v.Args[0], v.Args[1])
+ v.Op = opCmpLoadMap[v.Op].opCmp
v.AuxInt = vo.Val()
v.Aux = nil
v.SetArgs1(load)
- case OpAMD64CMPWconstload:
+ case OpAMD64CMPWconstload, Op386CMPWconstload:
vo := v.AuxValAndOff()
- load := b.NewValue2IA(v.Pos, OpAMD64MOVWload, f.Config.Types.UInt16, vo.Off(), v.Aux, v.Args[0], v.Args[1])
- v.Op = OpAMD64CMPWconst
+ load := b.NewValue2IA(v.Pos, opCmpLoadMap[v.Op].opLoad, f.Config.Types.UInt16, vo.Off(), v.Aux, v.Args[0], v.Args[1])
+ v.Op = opCmpLoadMap[v.Op].opCmp
v.AuxInt = vo.Val()
v.Aux = nil
v.SetArgs1(load)
- case OpAMD64CMPBconstload:
+ case OpAMD64CMPBconstload, Op386CMPBconstload:
vo := v.AuxValAndOff()
- load := b.NewValue2IA(v.Pos, OpAMD64MOVBload, f.Config.Types.UInt8, vo.Off(), v.Aux, v.Args[0], v.Args[1])
- v.Op = OpAMD64CMPBconst
+ load := b.NewValue2IA(v.Pos, opCmpLoadMap[v.Op].opLoad, f.Config.Types.UInt8, vo.Off(), v.Aux, v.Args[0], v.Args[1])
+ v.Op = opCmpLoadMap[v.Op].opCmp
v.AuxInt = vo.Val()
v.Aux = nil
v.SetArgs1(load)
// a register to use for holding the address of the constant pool entry.
(MOVSSconst [c]) && config.ctxt.Flag_shared -> (MOVSSconst2 (MOVSSconst1 [c]))
(MOVSDconst [c]) && config.ctxt.Flag_shared -> (MOVSDconst2 (MOVSDconst1 [c]))
+
+(CMP(L|W|B) l:(MOV(L|W|B)load {sym} [off] ptr mem) x) && canMergeLoad(v, l, x) && clobber(l) -> (CMP(L|W|B)load {sym} [off] ptr x mem)
+(CMP(L|W|B) x l:(MOV(L|W|B)load {sym} [off] ptr mem)) && canMergeLoad(v, l, x) && clobber(l) -> (InvertFlags (CMP(L|W|B)load {sym} [off] ptr x mem))
+
+(CMP(L|W|B)const l:(MOV(L|W|B)load {sym} [off] ptr mem) [c])
+ && l.Uses == 1
+ && validValAndOff(c, off)
+ && clobber(l) ->
+ @l.Block (CMP(L|W|B)constload {sym} [makeValAndOff(c,off)] ptr mem)
+
+(CMPLload {sym} [off] ptr (MOVLconst [c]) mem) && validValAndOff(int64(int32(c)),off) -> (CMPLconstload {sym} [makeValAndOff(int64(int32(c)),off)] ptr mem)
+(CMPWload {sym} [off] ptr (MOVLconst [c]) mem) && validValAndOff(int64(int16(c)),off) -> (CMPWconstload {sym} [makeValAndOff(int64(int16(c)),off)] ptr mem)
+(CMPBload {sym} [off] ptr (MOVLconst [c]) mem) && validValAndOff(int64(int8(c)),off) -> (CMPBconstload {sym} [makeValAndOff(int64(int8(c)),off)] ptr mem)
gp11mod = regInfo{inputs: []regMask{ax, gpsp &^ dx}, outputs: []regMask{dx}, clobbers: ax}
gp21mul = regInfo{inputs: []regMask{ax, gpsp}, outputs: []regMask{dx, ax}}
- gp2flags = regInfo{inputs: []regMask{gpsp, gpsp}}
- gp1flags = regInfo{inputs: []regMask{gpsp}}
- flagsgp = regInfo{inputs: nil, outputs: gponly}
+ gp2flags = regInfo{inputs: []regMask{gpsp, gpsp}}
+ gp1flags = regInfo{inputs: []regMask{gpsp}}
+ gp0flagsLoad = regInfo{inputs: []regMask{gpspsb, 0}}
+ gp1flagsLoad = regInfo{inputs: []regMask{gpspsb, gpsp, 0}}
+ flagsgp = regInfo{inputs: nil, outputs: gponly}
readflags = regInfo{inputs: nil, outputs: gponly}
flagsgpax = regInfo{inputs: nil, clobbers: ax, outputs: []regMask{gp &^ ax}}
{name: "CMPWconst", argLength: 1, reg: gp1flags, asm: "CMPW", typ: "Flags", aux: "Int16"}, // arg0 compare to auxint
{name: "CMPBconst", argLength: 1, reg: gp1flags, asm: "CMPB", typ: "Flags", aux: "Int8"}, // arg0 compare to auxint
+ // compare *(arg0+auxint+aux) to arg1 (in that order). arg2=mem.
+ {name: "CMPLload", argLength: 3, reg: gp1flagsLoad, asm: "CMPL", aux: "SymOff", typ: "Flags", symEffect: "Read", faultOnNilArg0: true},
+ {name: "CMPWload", argLength: 3, reg: gp1flagsLoad, asm: "CMPW", aux: "SymOff", typ: "Flags", symEffect: "Read", faultOnNilArg0: true},
+ {name: "CMPBload", argLength: 3, reg: gp1flagsLoad, asm: "CMPB", aux: "SymOff", typ: "Flags", symEffect: "Read", faultOnNilArg0: true},
+
+ // compare *(arg0+ValAndOff(AuxInt).Off()+aux) to ValAndOff(AuxInt).Val() (in that order). arg1=mem.
+ {name: "CMPLconstload", argLength: 2, reg: gp0flagsLoad, asm: "CMPL", aux: "SymValAndOff", typ: "Flags", symEffect: "Read", faultOnNilArg0: true},
+ {name: "CMPWconstload", argLength: 2, reg: gp0flagsLoad, asm: "CMPW", aux: "SymValAndOff", typ: "Flags", symEffect: "Read", faultOnNilArg0: true},
+ {name: "CMPBconstload", argLength: 2, reg: gp0flagsLoad, asm: "CMPB", aux: "SymValAndOff", typ: "Flags", symEffect: "Read", faultOnNilArg0: true},
+
{name: "UCOMISS", argLength: 2, reg: fp2flags, asm: "UCOMISS", typ: "Flags", usesScratch: true}, // arg0 compare to arg1, f32
{name: "UCOMISD", argLength: 2, reg: fp2flags, asm: "UCOMISD", typ: "Flags", usesScratch: true}, // arg0 compare to arg1, f64
Op386CMPLconst
Op386CMPWconst
Op386CMPBconst
+ Op386CMPLload
+ Op386CMPWload
+ Op386CMPBload
+ Op386CMPLconstload
+ Op386CMPWconstload
+ Op386CMPBconstload
Op386UCOMISS
Op386UCOMISD
Op386TESTL
},
},
},
+ {
+ name: "CMPLload",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.ACMPL,
+ 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: "CMPWload",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.ACMPW,
+ 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: "CMPBload",
+ auxType: auxSymOff,
+ argLen: 3,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.ACMPB,
+ 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: "CMPLconstload",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.ACMPL,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "CMPWconstload",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.ACMPW,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
+ {
+ name: "CMPBconstload",
+ auxType: auxSymValAndOff,
+ argLen: 2,
+ faultOnNilArg0: true,
+ symEffect: SymRead,
+ asm: x86.ACMPB,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 65791}, // AX CX DX BX SP BP SI DI SB
+ },
+ },
+ },
{
name: "UCOMISS",
argLen: 2,
return rewriteValue386_Op386CMPB_0(v)
case Op386CMPBconst:
return rewriteValue386_Op386CMPBconst_0(v)
+ case Op386CMPBload:
+ return rewriteValue386_Op386CMPBload_0(v)
case Op386CMPL:
return rewriteValue386_Op386CMPL_0(v)
case Op386CMPLconst:
- return rewriteValue386_Op386CMPLconst_0(v)
+ return rewriteValue386_Op386CMPLconst_0(v) || rewriteValue386_Op386CMPLconst_10(v)
+ case Op386CMPLload:
+ return rewriteValue386_Op386CMPLload_0(v)
case Op386CMPW:
return rewriteValue386_Op386CMPW_0(v)
case Op386CMPWconst:
return rewriteValue386_Op386CMPWconst_0(v)
+ case Op386CMPWload:
+ return rewriteValue386_Op386CMPWload_0(v)
case Op386LEAL:
return rewriteValue386_Op386LEAL_0(v)
case Op386LEAL1:
v.AddArg(v0)
return true
}
+ // match: (CMPB l:(MOVBload {sym} [off] ptr mem) x)
+ // cond: canMergeLoad(v, l, x) && clobber(l)
+ // result: (CMPBload {sym} [off] ptr x mem)
+ for {
+ _ = v.Args[1]
+ l := v.Args[0]
+ if l.Op != Op386MOVBload {
+ break
+ }
+ off := l.AuxInt
+ sym := l.Aux
+ _ = l.Args[1]
+ ptr := l.Args[0]
+ mem := l.Args[1]
+ x := v.Args[1]
+ if !(canMergeLoad(v, l, x) && clobber(l)) {
+ break
+ }
+ v.reset(Op386CMPBload)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(x)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (CMPB x l:(MOVBload {sym} [off] ptr mem))
+ // cond: canMergeLoad(v, l, x) && clobber(l)
+ // result: (InvertFlags (CMPBload {sym} [off] ptr x mem))
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ l := v.Args[1]
+ if l.Op != Op386MOVBload {
+ break
+ }
+ off := l.AuxInt
+ sym := l.Aux
+ _ = l.Args[1]
+ ptr := l.Args[0]
+ mem := l.Args[1]
+ if !(canMergeLoad(v, l, x) && clobber(l)) {
+ break
+ }
+ v.reset(Op386InvertFlags)
+ v0 := b.NewValue0(v.Pos, Op386CMPBload, types.TypeFlags)
+ v0.AuxInt = off
+ v0.Aux = sym
+ v0.AddArg(ptr)
+ v0.AddArg(x)
+ v0.AddArg(mem)
+ v.AddArg(v0)
+ return true
+ }
return false
}
func rewriteValue386_Op386CMPBconst_0(v *Value) bool {
+ b := v.Block
+ _ = b
// match: (CMPBconst (MOVLconst [x]) [y])
// cond: int8(x)==int8(y)
// result: (FlagEQ)
v.AddArg(x)
return true
}
+ // match: (CMPBconst l:(MOVBload {sym} [off] ptr mem) [c])
+ // cond: l.Uses == 1 && validValAndOff(c, off) && clobber(l)
+ // result: @l.Block (CMPBconstload {sym} [makeValAndOff(c,off)] ptr mem)
+ for {
+ c := v.AuxInt
+ l := v.Args[0]
+ if l.Op != Op386MOVBload {
+ break
+ }
+ off := l.AuxInt
+ sym := l.Aux
+ _ = l.Args[1]
+ ptr := l.Args[0]
+ mem := l.Args[1]
+ if !(l.Uses == 1 && validValAndOff(c, off) && clobber(l)) {
+ break
+ }
+ b = l.Block
+ v0 := b.NewValue0(v.Pos, Op386CMPBconstload, types.TypeFlags)
+ v.reset(OpCopy)
+ v.AddArg(v0)
+ v0.AuxInt = makeValAndOff(c, off)
+ v0.Aux = sym
+ v0.AddArg(ptr)
+ v0.AddArg(mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386CMPBload_0(v *Value) bool {
+ // match: (CMPBload {sym} [off] ptr (MOVLconst [c]) mem)
+ // cond: validValAndOff(int64(int8(c)),off)
+ // result: (CMPBconstload {sym} [makeValAndOff(int64(int8(c)),off)] ptr mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := v_1.AuxInt
+ mem := v.Args[2]
+ if !(validValAndOff(int64(int8(c)), off)) {
+ break
+ }
+ v.reset(Op386CMPBconstload)
+ v.AuxInt = makeValAndOff(int64(int8(c)), off)
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
return false
}
func rewriteValue386_Op386CMPL_0(v *Value) bool {
v.AddArg(v0)
return true
}
+ // match: (CMPL l:(MOVLload {sym} [off] ptr mem) x)
+ // cond: canMergeLoad(v, l, x) && clobber(l)
+ // result: (CMPLload {sym} [off] ptr x mem)
+ for {
+ _ = v.Args[1]
+ l := v.Args[0]
+ if l.Op != Op386MOVLload {
+ break
+ }
+ off := l.AuxInt
+ sym := l.Aux
+ _ = l.Args[1]
+ ptr := l.Args[0]
+ mem := l.Args[1]
+ x := v.Args[1]
+ if !(canMergeLoad(v, l, x) && clobber(l)) {
+ break
+ }
+ v.reset(Op386CMPLload)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(x)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (CMPL x l:(MOVLload {sym} [off] ptr mem))
+ // cond: canMergeLoad(v, l, x) && clobber(l)
+ // result: (InvertFlags (CMPLload {sym} [off] ptr x mem))
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ l := v.Args[1]
+ if l.Op != Op386MOVLload {
+ break
+ }
+ off := l.AuxInt
+ sym := l.Aux
+ _ = l.Args[1]
+ ptr := l.Args[0]
+ mem := l.Args[1]
+ if !(canMergeLoad(v, l, x) && clobber(l)) {
+ break
+ }
+ v.reset(Op386InvertFlags)
+ v0 := b.NewValue0(v.Pos, Op386CMPLload, types.TypeFlags)
+ v0.AuxInt = off
+ v0.Aux = sym
+ v0.AddArg(ptr)
+ v0.AddArg(x)
+ v0.AddArg(mem)
+ v.AddArg(v0)
+ return true
+ }
return false
}
func rewriteValue386_Op386CMPLconst_0(v *Value) bool {
}
return false
}
+func rewriteValue386_Op386CMPLconst_10(v *Value) bool {
+ b := v.Block
+ _ = b
+ // match: (CMPLconst l:(MOVLload {sym} [off] ptr mem) [c])
+ // cond: l.Uses == 1 && validValAndOff(c, off) && clobber(l)
+ // result: @l.Block (CMPLconstload {sym} [makeValAndOff(c,off)] ptr mem)
+ for {
+ c := v.AuxInt
+ l := v.Args[0]
+ if l.Op != Op386MOVLload {
+ break
+ }
+ off := l.AuxInt
+ sym := l.Aux
+ _ = l.Args[1]
+ ptr := l.Args[0]
+ mem := l.Args[1]
+ if !(l.Uses == 1 && validValAndOff(c, off) && clobber(l)) {
+ break
+ }
+ b = l.Block
+ v0 := b.NewValue0(v.Pos, Op386CMPLconstload, types.TypeFlags)
+ v.reset(OpCopy)
+ v.AddArg(v0)
+ v0.AuxInt = makeValAndOff(c, off)
+ v0.Aux = sym
+ v0.AddArg(ptr)
+ v0.AddArg(mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386CMPLload_0(v *Value) bool {
+ // match: (CMPLload {sym} [off] ptr (MOVLconst [c]) mem)
+ // cond: validValAndOff(int64(int32(c)),off)
+ // result: (CMPLconstload {sym} [makeValAndOff(int64(int32(c)),off)] ptr mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := v_1.AuxInt
+ mem := v.Args[2]
+ if !(validValAndOff(int64(int32(c)), off)) {
+ break
+ }
+ v.reset(Op386CMPLconstload)
+ v.AuxInt = makeValAndOff(int64(int32(c)), off)
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
+ return false
+}
func rewriteValue386_Op386CMPW_0(v *Value) bool {
b := v.Block
_ = b
v.AddArg(v0)
return true
}
+ // match: (CMPW l:(MOVWload {sym} [off] ptr mem) x)
+ // cond: canMergeLoad(v, l, x) && clobber(l)
+ // result: (CMPWload {sym} [off] ptr x mem)
+ for {
+ _ = v.Args[1]
+ l := v.Args[0]
+ if l.Op != Op386MOVWload {
+ break
+ }
+ off := l.AuxInt
+ sym := l.Aux
+ _ = l.Args[1]
+ ptr := l.Args[0]
+ mem := l.Args[1]
+ x := v.Args[1]
+ if !(canMergeLoad(v, l, x) && clobber(l)) {
+ break
+ }
+ v.reset(Op386CMPWload)
+ v.AuxInt = off
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(x)
+ v.AddArg(mem)
+ return true
+ }
+ // match: (CMPW x l:(MOVWload {sym} [off] ptr mem))
+ // cond: canMergeLoad(v, l, x) && clobber(l)
+ // result: (InvertFlags (CMPWload {sym} [off] ptr x mem))
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ l := v.Args[1]
+ if l.Op != Op386MOVWload {
+ break
+ }
+ off := l.AuxInt
+ sym := l.Aux
+ _ = l.Args[1]
+ ptr := l.Args[0]
+ mem := l.Args[1]
+ if !(canMergeLoad(v, l, x) && clobber(l)) {
+ break
+ }
+ v.reset(Op386InvertFlags)
+ v0 := b.NewValue0(v.Pos, Op386CMPWload, types.TypeFlags)
+ v0.AuxInt = off
+ v0.Aux = sym
+ v0.AddArg(ptr)
+ v0.AddArg(x)
+ v0.AddArg(mem)
+ v.AddArg(v0)
+ return true
+ }
return false
}
func rewriteValue386_Op386CMPWconst_0(v *Value) bool {
+ b := v.Block
+ _ = b
// match: (CMPWconst (MOVLconst [x]) [y])
// cond: int16(x)==int16(y)
// result: (FlagEQ)
v.AddArg(x)
return true
}
+ // match: (CMPWconst l:(MOVWload {sym} [off] ptr mem) [c])
+ // cond: l.Uses == 1 && validValAndOff(c, off) && clobber(l)
+ // result: @l.Block (CMPWconstload {sym} [makeValAndOff(c,off)] ptr mem)
+ for {
+ c := v.AuxInt
+ l := v.Args[0]
+ if l.Op != Op386MOVWload {
+ break
+ }
+ off := l.AuxInt
+ sym := l.Aux
+ _ = l.Args[1]
+ ptr := l.Args[0]
+ mem := l.Args[1]
+ if !(l.Uses == 1 && validValAndOff(c, off) && clobber(l)) {
+ break
+ }
+ b = l.Block
+ v0 := b.NewValue0(v.Pos, Op386CMPWconstload, types.TypeFlags)
+ v.reset(OpCopy)
+ v.AddArg(v0)
+ v0.AuxInt = makeValAndOff(c, off)
+ v0.Aux = sym
+ v0.AddArg(ptr)
+ v0.AddArg(mem)
+ return true
+ }
+ return false
+}
+func rewriteValue386_Op386CMPWload_0(v *Value) bool {
+ // match: (CMPWload {sym} [off] ptr (MOVLconst [c]) mem)
+ // cond: validValAndOff(int64(int16(c)),off)
+ // result: (CMPWconstload {sym} [makeValAndOff(int64(int16(c)),off)] ptr mem)
+ for {
+ off := v.AuxInt
+ sym := v.Aux
+ _ = v.Args[2]
+ ptr := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != Op386MOVLconst {
+ break
+ }
+ c := v_1.AuxInt
+ mem := v.Args[2]
+ if !(validValAndOff(int64(int16(c)), off)) {
+ break
+ }
+ v.reset(Op386CMPWconstload)
+ v.AuxInt = makeValAndOff(int64(int16(c)), off)
+ v.Aux = sym
+ v.AddArg(ptr)
+ v.AddArg(mem)
+ return true
+ }
return false
}
func rewriteValue386_Op386LEAL_0(v *Value) bool {
p.From.Offset = v.AuxInt
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Args[0].Reg()
+ case ssa.Op386CMPLload, ssa.Op386CMPWload, ssa.Op386CMPBload:
+ p := s.Prog(v.Op.Asm())
+ p.From.Type = obj.TYPE_MEM
+ p.From.Reg = v.Args[0].Reg()
+ gc.AddAux(&p.From, v)
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = v.Args[1].Reg()
+ case ssa.Op386CMPLconstload, ssa.Op386CMPWconstload, ssa.Op386CMPBconstload:
+ sc := v.AuxValAndOff()
+ p := s.Prog(v.Op.Asm())
+ p.From.Type = obj.TYPE_MEM
+ p.From.Reg = v.Args[0].Reg()
+ gc.AddAux2(&p.From, v, sc.Off())
+ p.To.Type = obj.TYPE_CONST
+ p.To.Offset = sc.Val()
case ssa.Op386MOVLconst:
x := v.Reg()
*p = nil
}
+func CmpMem6(a []int) int {
+ // 386:`CMPL\s8\([A-Z]+\),`
+ // amd64:`CMPQ\s16\([A-Z]+\),`
+ if a[1] > a[2] {
+ return 1
+ } else {
+ return 2
+ }
+}
+
// Check tbz/tbnz are generated when comparing against zero on arm64
func CmpZero1(a int32, ptr *int) {