diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index 454eb498c6..347bf2a00f 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -1733,6 +1733,12 @@ (Eq(8|16|32|64) s:(Sub(8|16|32|64) x y) (Const(8|16|32|64) [0])) && s.Uses == 1 -> (Eq(8|16|32|64) x y) (Neq(8|16|32|64) s:(Sub(8|16|32|64) x y) (Const(8|16|32|64) [0])) && s.Uses == 1 -> (Neq(8|16|32|64) x y) +// Optimize bitsets +(Eq(8|16|32|64) (And(8|16|32|64) x (Const(8|16|32|64) [y])) (Const(8|16|32|64) [y])) && isPowerOfTwo(y) + -> (Neq(8|16|32|64) (And(8|16|32|64) x (Const(8|16|32|64) [y])) (Const(8|16|32|64) [0])) +(Neq(8|16|32|64) (And(8|16|32|64) x (Const(8|16|32|64) [y])) (Const(8|16|32|64) [y])) && isPowerOfTwo(y) + -> (Eq(8|16|32|64) (And(8|16|32|64) x (Const(8|16|32|64) [y])) (Const(8|16|32|64) [0])) + // Reassociate expressions involving // constants such that constants come first, // exposing obvious constant-folding opportunities. diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index db0b1749a8..6b0cd05047 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -89,7 +89,7 @@ func rewriteValuegeneric(v *Value) bool { case OpDiv8u: return rewriteValuegeneric_OpDiv8u_0(v) case OpEq16: - return rewriteValuegeneric_OpEq16_0(v) || rewriteValuegeneric_OpEq16_10(v) || rewriteValuegeneric_OpEq16_20(v) || rewriteValuegeneric_OpEq16_30(v) || rewriteValuegeneric_OpEq16_40(v) || rewriteValuegeneric_OpEq16_50(v) + return rewriteValuegeneric_OpEq16_0(v) || rewriteValuegeneric_OpEq16_10(v) || rewriteValuegeneric_OpEq16_20(v) || rewriteValuegeneric_OpEq16_30(v) || rewriteValuegeneric_OpEq16_40(v) || rewriteValuegeneric_OpEq16_50(v) || rewriteValuegeneric_OpEq16_60(v) case OpEq32: return rewriteValuegeneric_OpEq32_0(v) || rewriteValuegeneric_OpEq32_10(v) || rewriteValuegeneric_OpEq32_20(v) || rewriteValuegeneric_OpEq32_30(v) || rewriteValuegeneric_OpEq32_40(v) || rewriteValuegeneric_OpEq32_50(v) || rewriteValuegeneric_OpEq32_60(v) || rewriteValuegeneric_OpEq32_70(v) || rewriteValuegeneric_OpEq32_80(v) || rewriteValuegeneric_OpEq32_90(v) case OpEq32F: @@ -275,17 +275,17 @@ func rewriteValuegeneric(v *Value) bool { case OpNeg8: return rewriteValuegeneric_OpNeg8_0(v) case OpNeq16: - return rewriteValuegeneric_OpNeq16_0(v) + return rewriteValuegeneric_OpNeq16_0(v) || rewriteValuegeneric_OpNeq16_10(v) case OpNeq32: - return rewriteValuegeneric_OpNeq32_0(v) + return rewriteValuegeneric_OpNeq32_0(v) || rewriteValuegeneric_OpNeq32_10(v) case OpNeq32F: return rewriteValuegeneric_OpNeq32F_0(v) case OpNeq64: - return rewriteValuegeneric_OpNeq64_0(v) + return rewriteValuegeneric_OpNeq64_0(v) || rewriteValuegeneric_OpNeq64_10(v) case OpNeq64F: return rewriteValuegeneric_OpNeq64F_0(v) case OpNeq8: - return rewriteValuegeneric_OpNeq8_0(v) + return rewriteValuegeneric_OpNeq8_0(v) || rewriteValuegeneric_OpNeq8_10(v) case OpNeqB: return rewriteValuegeneric_OpNeqB_0(v) case OpNeqInter: @@ -12716,6 +12716,188 @@ func rewriteValuegeneric_OpEq16_50(v *Value) bool { v.AddArg(y) return true } + // match: (Eq16 (And16 x (Const16 [y])) (Const16 [y])) + // cond: isPowerOfTwo(y) + // result: (Neq16 (And16 x (Const16 [y])) (Const16 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpAnd16 { + break + } + t := v_0.Type + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpConst16 { + break + } + if v_0_1.Type != t { + break + } + y := v_0_1.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpConst16 { + break + } + if v_1.Type != t { + break + } + if v_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpNeq16) + v0 := b.NewValue0(v.Pos, OpAnd16, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst16, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst16, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + // match: (Eq16 (And16 (Const16 [y]) x) (Const16 [y])) + // cond: isPowerOfTwo(y) + // result: (Neq16 (And16 x (Const16 [y])) (Const16 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpAnd16 { + break + } + t := v_0.Type + x := v_0.Args[1] + v_0_0 := v_0.Args[0] + if v_0_0.Op != OpConst16 { + break + } + if v_0_0.Type != t { + break + } + y := v_0_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpConst16 { + break + } + if v_1.Type != t { + break + } + if v_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpNeq16) + v0 := b.NewValue0(v.Pos, OpAnd16, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst16, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst16, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + // match: (Eq16 (Const16 [y]) (And16 x (Const16 [y]))) + // cond: isPowerOfTwo(y) + // result: (Neq16 (And16 x (Const16 [y])) (Const16 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst16 { + break + } + t := v_0.Type + y := v_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpAnd16 { + break + } + if v_1.Type != t { + break + } + _ = v_1.Args[1] + x := v_1.Args[0] + v_1_1 := v_1.Args[1] + if v_1_1.Op != OpConst16 { + break + } + if v_1_1.Type != t { + break + } + if v_1_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpNeq16) + v0 := b.NewValue0(v.Pos, OpAnd16, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst16, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst16, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + return false +} +func rewriteValuegeneric_OpEq16_60(v *Value) bool { + b := v.Block + // match: (Eq16 (Const16 [y]) (And16 (Const16 [y]) x)) + // cond: isPowerOfTwo(y) + // result: (Neq16 (And16 x (Const16 [y])) (Const16 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst16 { + break + } + t := v_0.Type + y := v_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpAnd16 { + break + } + if v_1.Type != t { + break + } + x := v_1.Args[1] + v_1_0 := v_1.Args[0] + if v_1_0.Op != OpConst16 { + break + } + if v_1_0.Type != t { + break + } + if v_1_0.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpNeq16) + v0 := b.NewValue0(v.Pos, OpAnd16, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst16, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst16, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } return false } func rewriteValuegeneric_OpEq32_0(v *Value) bool { @@ -19708,6 +19890,184 @@ func rewriteValuegeneric_OpEq32_90(v *Value) bool { v.AddArg(y) return true } + // match: (Eq32 (And32 x (Const32 [y])) (Const32 [y])) + // cond: isPowerOfTwo(y) + // result: (Neq32 (And32 x (Const32 [y])) (Const32 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpAnd32 { + break + } + t := v_0.Type + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpConst32 { + break + } + if v_0_1.Type != t { + break + } + y := v_0_1.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpConst32 { + break + } + if v_1.Type != t { + break + } + if v_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpNeq32) + v0 := b.NewValue0(v.Pos, OpAnd32, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst32, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst32, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + // match: (Eq32 (And32 (Const32 [y]) x) (Const32 [y])) + // cond: isPowerOfTwo(y) + // result: (Neq32 (And32 x (Const32 [y])) (Const32 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpAnd32 { + break + } + t := v_0.Type + x := v_0.Args[1] + v_0_0 := v_0.Args[0] + if v_0_0.Op != OpConst32 { + break + } + if v_0_0.Type != t { + break + } + y := v_0_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpConst32 { + break + } + if v_1.Type != t { + break + } + if v_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpNeq32) + v0 := b.NewValue0(v.Pos, OpAnd32, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst32, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst32, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + // match: (Eq32 (Const32 [y]) (And32 x (Const32 [y]))) + // cond: isPowerOfTwo(y) + // result: (Neq32 (And32 x (Const32 [y])) (Const32 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst32 { + break + } + t := v_0.Type + y := v_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpAnd32 { + break + } + if v_1.Type != t { + break + } + _ = v_1.Args[1] + x := v_1.Args[0] + v_1_1 := v_1.Args[1] + if v_1_1.Op != OpConst32 { + break + } + if v_1_1.Type != t { + break + } + if v_1_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpNeq32) + v0 := b.NewValue0(v.Pos, OpAnd32, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst32, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst32, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + // match: (Eq32 (Const32 [y]) (And32 (Const32 [y]) x)) + // cond: isPowerOfTwo(y) + // result: (Neq32 (And32 x (Const32 [y])) (Const32 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst32 { + break + } + t := v_0.Type + y := v_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpAnd32 { + break + } + if v_1.Type != t { + break + } + x := v_1.Args[1] + v_1_0 := v_1.Args[0] + if v_1_0.Op != OpConst32 { + break + } + if v_1_0.Type != t { + break + } + if v_1_0.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpNeq32) + v0 := b.NewValue0(v.Pos, OpAnd32, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst32, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst32, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } return false } func rewriteValuegeneric_OpEq32F_0(v *Value) bool { @@ -24058,6 +24418,7 @@ func rewriteValuegeneric_OpEq64_50(v *Value) bool { return false } func rewriteValuegeneric_OpEq64_60(v *Value) bool { + b := v.Block // match: (Eq64 (Const64 [0]) s:(Sub64 x y)) // cond: s.Uses == 1 // result: (Eq64 x y) @@ -24084,6 +24445,184 @@ func rewriteValuegeneric_OpEq64_60(v *Value) bool { v.AddArg(y) return true } + // match: (Eq64 (And64 x (Const64 [y])) (Const64 [y])) + // cond: isPowerOfTwo(y) + // result: (Neq64 (And64 x (Const64 [y])) (Const64 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpAnd64 { + break + } + t := v_0.Type + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpConst64 { + break + } + if v_0_1.Type != t { + break + } + y := v_0_1.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpConst64 { + break + } + if v_1.Type != t { + break + } + if v_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpNeq64) + v0 := b.NewValue0(v.Pos, OpAnd64, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst64, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst64, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + // match: (Eq64 (And64 (Const64 [y]) x) (Const64 [y])) + // cond: isPowerOfTwo(y) + // result: (Neq64 (And64 x (Const64 [y])) (Const64 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpAnd64 { + break + } + t := v_0.Type + x := v_0.Args[1] + v_0_0 := v_0.Args[0] + if v_0_0.Op != OpConst64 { + break + } + if v_0_0.Type != t { + break + } + y := v_0_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpConst64 { + break + } + if v_1.Type != t { + break + } + if v_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpNeq64) + v0 := b.NewValue0(v.Pos, OpAnd64, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst64, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst64, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + // match: (Eq64 (Const64 [y]) (And64 x (Const64 [y]))) + // cond: isPowerOfTwo(y) + // result: (Neq64 (And64 x (Const64 [y])) (Const64 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst64 { + break + } + t := v_0.Type + y := v_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpAnd64 { + break + } + if v_1.Type != t { + break + } + _ = v_1.Args[1] + x := v_1.Args[0] + v_1_1 := v_1.Args[1] + if v_1_1.Op != OpConst64 { + break + } + if v_1_1.Type != t { + break + } + if v_1_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpNeq64) + v0 := b.NewValue0(v.Pos, OpAnd64, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst64, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst64, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + // match: (Eq64 (Const64 [y]) (And64 (Const64 [y]) x)) + // cond: isPowerOfTwo(y) + // result: (Neq64 (And64 x (Const64 [y])) (Const64 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst64 { + break + } + t := v_0.Type + y := v_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpAnd64 { + break + } + if v_1.Type != t { + break + } + x := v_1.Args[1] + v_1_0 := v_1.Args[0] + if v_1_0.Op != OpConst64 { + break + } + if v_1_0.Type != t { + break + } + if v_1_0.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpNeq64) + v0 := b.NewValue0(v.Pos, OpAnd64, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst64, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst64, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } return false } func rewriteValuegeneric_OpEq64F_0(v *Value) bool { @@ -26177,6 +26716,184 @@ func rewriteValuegeneric_OpEq8_30(v *Value) bool { v.AddArg(y) return true } + // match: (Eq8 (And8 x (Const8 [y])) (Const8 [y])) + // cond: isPowerOfTwo(y) + // result: (Neq8 (And8 x (Const8 [y])) (Const8 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpAnd8 { + break + } + t := v_0.Type + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpConst8 { + break + } + if v_0_1.Type != t { + break + } + y := v_0_1.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpConst8 { + break + } + if v_1.Type != t { + break + } + if v_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpNeq8) + v0 := b.NewValue0(v.Pos, OpAnd8, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst8, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst8, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + // match: (Eq8 (And8 (Const8 [y]) x) (Const8 [y])) + // cond: isPowerOfTwo(y) + // result: (Neq8 (And8 x (Const8 [y])) (Const8 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpAnd8 { + break + } + t := v_0.Type + x := v_0.Args[1] + v_0_0 := v_0.Args[0] + if v_0_0.Op != OpConst8 { + break + } + if v_0_0.Type != t { + break + } + y := v_0_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpConst8 { + break + } + if v_1.Type != t { + break + } + if v_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpNeq8) + v0 := b.NewValue0(v.Pos, OpAnd8, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst8, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst8, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + // match: (Eq8 (Const8 [y]) (And8 x (Const8 [y]))) + // cond: isPowerOfTwo(y) + // result: (Neq8 (And8 x (Const8 [y])) (Const8 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst8 { + break + } + t := v_0.Type + y := v_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpAnd8 { + break + } + if v_1.Type != t { + break + } + _ = v_1.Args[1] + x := v_1.Args[0] + v_1_1 := v_1.Args[1] + if v_1_1.Op != OpConst8 { + break + } + if v_1_1.Type != t { + break + } + if v_1_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpNeq8) + v0 := b.NewValue0(v.Pos, OpAnd8, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst8, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst8, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + // match: (Eq8 (Const8 [y]) (And8 (Const8 [y]) x)) + // cond: isPowerOfTwo(y) + // result: (Neq8 (And8 x (Const8 [y])) (Const8 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst8 { + break + } + t := v_0.Type + y := v_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpAnd8 { + break + } + if v_1.Type != t { + break + } + x := v_1.Args[1] + v_1_0 := v_1.Args[0] + if v_1_0.Op != OpConst8 { + break + } + if v_1_0.Type != t { + break + } + if v_1_0.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpNeq8) + v0 := b.NewValue0(v.Pos, OpAnd8, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst8, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst8, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } return false } func rewriteValuegeneric_OpEqB_0(v *Value) bool { @@ -35976,6 +36693,188 @@ func rewriteValuegeneric_OpNeq16_0(v *Value) bool { v.AddArg(y) return true } + // match: (Neq16 (And16 x (Const16 [y])) (Const16 [y])) + // cond: isPowerOfTwo(y) + // result: (Eq16 (And16 x (Const16 [y])) (Const16 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpAnd16 { + break + } + t := v_0.Type + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpConst16 { + break + } + if v_0_1.Type != t { + break + } + y := v_0_1.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpConst16 { + break + } + if v_1.Type != t { + break + } + if v_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpEq16) + v0 := b.NewValue0(v.Pos, OpAnd16, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst16, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst16, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + return false +} +func rewriteValuegeneric_OpNeq16_10(v *Value) bool { + b := v.Block + // match: (Neq16 (And16 (Const16 [y]) x) (Const16 [y])) + // cond: isPowerOfTwo(y) + // result: (Eq16 (And16 x (Const16 [y])) (Const16 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpAnd16 { + break + } + t := v_0.Type + x := v_0.Args[1] + v_0_0 := v_0.Args[0] + if v_0_0.Op != OpConst16 { + break + } + if v_0_0.Type != t { + break + } + y := v_0_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpConst16 { + break + } + if v_1.Type != t { + break + } + if v_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpEq16) + v0 := b.NewValue0(v.Pos, OpAnd16, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst16, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst16, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + // match: (Neq16 (Const16 [y]) (And16 x (Const16 [y]))) + // cond: isPowerOfTwo(y) + // result: (Eq16 (And16 x (Const16 [y])) (Const16 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst16 { + break + } + t := v_0.Type + y := v_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpAnd16 { + break + } + if v_1.Type != t { + break + } + _ = v_1.Args[1] + x := v_1.Args[0] + v_1_1 := v_1.Args[1] + if v_1_1.Op != OpConst16 { + break + } + if v_1_1.Type != t { + break + } + if v_1_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpEq16) + v0 := b.NewValue0(v.Pos, OpAnd16, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst16, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst16, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + // match: (Neq16 (Const16 [y]) (And16 (Const16 [y]) x)) + // cond: isPowerOfTwo(y) + // result: (Eq16 (And16 x (Const16 [y])) (Const16 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst16 { + break + } + t := v_0.Type + y := v_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpAnd16 { + break + } + if v_1.Type != t { + break + } + x := v_1.Args[1] + v_1_0 := v_1.Args[0] + if v_1_0.Op != OpConst16 { + break + } + if v_1_0.Type != t { + break + } + if v_1_0.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpEq16) + v0 := b.NewValue0(v.Pos, OpAnd16, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst16, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst16, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } return false } func rewriteValuegeneric_OpNeq32_0(v *Value) bool { @@ -36208,6 +37107,188 @@ func rewriteValuegeneric_OpNeq32_0(v *Value) bool { v.AddArg(y) return true } + // match: (Neq32 (And32 x (Const32 [y])) (Const32 [y])) + // cond: isPowerOfTwo(y) + // result: (Eq32 (And32 x (Const32 [y])) (Const32 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpAnd32 { + break + } + t := v_0.Type + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpConst32 { + break + } + if v_0_1.Type != t { + break + } + y := v_0_1.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpConst32 { + break + } + if v_1.Type != t { + break + } + if v_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpEq32) + v0 := b.NewValue0(v.Pos, OpAnd32, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst32, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst32, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + return false +} +func rewriteValuegeneric_OpNeq32_10(v *Value) bool { + b := v.Block + // match: (Neq32 (And32 (Const32 [y]) x) (Const32 [y])) + // cond: isPowerOfTwo(y) + // result: (Eq32 (And32 x (Const32 [y])) (Const32 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpAnd32 { + break + } + t := v_0.Type + x := v_0.Args[1] + v_0_0 := v_0.Args[0] + if v_0_0.Op != OpConst32 { + break + } + if v_0_0.Type != t { + break + } + y := v_0_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpConst32 { + break + } + if v_1.Type != t { + break + } + if v_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpEq32) + v0 := b.NewValue0(v.Pos, OpAnd32, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst32, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst32, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + // match: (Neq32 (Const32 [y]) (And32 x (Const32 [y]))) + // cond: isPowerOfTwo(y) + // result: (Eq32 (And32 x (Const32 [y])) (Const32 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst32 { + break + } + t := v_0.Type + y := v_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpAnd32 { + break + } + if v_1.Type != t { + break + } + _ = v_1.Args[1] + x := v_1.Args[0] + v_1_1 := v_1.Args[1] + if v_1_1.Op != OpConst32 { + break + } + if v_1_1.Type != t { + break + } + if v_1_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpEq32) + v0 := b.NewValue0(v.Pos, OpAnd32, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst32, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst32, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + // match: (Neq32 (Const32 [y]) (And32 (Const32 [y]) x)) + // cond: isPowerOfTwo(y) + // result: (Eq32 (And32 x (Const32 [y])) (Const32 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst32 { + break + } + t := v_0.Type + y := v_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpAnd32 { + break + } + if v_1.Type != t { + break + } + x := v_1.Args[1] + v_1_0 := v_1.Args[0] + if v_1_0.Op != OpConst32 { + break + } + if v_1_0.Type != t { + break + } + if v_1_0.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpEq32) + v0 := b.NewValue0(v.Pos, OpAnd32, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst32, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst32, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } return false } func rewriteValuegeneric_OpNeq32F_0(v *Value) bool { @@ -36481,6 +37562,188 @@ func rewriteValuegeneric_OpNeq64_0(v *Value) bool { v.AddArg(y) return true } + // match: (Neq64 (And64 x (Const64 [y])) (Const64 [y])) + // cond: isPowerOfTwo(y) + // result: (Eq64 (And64 x (Const64 [y])) (Const64 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpAnd64 { + break + } + t := v_0.Type + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpConst64 { + break + } + if v_0_1.Type != t { + break + } + y := v_0_1.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpConst64 { + break + } + if v_1.Type != t { + break + } + if v_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpEq64) + v0 := b.NewValue0(v.Pos, OpAnd64, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst64, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst64, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + return false +} +func rewriteValuegeneric_OpNeq64_10(v *Value) bool { + b := v.Block + // match: (Neq64 (And64 (Const64 [y]) x) (Const64 [y])) + // cond: isPowerOfTwo(y) + // result: (Eq64 (And64 x (Const64 [y])) (Const64 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpAnd64 { + break + } + t := v_0.Type + x := v_0.Args[1] + v_0_0 := v_0.Args[0] + if v_0_0.Op != OpConst64 { + break + } + if v_0_0.Type != t { + break + } + y := v_0_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpConst64 { + break + } + if v_1.Type != t { + break + } + if v_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpEq64) + v0 := b.NewValue0(v.Pos, OpAnd64, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst64, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst64, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + // match: (Neq64 (Const64 [y]) (And64 x (Const64 [y]))) + // cond: isPowerOfTwo(y) + // result: (Eq64 (And64 x (Const64 [y])) (Const64 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst64 { + break + } + t := v_0.Type + y := v_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpAnd64 { + break + } + if v_1.Type != t { + break + } + _ = v_1.Args[1] + x := v_1.Args[0] + v_1_1 := v_1.Args[1] + if v_1_1.Op != OpConst64 { + break + } + if v_1_1.Type != t { + break + } + if v_1_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpEq64) + v0 := b.NewValue0(v.Pos, OpAnd64, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst64, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst64, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + // match: (Neq64 (Const64 [y]) (And64 (Const64 [y]) x)) + // cond: isPowerOfTwo(y) + // result: (Eq64 (And64 x (Const64 [y])) (Const64 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst64 { + break + } + t := v_0.Type + y := v_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpAnd64 { + break + } + if v_1.Type != t { + break + } + x := v_1.Args[1] + v_1_0 := v_1.Args[0] + if v_1_0.Op != OpConst64 { + break + } + if v_1_0.Type != t { + break + } + if v_1_0.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpEq64) + v0 := b.NewValue0(v.Pos, OpAnd64, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst64, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst64, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } return false } func rewriteValuegeneric_OpNeq64F_0(v *Value) bool { @@ -36754,6 +38017,188 @@ func rewriteValuegeneric_OpNeq8_0(v *Value) bool { v.AddArg(y) return true } + // match: (Neq8 (And8 x (Const8 [y])) (Const8 [y])) + // cond: isPowerOfTwo(y) + // result: (Eq8 (And8 x (Const8 [y])) (Const8 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpAnd8 { + break + } + t := v_0.Type + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpConst8 { + break + } + if v_0_1.Type != t { + break + } + y := v_0_1.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpConst8 { + break + } + if v_1.Type != t { + break + } + if v_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpEq8) + v0 := b.NewValue0(v.Pos, OpAnd8, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst8, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst8, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + return false +} +func rewriteValuegeneric_OpNeq8_10(v *Value) bool { + b := v.Block + // match: (Neq8 (And8 (Const8 [y]) x) (Const8 [y])) + // cond: isPowerOfTwo(y) + // result: (Eq8 (And8 x (Const8 [y])) (Const8 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpAnd8 { + break + } + t := v_0.Type + x := v_0.Args[1] + v_0_0 := v_0.Args[0] + if v_0_0.Op != OpConst8 { + break + } + if v_0_0.Type != t { + break + } + y := v_0_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpConst8 { + break + } + if v_1.Type != t { + break + } + if v_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpEq8) + v0 := b.NewValue0(v.Pos, OpAnd8, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst8, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst8, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + // match: (Neq8 (Const8 [y]) (And8 x (Const8 [y]))) + // cond: isPowerOfTwo(y) + // result: (Eq8 (And8 x (Const8 [y])) (Const8 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst8 { + break + } + t := v_0.Type + y := v_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpAnd8 { + break + } + if v_1.Type != t { + break + } + _ = v_1.Args[1] + x := v_1.Args[0] + v_1_1 := v_1.Args[1] + if v_1_1.Op != OpConst8 { + break + } + if v_1_1.Type != t { + break + } + if v_1_1.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpEq8) + v0 := b.NewValue0(v.Pos, OpAnd8, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst8, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst8, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } + // match: (Neq8 (Const8 [y]) (And8 (Const8 [y]) x)) + // cond: isPowerOfTwo(y) + // result: (Eq8 (And8 x (Const8 [y])) (Const8 [0])) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst8 { + break + } + t := v_0.Type + y := v_0.AuxInt + v_1 := v.Args[1] + if v_1.Op != OpAnd8 { + break + } + if v_1.Type != t { + break + } + x := v_1.Args[1] + v_1_0 := v_1.Args[0] + if v_1_0.Op != OpConst8 { + break + } + if v_1_0.Type != t { + break + } + if v_1_0.AuxInt != y { + break + } + if !(isPowerOfTwo(y)) { + break + } + v.reset(OpEq8) + v0 := b.NewValue0(v.Pos, OpAnd8, t) + v0.AddArg(x) + v1 := b.NewValue0(v.Pos, OpConst8, t) + v1.AuxInt = y + v0.AddArg(v1) + v.AddArg(v0) + v2 := b.NewValue0(v.Pos, OpConst8, t) + v2.AuxInt = 0 + v.AddArg(v2) + return true + } return false } func rewriteValuegeneric_OpNeqB_0(v *Value) bool { diff --git a/test/codegen/bits.go b/test/codegen/bits.go index 65d57c8f9f..18f9daf7cf 100644 --- a/test/codegen/bits.go +++ b/test/codegen/bits.go @@ -314,3 +314,15 @@ func op_orn(x, y uint32) uint32 { // arm64:`ORN\t`,-`ORR` return x | ^y } + +// check bitsets +func bitSetPowerOf2Test(x int) bool { + // amd64:"BTL\t[$]3" + return x&8 == 8 +} + +func bitSetTest(x int) bool { + // amd64:"ANDQ\t[$]9, AX" + // amd64:"CMPQ\tAX, [$]9" + return x&9 == 9 +}