// x & 1 != 0 -> x & 1
(SETNE (TEST(B|W)const [1] x)) => (AND(L|L)const [1] x)
(SETB (BT(L|Q)const [0] x)) => (AND(L|Q)const [1] x)
+// x & 1 == 0 -> (x & 1) ^ 1
+(SETAE (BT(L|Q)const [0] x)) => (XORLconst [1] (ANDLconst <typ.Bool> [1] x))
// Recognize bit tests: a&(1<<b) != 0 for b suitably bounded
// Note that BTx instructions use the carry bit, so we need to convert tests for zero flag
}
func rewriteValueAMD64_OpAMD64SETAE(v *Value) bool {
v_0 := v.Args[0]
+ b := v.Block
+ typ := &b.Func.Config.Types
// match: (SETAE (TESTQ x x))
// result: (ConstBool [true])
for {
v.AuxInt = boolToAuxInt(true)
return true
}
+ // match: (SETAE (BTLconst [0] x))
+ // result: (XORLconst [1] (ANDLconst <typ.Bool> [1] x))
+ for {
+ if v_0.Op != OpAMD64BTLconst || auxIntToInt8(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64XORLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpAMD64ANDLconst, typ.Bool)
+ v0.AuxInt = int32ToAuxInt(1)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
+ // match: (SETAE (BTQconst [0] x))
+ // result: (XORLconst [1] (ANDLconst <typ.Bool> [1] x))
+ for {
+ if v_0.Op != OpAMD64BTQconst || auxIntToInt8(v_0.AuxInt) != 0 {
+ break
+ }
+ x := v_0.Args[0]
+ v.reset(OpAMD64XORLconst)
+ v.AuxInt = int32ToAuxInt(1)
+ v0 := b.NewValue0(v.Pos, OpAMD64ANDLconst, typ.Bool)
+ v0.AuxInt = int32ToAuxInt(1)
+ v0.AddArg(x)
+ v.AddArg(v0)
+ return true
+ }
// match: (SETAE (InvertFlags x))
// result: (SETBE x)
for {
func convertEqBool32(x uint32) bool {
// ppc64x:"RLDICL",-"CMPW","XOR",-"ISEL"
+ // amd64:"ANDL","XORL",-"BTL",-"SETCC"
return x&1 == 0
}
func convertEqBool64(x uint64) bool {
// ppc64x:"RLDICL","XOR",-"CMP",-"ISEL"
+ // amd64:"ANDL","XORL",-"BTL",-"SETCC"
return x&1 == 0
}