diff --git a/src/cmd/compile/internal/ssa/_gen/generic.rules b/src/cmd/compile/internal/ssa/_gen/generic.rules index 96f5f2cad2..84cf50a964 100644 --- a/src/cmd/compile/internal/ssa/_gen/generic.rules +++ b/src/cmd/compile/internal/ssa/_gen/generic.rules @@ -289,20 +289,34 @@ (NeqB (ConstBool [true]) x) => (Not x) (NeqB (Not x) y) => (EqB x y) -(Eq64 (Const64 [c]) (Add64 (Const64 [d]) x)) => (Eq64 (Const64 [c-d]) x) -(Eq32 (Const32 [c]) (Add32 (Const32 [d]) x)) => (Eq32 (Const32 [c-d]) x) -(Eq16 (Const16 [c]) (Add16 (Const16 [d]) x)) => (Eq16 (Const16 [c-d]) x) -(Eq8 (Const8 [c]) (Add8 (Const8 [d]) x)) => (Eq8 (Const8 [c-d]) x) - -(Neq64 (Const64 [c]) (Add64 (Const64 [d]) x)) => (Neq64 (Const64 [c-d]) x) -(Neq32 (Const32 [c]) (Add32 (Const32 [d]) x)) => (Neq32 (Const32 [c-d]) x) -(Neq16 (Const16 [c]) (Add16 (Const16 [d]) x)) => (Neq16 (Const16 [c-d]) x) -(Neq8 (Const8 [c]) (Add8 (Const8 [d]) x)) => (Neq8 (Const8 [c-d]) x) - (CondSelect x _ (ConstBool [true ])) => x (CondSelect _ y (ConstBool [false])) => y (CondSelect x x _) => x +// fold eq / neq between a constant and a compile time bijective operation into the constant. +(Eq(64|32|16|8) (Const(64|32|16|8) [c]) o:(Add(64|32|16|8) (Const(64|32|16|8) [d]) x)) && o.Uses == 1 => (Eq(64|32|16|8) (Const(64|32|16|8) [c-d]) x) +(Neq(64|32|16|8) (Const(64|32|16|8) [c]) o:(Add(64|32|16|8) (Const(64|32|16|8) [d]) x)) && o.Uses == 1 => (Neq(64|32|16|8) (Const(64|32|16|8) [c-d]) x) + +(Eq(64|32|16|8) (Const(64|32|16|8) [c]) o:(Sub(64|32|16|8) x (Const(64|32|16|8) [d]))) && o.Uses == 1 => (Eq(64|32|16|8) (Const(64|32|16|8) [c+d]) x) +(Neq(64|32|16|8) (Const(64|32|16|8) [c]) o:(Sub(64|32|16|8) x (Const(64|32|16|8) [d]))) && o.Uses == 1 => (Neq(64|32|16|8) (Const(64|32|16|8) [c+d]) x) + +(Eq(64|32|16|8) (Const(64|32|16|8) [c]) o:(Sub(64|32|16|8) (Const(64|32|16|8) [d]) x)) && o.Uses == 1 => (Eq(64|32|16|8) (Const(64|32|16|8) [d-c]) x) +(Neq(64|32|16|8) (Const(64|32|16|8) [c]) o:(Sub(64|32|16|8) (Const(64|32|16|8) [d]) x)) && o.Uses == 1 => (Neq(64|32|16|8) (Const(64|32|16|8) [d-c]) x) + +(Eq(64|32|16|8) (Const(64|32|16|8) [c]) o:(Xor(64|32|16|8) (Const(64|32|16|8) [d]) x)) && o.Uses == 1 => (Eq(64|32|16|8) (Const(64|32|16|8) [d^c]) x) +(Neq(64|32|16|8) (Const(64|32|16|8) [c]) o:(Xor(64|32|16|8) (Const(64|32|16|8) [d]) x)) && o.Uses == 1 => (Neq(64|32|16|8) (Const(64|32|16|8) [d^c]) x) + +(Eq(64|32|16|8) (Const(64|32|16|8) [c]) o:(Com(64|32|16|8) x)) && o.Uses == 1 => (Eq(64|32|16|8) (Const(64|32|16|8) [^c]) x) +(Neq(64|32|16|8) (Const(64|32|16|8) [c]) o:(Com(64|32|16|8) x)) && o.Uses == 1 => (Neq(64|32|16|8) (Const(64|32|16|8) [^c]) x) + +(Eq(64|32|16|8) (Const(64|32|16|8) [c]) o:(Neg(64|32|16|8) x)) && o.Uses == 1 => (Eq(64|32|16|8) (Const(64|32|16|8) [-c]) x) +(Neq(64|32|16|8) (Const(64|32|16|8) [c]) o:(Neg(64|32|16|8) x)) && o.Uses == 1 => (Neq(64|32|16|8) (Const(64|32|16|8) [-c]) x) + +((Eq|Neq)64 (Const64 [c]) o:(Mul64 (Const64 [d]) x)) && uint64(d)%2 == 1 && o.Uses == 1 => ((Eq|Neq)64 (Const64 [int64(uint64(c) * modularMultiplicativeInverse(uint64(d))) ]) x) +((Eq|Neq)32 (Const32 [c]) o:(Mul32 (Const32 [d]) x)) && uint32(d)%2 == 1 && o.Uses == 1 => ((Eq|Neq)32 (Const32 [int32(uint32(c) * uint32(modularMultiplicativeInverse(uint64(d))))]) x) +((Eq|Neq)16 (Const16 [c]) o:(Mul16 (Const16 [d]) x)) && uint16(d)%2 == 1 && o.Uses == 1 => ((Eq|Neq)16 (Const16 [int16(uint16(c) * uint16(modularMultiplicativeInverse(uint64(d))))]) x) +((Eq|Neq)8 (Const8 [c]) o:(Mul8 (Const8 [d]) x)) && uint8( d)%2 == 1 && o.Uses == 1 => ((Eq|Neq)8 (Const8 [int8( uint8( c) * uint8( modularMultiplicativeInverse(uint64(d))))]) x) + // signed integer range: ( c <= x && x (<|<=) d ) -> ( unsigned(x-c) (<|<=) unsigned(d-c) ) (AndB (Leq64 (Const64 [c]) x) ((Less|Leq)64 x (Const64 [d]))) && d >= c => ((Less|Leq)64U (Sub64 x (Const64 [c])) (Const64 [d-c])) (AndB (Leq32 (Const32 [c]) x) ((Less|Leq)32 x (Const32 [d]))) && d >= c => ((Less|Leq)32U (Sub32 x (Const32 [c])) (Const32 [d-c])) diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index e288725b69..4619faa48c 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -2855,3 +2855,19 @@ func addToSub(op Op) Op { panic(fmt.Sprintf("unexpected op %v", op)) } } + +func modularMultiplicativeInverse(x uint64) (y uint64) { + if x%2 != 1 { + panic("even numbers in a power-of-two modulus do not have a multiplicative inverse") + } + // we start with 3 bits of precision because each odd number is its own multiplicative inverse mod 8 + y = x // 3 bits + + // now use the Newton-Raphson method to double the number of correct bits in each iteration. + y *= 2 - x*y // 6 bits + y *= 2 - x*y // 12 bits + y *= 2 - x*y // 24 bits + y *= 2 - x*y // 48 bits + y *= 2 - x*y // 96 bits; good enough + return +} diff --git a/src/cmd/compile/internal/ssa/rewrite_test.go b/src/cmd/compile/internal/ssa/rewrite_test.go index 870abed56e..02c0cd2780 100644 --- a/src/cmd/compile/internal/ssa/rewrite_test.go +++ b/src/cmd/compile/internal/ssa/rewrite_test.go @@ -359,3 +359,20 @@ func TestDisjointTypesRun(t *testing.T) { t.Errorf("disjointTypes gives an incorrect answer that leads to an incorrect optimization.") } } + +func TestModularMultiplicativeInverse(t *testing.T) { + t.Parallel() + + // We've got 63 bits of phase space for the Multiplier + // Needless to say this is too much to bruteforce here. + // I've randomly picked a range of 1<<24 because it runs in 0.03s on my machine which isn't too slow. + // We test both sides of the wrapping point (0 and math.MaxUint64) since we need to test something and it's a usual place to have bugs. + const halfRange = 1 << 23 + for i := -int64(halfRange) - 1; i < halfRange; i += 2 { // odd only, a bit after to a bit before the wrapping point + mmi := modularMultiplicativeInverse(uint64(i)) + + if uint64(i)*mmi != 1 { + t.Errorf("%d * modularMultiplicativeInverse(%d) != 1; modularMultiplicativeInverse(%d) == %d", i, i, i, mmi) + } + } +} diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index 56411cacd2..e39e08d7ae 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -8973,7 +8973,8 @@ func rewriteValuegeneric_OpEq16(v *Value) bool { v.AuxInt = boolToAuxInt(true) return true } - // match: (Eq16 (Const16 [c]) (Add16 (Const16 [d]) x)) + // match: (Eq16 (Const16 [c]) o:(Add16 (Const16 [d]) x)) + // cond: o.Uses == 1 // result: (Eq16 (Const16 [c-d]) x) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { @@ -8982,18 +8983,22 @@ func rewriteValuegeneric_OpEq16(v *Value) bool { } t := v_0.Type c := auxIntToInt16(v_0.AuxInt) - if v_1.Op != OpAdd16 { + o := v_1 + if o.Op != OpAdd16 { continue } - _ = v_1.Args[1] - v_1_0 := v_1.Args[0] - v_1_1 := v_1.Args[1] - for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 { - if v_1_0.Op != OpConst16 || v_1_0.Type != t { + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst16 { + continue + } + d := auxIntToInt16(o_0.AuxInt) + x := o_1 + if !(o.Uses == 1) { continue } - d := auxIntToInt16(v_1_0.AuxInt) - x := v_1_1 v.reset(OpEq16) v0 := b.NewValue0(v.Pos, OpConst16, t) v0.AuxInt = int16ToAuxInt(c - d) @@ -9003,6 +9008,191 @@ func rewriteValuegeneric_OpEq16(v *Value) bool { } break } + // match: (Eq16 (Const16 [c]) o:(Sub16 x (Const16 [d]))) + // cond: o.Uses == 1 + // result: (Eq16 (Const16 [c+d]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst16 { + continue + } + t := v_0.Type + c := auxIntToInt16(v_0.AuxInt) + o := v_1 + if o.Op != OpSub16 { + continue + } + _ = o.Args[1] + x := o.Args[0] + o_1 := o.Args[1] + if o_1.Op != OpConst16 { + continue + } + d := auxIntToInt16(o_1.AuxInt) + if !(o.Uses == 1) { + continue + } + v.reset(OpEq16) + v0 := b.NewValue0(v.Pos, OpConst16, t) + v0.AuxInt = int16ToAuxInt(c + d) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Eq16 (Const16 [c]) o:(Sub16 (Const16 [d]) x)) + // cond: o.Uses == 1 + // result: (Eq16 (Const16 [d-c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst16 { + continue + } + t := v_0.Type + c := auxIntToInt16(v_0.AuxInt) + o := v_1 + if o.Op != OpSub16 { + continue + } + x := o.Args[1] + o_0 := o.Args[0] + if o_0.Op != OpConst16 { + continue + } + d := auxIntToInt16(o_0.AuxInt) + if !(o.Uses == 1) { + continue + } + v.reset(OpEq16) + v0 := b.NewValue0(v.Pos, OpConst16, t) + v0.AuxInt = int16ToAuxInt(d - c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Eq16 (Const16 [c]) o:(Xor16 (Const16 [d]) x)) + // cond: o.Uses == 1 + // result: (Eq16 (Const16 [d^c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst16 { + continue + } + t := v_0.Type + c := auxIntToInt16(v_0.AuxInt) + o := v_1 + if o.Op != OpXor16 { + continue + } + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst16 { + continue + } + d := auxIntToInt16(o_0.AuxInt) + x := o_1 + if !(o.Uses == 1) { + continue + } + v.reset(OpEq16) + v0 := b.NewValue0(v.Pos, OpConst16, t) + v0.AuxInt = int16ToAuxInt(d ^ c) + v.AddArg2(v0, x) + return true + } + } + break + } + // match: (Eq16 (Const16 [c]) o:(Com16 x)) + // cond: o.Uses == 1 + // result: (Eq16 (Const16 [^c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst16 { + continue + } + t := v_0.Type + c := auxIntToInt16(v_0.AuxInt) + o := v_1 + if o.Op != OpCom16 { + continue + } + x := o.Args[0] + if !(o.Uses == 1) { + continue + } + v.reset(OpEq16) + v0 := b.NewValue0(v.Pos, OpConst16, t) + v0.AuxInt = int16ToAuxInt(^c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Eq16 (Const16 [c]) o:(Neg16 x)) + // cond: o.Uses == 1 + // result: (Eq16 (Const16 [-c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst16 { + continue + } + t := v_0.Type + c := auxIntToInt16(v_0.AuxInt) + o := v_1 + if o.Op != OpNeg16 { + continue + } + x := o.Args[0] + if !(o.Uses == 1) { + continue + } + v.reset(OpEq16) + v0 := b.NewValue0(v.Pos, OpConst16, t) + v0.AuxInt = int16ToAuxInt(-c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Eq16 (Const16 [c]) o:(Mul16 (Const16 [d]) x)) + // cond: uint16(d)%2 == 1 && o.Uses == 1 + // result: (Eq16 (Const16 [int16(uint16(c) * uint16(modularMultiplicativeInverse(uint64(d))))]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst16 { + continue + } + t := v_0.Type + c := auxIntToInt16(v_0.AuxInt) + o := v_1 + if o.Op != OpMul16 { + continue + } + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst16 { + continue + } + d := auxIntToInt16(o_0.AuxInt) + x := o_1 + if !(uint16(d)%2 == 1 && o.Uses == 1) { + continue + } + v.reset(OpEq16) + v0 := b.NewValue0(v.Pos, OpConst16, t) + v0.AuxInt = int16ToAuxInt(int16(uint16(c) * uint16(modularMultiplicativeInverse(uint64(d))))) + v.AddArg2(v0, x) + return true + } + } + break + } // match: (Eq16 (Const16 [c]) (Const16 [d])) // result: (ConstBool [c == d]) for { @@ -9197,7 +9387,8 @@ func rewriteValuegeneric_OpEq32(v *Value) bool { v.AuxInt = boolToAuxInt(true) return true } - // match: (Eq32 (Const32 [c]) (Add32 (Const32 [d]) x)) + // match: (Eq32 (Const32 [c]) o:(Add32 (Const32 [d]) x)) + // cond: o.Uses == 1 // result: (Eq32 (Const32 [c-d]) x) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { @@ -9206,18 +9397,22 @@ func rewriteValuegeneric_OpEq32(v *Value) bool { } t := v_0.Type c := auxIntToInt32(v_0.AuxInt) - if v_1.Op != OpAdd32 { + o := v_1 + if o.Op != OpAdd32 { continue } - _ = v_1.Args[1] - v_1_0 := v_1.Args[0] - v_1_1 := v_1.Args[1] - for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 { - if v_1_0.Op != OpConst32 || v_1_0.Type != t { + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst32 { + continue + } + d := auxIntToInt32(o_0.AuxInt) + x := o_1 + if !(o.Uses == 1) { continue } - d := auxIntToInt32(v_1_0.AuxInt) - x := v_1_1 v.reset(OpEq32) v0 := b.NewValue0(v.Pos, OpConst32, t) v0.AuxInt = int32ToAuxInt(c - d) @@ -9227,6 +9422,191 @@ func rewriteValuegeneric_OpEq32(v *Value) bool { } break } + // match: (Eq32 (Const32 [c]) o:(Sub32 x (Const32 [d]))) + // cond: o.Uses == 1 + // result: (Eq32 (Const32 [c+d]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst32 { + continue + } + t := v_0.Type + c := auxIntToInt32(v_0.AuxInt) + o := v_1 + if o.Op != OpSub32 { + continue + } + _ = o.Args[1] + x := o.Args[0] + o_1 := o.Args[1] + if o_1.Op != OpConst32 { + continue + } + d := auxIntToInt32(o_1.AuxInt) + if !(o.Uses == 1) { + continue + } + v.reset(OpEq32) + v0 := b.NewValue0(v.Pos, OpConst32, t) + v0.AuxInt = int32ToAuxInt(c + d) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Eq32 (Const32 [c]) o:(Sub32 (Const32 [d]) x)) + // cond: o.Uses == 1 + // result: (Eq32 (Const32 [d-c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst32 { + continue + } + t := v_0.Type + c := auxIntToInt32(v_0.AuxInt) + o := v_1 + if o.Op != OpSub32 { + continue + } + x := o.Args[1] + o_0 := o.Args[0] + if o_0.Op != OpConst32 { + continue + } + d := auxIntToInt32(o_0.AuxInt) + if !(o.Uses == 1) { + continue + } + v.reset(OpEq32) + v0 := b.NewValue0(v.Pos, OpConst32, t) + v0.AuxInt = int32ToAuxInt(d - c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Eq32 (Const32 [c]) o:(Xor32 (Const32 [d]) x)) + // cond: o.Uses == 1 + // result: (Eq32 (Const32 [d^c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst32 { + continue + } + t := v_0.Type + c := auxIntToInt32(v_0.AuxInt) + o := v_1 + if o.Op != OpXor32 { + continue + } + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst32 { + continue + } + d := auxIntToInt32(o_0.AuxInt) + x := o_1 + if !(o.Uses == 1) { + continue + } + v.reset(OpEq32) + v0 := b.NewValue0(v.Pos, OpConst32, t) + v0.AuxInt = int32ToAuxInt(d ^ c) + v.AddArg2(v0, x) + return true + } + } + break + } + // match: (Eq32 (Const32 [c]) o:(Com32 x)) + // cond: o.Uses == 1 + // result: (Eq32 (Const32 [^c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst32 { + continue + } + t := v_0.Type + c := auxIntToInt32(v_0.AuxInt) + o := v_1 + if o.Op != OpCom32 { + continue + } + x := o.Args[0] + if !(o.Uses == 1) { + continue + } + v.reset(OpEq32) + v0 := b.NewValue0(v.Pos, OpConst32, t) + v0.AuxInt = int32ToAuxInt(^c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Eq32 (Const32 [c]) o:(Neg32 x)) + // cond: o.Uses == 1 + // result: (Eq32 (Const32 [-c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst32 { + continue + } + t := v_0.Type + c := auxIntToInt32(v_0.AuxInt) + o := v_1 + if o.Op != OpNeg32 { + continue + } + x := o.Args[0] + if !(o.Uses == 1) { + continue + } + v.reset(OpEq32) + v0 := b.NewValue0(v.Pos, OpConst32, t) + v0.AuxInt = int32ToAuxInt(-c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Eq32 (Const32 [c]) o:(Mul32 (Const32 [d]) x)) + // cond: uint32(d)%2 == 1 && o.Uses == 1 + // result: (Eq32 (Const32 [int32(uint32(c) * uint32(modularMultiplicativeInverse(uint64(d))))]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst32 { + continue + } + t := v_0.Type + c := auxIntToInt32(v_0.AuxInt) + o := v_1 + if o.Op != OpMul32 { + continue + } + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst32 { + continue + } + d := auxIntToInt32(o_0.AuxInt) + x := o_1 + if !(uint32(d)%2 == 1 && o.Uses == 1) { + continue + } + v.reset(OpEq32) + v0 := b.NewValue0(v.Pos, OpConst32, t) + v0.AuxInt = int32ToAuxInt(int32(uint32(c) * uint32(modularMultiplicativeInverse(uint64(d))))) + v.AddArg2(v0, x) + return true + } + } + break + } // match: (Eq32 (Const32 [c]) (Const32 [d])) // result: (ConstBool [c == d]) for { @@ -9380,7 +9760,8 @@ func rewriteValuegeneric_OpEq64(v *Value) bool { v.AuxInt = boolToAuxInt(true) return true } - // match: (Eq64 (Const64 [c]) (Add64 (Const64 [d]) x)) + // match: (Eq64 (Const64 [c]) o:(Add64 (Const64 [d]) x)) + // cond: o.Uses == 1 // result: (Eq64 (Const64 [c-d]) x) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { @@ -9389,18 +9770,22 @@ func rewriteValuegeneric_OpEq64(v *Value) bool { } t := v_0.Type c := auxIntToInt64(v_0.AuxInt) - if v_1.Op != OpAdd64 { + o := v_1 + if o.Op != OpAdd64 { continue } - _ = v_1.Args[1] - v_1_0 := v_1.Args[0] - v_1_1 := v_1.Args[1] - for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 { - if v_1_0.Op != OpConst64 || v_1_0.Type != t { + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst64 { + continue + } + d := auxIntToInt64(o_0.AuxInt) + x := o_1 + if !(o.Uses == 1) { continue } - d := auxIntToInt64(v_1_0.AuxInt) - x := v_1_1 v.reset(OpEq64) v0 := b.NewValue0(v.Pos, OpConst64, t) v0.AuxInt = int64ToAuxInt(c - d) @@ -9410,6 +9795,191 @@ func rewriteValuegeneric_OpEq64(v *Value) bool { } break } + // match: (Eq64 (Const64 [c]) o:(Sub64 x (Const64 [d]))) + // cond: o.Uses == 1 + // result: (Eq64 (Const64 [c+d]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst64 { + continue + } + t := v_0.Type + c := auxIntToInt64(v_0.AuxInt) + o := v_1 + if o.Op != OpSub64 { + continue + } + _ = o.Args[1] + x := o.Args[0] + o_1 := o.Args[1] + if o_1.Op != OpConst64 { + continue + } + d := auxIntToInt64(o_1.AuxInt) + if !(o.Uses == 1) { + continue + } + v.reset(OpEq64) + v0 := b.NewValue0(v.Pos, OpConst64, t) + v0.AuxInt = int64ToAuxInt(c + d) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Eq64 (Const64 [c]) o:(Sub64 (Const64 [d]) x)) + // cond: o.Uses == 1 + // result: (Eq64 (Const64 [d-c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst64 { + continue + } + t := v_0.Type + c := auxIntToInt64(v_0.AuxInt) + o := v_1 + if o.Op != OpSub64 { + continue + } + x := o.Args[1] + o_0 := o.Args[0] + if o_0.Op != OpConst64 { + continue + } + d := auxIntToInt64(o_0.AuxInt) + if !(o.Uses == 1) { + continue + } + v.reset(OpEq64) + v0 := b.NewValue0(v.Pos, OpConst64, t) + v0.AuxInt = int64ToAuxInt(d - c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Eq64 (Const64 [c]) o:(Xor64 (Const64 [d]) x)) + // cond: o.Uses == 1 + // result: (Eq64 (Const64 [d^c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst64 { + continue + } + t := v_0.Type + c := auxIntToInt64(v_0.AuxInt) + o := v_1 + if o.Op != OpXor64 { + continue + } + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst64 { + continue + } + d := auxIntToInt64(o_0.AuxInt) + x := o_1 + if !(o.Uses == 1) { + continue + } + v.reset(OpEq64) + v0 := b.NewValue0(v.Pos, OpConst64, t) + v0.AuxInt = int64ToAuxInt(d ^ c) + v.AddArg2(v0, x) + return true + } + } + break + } + // match: (Eq64 (Const64 [c]) o:(Com64 x)) + // cond: o.Uses == 1 + // result: (Eq64 (Const64 [^c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst64 { + continue + } + t := v_0.Type + c := auxIntToInt64(v_0.AuxInt) + o := v_1 + if o.Op != OpCom64 { + continue + } + x := o.Args[0] + if !(o.Uses == 1) { + continue + } + v.reset(OpEq64) + v0 := b.NewValue0(v.Pos, OpConst64, t) + v0.AuxInt = int64ToAuxInt(^c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Eq64 (Const64 [c]) o:(Neg64 x)) + // cond: o.Uses == 1 + // result: (Eq64 (Const64 [-c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst64 { + continue + } + t := v_0.Type + c := auxIntToInt64(v_0.AuxInt) + o := v_1 + if o.Op != OpNeg64 { + continue + } + x := o.Args[0] + if !(o.Uses == 1) { + continue + } + v.reset(OpEq64) + v0 := b.NewValue0(v.Pos, OpConst64, t) + v0.AuxInt = int64ToAuxInt(-c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Eq64 (Const64 [c]) o:(Mul64 (Const64 [d]) x)) + // cond: uint64(d)%2 == 1 && o.Uses == 1 + // result: (Eq64 (Const64 [int64(uint64(c) * modularMultiplicativeInverse(uint64(d))) ]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst64 { + continue + } + t := v_0.Type + c := auxIntToInt64(v_0.AuxInt) + o := v_1 + if o.Op != OpMul64 { + continue + } + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst64 { + continue + } + d := auxIntToInt64(o_0.AuxInt) + x := o_1 + if !(uint64(d)%2 == 1 && o.Uses == 1) { + continue + } + v.reset(OpEq64) + v0 := b.NewValue0(v.Pos, OpConst64, t) + v0.AuxInt = int64ToAuxInt(int64(uint64(c) * modularMultiplicativeInverse(uint64(d)))) + v.AddArg2(v0, x) + return true + } + } + break + } // match: (Eq64 (Const64 [c]) (Const64 [d])) // result: (ConstBool [c == d]) for { @@ -9565,7 +10135,8 @@ func rewriteValuegeneric_OpEq8(v *Value) bool { v.AuxInt = boolToAuxInt(true) return true } - // match: (Eq8 (Const8 [c]) (Add8 (Const8 [d]) x)) + // match: (Eq8 (Const8 [c]) o:(Add8 (Const8 [d]) x)) + // cond: o.Uses == 1 // result: (Eq8 (Const8 [c-d]) x) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { @@ -9574,18 +10145,22 @@ func rewriteValuegeneric_OpEq8(v *Value) bool { } t := v_0.Type c := auxIntToInt8(v_0.AuxInt) - if v_1.Op != OpAdd8 { + o := v_1 + if o.Op != OpAdd8 { continue } - _ = v_1.Args[1] - v_1_0 := v_1.Args[0] - v_1_1 := v_1.Args[1] - for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 { - if v_1_0.Op != OpConst8 || v_1_0.Type != t { + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst8 { + continue + } + d := auxIntToInt8(o_0.AuxInt) + x := o_1 + if !(o.Uses == 1) { continue } - d := auxIntToInt8(v_1_0.AuxInt) - x := v_1_1 v.reset(OpEq8) v0 := b.NewValue0(v.Pos, OpConst8, t) v0.AuxInt = int8ToAuxInt(c - d) @@ -9595,6 +10170,191 @@ func rewriteValuegeneric_OpEq8(v *Value) bool { } break } + // match: (Eq8 (Const8 [c]) o:(Sub8 x (Const8 [d]))) + // cond: o.Uses == 1 + // result: (Eq8 (Const8 [c+d]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst8 { + continue + } + t := v_0.Type + c := auxIntToInt8(v_0.AuxInt) + o := v_1 + if o.Op != OpSub8 { + continue + } + _ = o.Args[1] + x := o.Args[0] + o_1 := o.Args[1] + if o_1.Op != OpConst8 { + continue + } + d := auxIntToInt8(o_1.AuxInt) + if !(o.Uses == 1) { + continue + } + v.reset(OpEq8) + v0 := b.NewValue0(v.Pos, OpConst8, t) + v0.AuxInt = int8ToAuxInt(c + d) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Eq8 (Const8 [c]) o:(Sub8 (Const8 [d]) x)) + // cond: o.Uses == 1 + // result: (Eq8 (Const8 [d-c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst8 { + continue + } + t := v_0.Type + c := auxIntToInt8(v_0.AuxInt) + o := v_1 + if o.Op != OpSub8 { + continue + } + x := o.Args[1] + o_0 := o.Args[0] + if o_0.Op != OpConst8 { + continue + } + d := auxIntToInt8(o_0.AuxInt) + if !(o.Uses == 1) { + continue + } + v.reset(OpEq8) + v0 := b.NewValue0(v.Pos, OpConst8, t) + v0.AuxInt = int8ToAuxInt(d - c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Eq8 (Const8 [c]) o:(Xor8 (Const8 [d]) x)) + // cond: o.Uses == 1 + // result: (Eq8 (Const8 [d^c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst8 { + continue + } + t := v_0.Type + c := auxIntToInt8(v_0.AuxInt) + o := v_1 + if o.Op != OpXor8 { + continue + } + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst8 { + continue + } + d := auxIntToInt8(o_0.AuxInt) + x := o_1 + if !(o.Uses == 1) { + continue + } + v.reset(OpEq8) + v0 := b.NewValue0(v.Pos, OpConst8, t) + v0.AuxInt = int8ToAuxInt(d ^ c) + v.AddArg2(v0, x) + return true + } + } + break + } + // match: (Eq8 (Const8 [c]) o:(Com8 x)) + // cond: o.Uses == 1 + // result: (Eq8 (Const8 [^c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst8 { + continue + } + t := v_0.Type + c := auxIntToInt8(v_0.AuxInt) + o := v_1 + if o.Op != OpCom8 { + continue + } + x := o.Args[0] + if !(o.Uses == 1) { + continue + } + v.reset(OpEq8) + v0 := b.NewValue0(v.Pos, OpConst8, t) + v0.AuxInt = int8ToAuxInt(^c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Eq8 (Const8 [c]) o:(Neg8 x)) + // cond: o.Uses == 1 + // result: (Eq8 (Const8 [-c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst8 { + continue + } + t := v_0.Type + c := auxIntToInt8(v_0.AuxInt) + o := v_1 + if o.Op != OpNeg8 { + continue + } + x := o.Args[0] + if !(o.Uses == 1) { + continue + } + v.reset(OpEq8) + v0 := b.NewValue0(v.Pos, OpConst8, t) + v0.AuxInt = int8ToAuxInt(-c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Eq8 (Const8 [c]) o:(Mul8 (Const8 [d]) x)) + // cond: uint8( d)%2 == 1 && o.Uses == 1 + // result: (Eq8 (Const8 [int8( uint8( c) * uint8( modularMultiplicativeInverse(uint64(d))))]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst8 { + continue + } + t := v_0.Type + c := auxIntToInt8(v_0.AuxInt) + o := v_1 + if o.Op != OpMul8 { + continue + } + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst8 { + continue + } + d := auxIntToInt8(o_0.AuxInt) + x := o_1 + if !(uint8(d)%2 == 1 && o.Uses == 1) { + continue + } + v.reset(OpEq8) + v0 := b.NewValue0(v.Pos, OpConst8, t) + v0.AuxInt = int8ToAuxInt(int8(uint8(c) * uint8(modularMultiplicativeInverse(uint64(d))))) + v.AddArg2(v0, x) + return true + } + } + break + } // match: (Eq8 (Const8 [c]) (Const8 [d])) // result: (ConstBool [c == d]) for { @@ -20220,7 +20980,8 @@ func rewriteValuegeneric_OpNeq16(v *Value) bool { v.AuxInt = boolToAuxInt(false) return true } - // match: (Neq16 (Const16 [c]) (Add16 (Const16 [d]) x)) + // match: (Neq16 (Const16 [c]) o:(Add16 (Const16 [d]) x)) + // cond: o.Uses == 1 // result: (Neq16 (Const16 [c-d]) x) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { @@ -20229,18 +20990,22 @@ func rewriteValuegeneric_OpNeq16(v *Value) bool { } t := v_0.Type c := auxIntToInt16(v_0.AuxInt) - if v_1.Op != OpAdd16 { + o := v_1 + if o.Op != OpAdd16 { continue } - _ = v_1.Args[1] - v_1_0 := v_1.Args[0] - v_1_1 := v_1.Args[1] - for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 { - if v_1_0.Op != OpConst16 || v_1_0.Type != t { + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst16 { + continue + } + d := auxIntToInt16(o_0.AuxInt) + x := o_1 + if !(o.Uses == 1) { continue } - d := auxIntToInt16(v_1_0.AuxInt) - x := v_1_1 v.reset(OpNeq16) v0 := b.NewValue0(v.Pos, OpConst16, t) v0.AuxInt = int16ToAuxInt(c - d) @@ -20250,6 +21015,191 @@ func rewriteValuegeneric_OpNeq16(v *Value) bool { } break } + // match: (Neq16 (Const16 [c]) o:(Sub16 x (Const16 [d]))) + // cond: o.Uses == 1 + // result: (Neq16 (Const16 [c+d]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst16 { + continue + } + t := v_0.Type + c := auxIntToInt16(v_0.AuxInt) + o := v_1 + if o.Op != OpSub16 { + continue + } + _ = o.Args[1] + x := o.Args[0] + o_1 := o.Args[1] + if o_1.Op != OpConst16 { + continue + } + d := auxIntToInt16(o_1.AuxInt) + if !(o.Uses == 1) { + continue + } + v.reset(OpNeq16) + v0 := b.NewValue0(v.Pos, OpConst16, t) + v0.AuxInt = int16ToAuxInt(c + d) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Neq16 (Const16 [c]) o:(Sub16 (Const16 [d]) x)) + // cond: o.Uses == 1 + // result: (Neq16 (Const16 [d-c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst16 { + continue + } + t := v_0.Type + c := auxIntToInt16(v_0.AuxInt) + o := v_1 + if o.Op != OpSub16 { + continue + } + x := o.Args[1] + o_0 := o.Args[0] + if o_0.Op != OpConst16 { + continue + } + d := auxIntToInt16(o_0.AuxInt) + if !(o.Uses == 1) { + continue + } + v.reset(OpNeq16) + v0 := b.NewValue0(v.Pos, OpConst16, t) + v0.AuxInt = int16ToAuxInt(d - c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Neq16 (Const16 [c]) o:(Xor16 (Const16 [d]) x)) + // cond: o.Uses == 1 + // result: (Neq16 (Const16 [d^c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst16 { + continue + } + t := v_0.Type + c := auxIntToInt16(v_0.AuxInt) + o := v_1 + if o.Op != OpXor16 { + continue + } + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst16 { + continue + } + d := auxIntToInt16(o_0.AuxInt) + x := o_1 + if !(o.Uses == 1) { + continue + } + v.reset(OpNeq16) + v0 := b.NewValue0(v.Pos, OpConst16, t) + v0.AuxInt = int16ToAuxInt(d ^ c) + v.AddArg2(v0, x) + return true + } + } + break + } + // match: (Neq16 (Const16 [c]) o:(Com16 x)) + // cond: o.Uses == 1 + // result: (Neq16 (Const16 [^c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst16 { + continue + } + t := v_0.Type + c := auxIntToInt16(v_0.AuxInt) + o := v_1 + if o.Op != OpCom16 { + continue + } + x := o.Args[0] + if !(o.Uses == 1) { + continue + } + v.reset(OpNeq16) + v0 := b.NewValue0(v.Pos, OpConst16, t) + v0.AuxInt = int16ToAuxInt(^c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Neq16 (Const16 [c]) o:(Neg16 x)) + // cond: o.Uses == 1 + // result: (Neq16 (Const16 [-c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst16 { + continue + } + t := v_0.Type + c := auxIntToInt16(v_0.AuxInt) + o := v_1 + if o.Op != OpNeg16 { + continue + } + x := o.Args[0] + if !(o.Uses == 1) { + continue + } + v.reset(OpNeq16) + v0 := b.NewValue0(v.Pos, OpConst16, t) + v0.AuxInt = int16ToAuxInt(-c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Neq16 (Const16 [c]) o:(Mul16 (Const16 [d]) x)) + // cond: uint16(d)%2 == 1 && o.Uses == 1 + // result: (Neq16 (Const16 [int16(uint16(c) * uint16(modularMultiplicativeInverse(uint64(d))))]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst16 { + continue + } + t := v_0.Type + c := auxIntToInt16(v_0.AuxInt) + o := v_1 + if o.Op != OpMul16 { + continue + } + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst16 { + continue + } + d := auxIntToInt16(o_0.AuxInt) + x := o_1 + if !(uint16(d)%2 == 1 && o.Uses == 1) { + continue + } + v.reset(OpNeq16) + v0 := b.NewValue0(v.Pos, OpConst16, t) + v0.AuxInt = int16ToAuxInt(int16(uint16(c) * uint16(modularMultiplicativeInverse(uint64(d))))) + v.AddArg2(v0, x) + return true + } + } + break + } // match: (Neq16 (Const16 [c]) (Const16 [d])) // result: (ConstBool [c != d]) for { @@ -20380,7 +21330,8 @@ func rewriteValuegeneric_OpNeq32(v *Value) bool { v.AuxInt = boolToAuxInt(false) return true } - // match: (Neq32 (Const32 [c]) (Add32 (Const32 [d]) x)) + // match: (Neq32 (Const32 [c]) o:(Add32 (Const32 [d]) x)) + // cond: o.Uses == 1 // result: (Neq32 (Const32 [c-d]) x) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { @@ -20389,18 +21340,22 @@ func rewriteValuegeneric_OpNeq32(v *Value) bool { } t := v_0.Type c := auxIntToInt32(v_0.AuxInt) - if v_1.Op != OpAdd32 { + o := v_1 + if o.Op != OpAdd32 { continue } - _ = v_1.Args[1] - v_1_0 := v_1.Args[0] - v_1_1 := v_1.Args[1] - for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 { - if v_1_0.Op != OpConst32 || v_1_0.Type != t { + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst32 { + continue + } + d := auxIntToInt32(o_0.AuxInt) + x := o_1 + if !(o.Uses == 1) { continue } - d := auxIntToInt32(v_1_0.AuxInt) - x := v_1_1 v.reset(OpNeq32) v0 := b.NewValue0(v.Pos, OpConst32, t) v0.AuxInt = int32ToAuxInt(c - d) @@ -20410,6 +21365,191 @@ func rewriteValuegeneric_OpNeq32(v *Value) bool { } break } + // match: (Neq32 (Const32 [c]) o:(Sub32 x (Const32 [d]))) + // cond: o.Uses == 1 + // result: (Neq32 (Const32 [c+d]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst32 { + continue + } + t := v_0.Type + c := auxIntToInt32(v_0.AuxInt) + o := v_1 + if o.Op != OpSub32 { + continue + } + _ = o.Args[1] + x := o.Args[0] + o_1 := o.Args[1] + if o_1.Op != OpConst32 { + continue + } + d := auxIntToInt32(o_1.AuxInt) + if !(o.Uses == 1) { + continue + } + v.reset(OpNeq32) + v0 := b.NewValue0(v.Pos, OpConst32, t) + v0.AuxInt = int32ToAuxInt(c + d) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Neq32 (Const32 [c]) o:(Sub32 (Const32 [d]) x)) + // cond: o.Uses == 1 + // result: (Neq32 (Const32 [d-c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst32 { + continue + } + t := v_0.Type + c := auxIntToInt32(v_0.AuxInt) + o := v_1 + if o.Op != OpSub32 { + continue + } + x := o.Args[1] + o_0 := o.Args[0] + if o_0.Op != OpConst32 { + continue + } + d := auxIntToInt32(o_0.AuxInt) + if !(o.Uses == 1) { + continue + } + v.reset(OpNeq32) + v0 := b.NewValue0(v.Pos, OpConst32, t) + v0.AuxInt = int32ToAuxInt(d - c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Neq32 (Const32 [c]) o:(Xor32 (Const32 [d]) x)) + // cond: o.Uses == 1 + // result: (Neq32 (Const32 [d^c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst32 { + continue + } + t := v_0.Type + c := auxIntToInt32(v_0.AuxInt) + o := v_1 + if o.Op != OpXor32 { + continue + } + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst32 { + continue + } + d := auxIntToInt32(o_0.AuxInt) + x := o_1 + if !(o.Uses == 1) { + continue + } + v.reset(OpNeq32) + v0 := b.NewValue0(v.Pos, OpConst32, t) + v0.AuxInt = int32ToAuxInt(d ^ c) + v.AddArg2(v0, x) + return true + } + } + break + } + // match: (Neq32 (Const32 [c]) o:(Com32 x)) + // cond: o.Uses == 1 + // result: (Neq32 (Const32 [^c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst32 { + continue + } + t := v_0.Type + c := auxIntToInt32(v_0.AuxInt) + o := v_1 + if o.Op != OpCom32 { + continue + } + x := o.Args[0] + if !(o.Uses == 1) { + continue + } + v.reset(OpNeq32) + v0 := b.NewValue0(v.Pos, OpConst32, t) + v0.AuxInt = int32ToAuxInt(^c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Neq32 (Const32 [c]) o:(Neg32 x)) + // cond: o.Uses == 1 + // result: (Neq32 (Const32 [-c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst32 { + continue + } + t := v_0.Type + c := auxIntToInt32(v_0.AuxInt) + o := v_1 + if o.Op != OpNeg32 { + continue + } + x := o.Args[0] + if !(o.Uses == 1) { + continue + } + v.reset(OpNeq32) + v0 := b.NewValue0(v.Pos, OpConst32, t) + v0.AuxInt = int32ToAuxInt(-c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Neq32 (Const32 [c]) o:(Mul32 (Const32 [d]) x)) + // cond: uint32(d)%2 == 1 && o.Uses == 1 + // result: (Neq32 (Const32 [int32(uint32(c) * uint32(modularMultiplicativeInverse(uint64(d))))]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst32 { + continue + } + t := v_0.Type + c := auxIntToInt32(v_0.AuxInt) + o := v_1 + if o.Op != OpMul32 { + continue + } + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst32 { + continue + } + d := auxIntToInt32(o_0.AuxInt) + x := o_1 + if !(uint32(d)%2 == 1 && o.Uses == 1) { + continue + } + v.reset(OpNeq32) + v0 := b.NewValue0(v.Pos, OpConst32, t) + v0.AuxInt = int32ToAuxInt(int32(uint32(c) * uint32(modularMultiplicativeInverse(uint64(d))))) + v.AddArg2(v0, x) + return true + } + } + break + } // match: (Neq32 (Const32 [c]) (Const32 [d])) // result: (ConstBool [c != d]) for { @@ -20563,7 +21703,8 @@ func rewriteValuegeneric_OpNeq64(v *Value) bool { v.AuxInt = boolToAuxInt(false) return true } - // match: (Neq64 (Const64 [c]) (Add64 (Const64 [d]) x)) + // match: (Neq64 (Const64 [c]) o:(Add64 (Const64 [d]) x)) + // cond: o.Uses == 1 // result: (Neq64 (Const64 [c-d]) x) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { @@ -20572,18 +21713,22 @@ func rewriteValuegeneric_OpNeq64(v *Value) bool { } t := v_0.Type c := auxIntToInt64(v_0.AuxInt) - if v_1.Op != OpAdd64 { + o := v_1 + if o.Op != OpAdd64 { continue } - _ = v_1.Args[1] - v_1_0 := v_1.Args[0] - v_1_1 := v_1.Args[1] - for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 { - if v_1_0.Op != OpConst64 || v_1_0.Type != t { + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst64 { + continue + } + d := auxIntToInt64(o_0.AuxInt) + x := o_1 + if !(o.Uses == 1) { continue } - d := auxIntToInt64(v_1_0.AuxInt) - x := v_1_1 v.reset(OpNeq64) v0 := b.NewValue0(v.Pos, OpConst64, t) v0.AuxInt = int64ToAuxInt(c - d) @@ -20593,6 +21738,191 @@ func rewriteValuegeneric_OpNeq64(v *Value) bool { } break } + // match: (Neq64 (Const64 [c]) o:(Sub64 x (Const64 [d]))) + // cond: o.Uses == 1 + // result: (Neq64 (Const64 [c+d]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst64 { + continue + } + t := v_0.Type + c := auxIntToInt64(v_0.AuxInt) + o := v_1 + if o.Op != OpSub64 { + continue + } + _ = o.Args[1] + x := o.Args[0] + o_1 := o.Args[1] + if o_1.Op != OpConst64 { + continue + } + d := auxIntToInt64(o_1.AuxInt) + if !(o.Uses == 1) { + continue + } + v.reset(OpNeq64) + v0 := b.NewValue0(v.Pos, OpConst64, t) + v0.AuxInt = int64ToAuxInt(c + d) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Neq64 (Const64 [c]) o:(Sub64 (Const64 [d]) x)) + // cond: o.Uses == 1 + // result: (Neq64 (Const64 [d-c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst64 { + continue + } + t := v_0.Type + c := auxIntToInt64(v_0.AuxInt) + o := v_1 + if o.Op != OpSub64 { + continue + } + x := o.Args[1] + o_0 := o.Args[0] + if o_0.Op != OpConst64 { + continue + } + d := auxIntToInt64(o_0.AuxInt) + if !(o.Uses == 1) { + continue + } + v.reset(OpNeq64) + v0 := b.NewValue0(v.Pos, OpConst64, t) + v0.AuxInt = int64ToAuxInt(d - c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Neq64 (Const64 [c]) o:(Xor64 (Const64 [d]) x)) + // cond: o.Uses == 1 + // result: (Neq64 (Const64 [d^c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst64 { + continue + } + t := v_0.Type + c := auxIntToInt64(v_0.AuxInt) + o := v_1 + if o.Op != OpXor64 { + continue + } + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst64 { + continue + } + d := auxIntToInt64(o_0.AuxInt) + x := o_1 + if !(o.Uses == 1) { + continue + } + v.reset(OpNeq64) + v0 := b.NewValue0(v.Pos, OpConst64, t) + v0.AuxInt = int64ToAuxInt(d ^ c) + v.AddArg2(v0, x) + return true + } + } + break + } + // match: (Neq64 (Const64 [c]) o:(Com64 x)) + // cond: o.Uses == 1 + // result: (Neq64 (Const64 [^c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst64 { + continue + } + t := v_0.Type + c := auxIntToInt64(v_0.AuxInt) + o := v_1 + if o.Op != OpCom64 { + continue + } + x := o.Args[0] + if !(o.Uses == 1) { + continue + } + v.reset(OpNeq64) + v0 := b.NewValue0(v.Pos, OpConst64, t) + v0.AuxInt = int64ToAuxInt(^c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Neq64 (Const64 [c]) o:(Neg64 x)) + // cond: o.Uses == 1 + // result: (Neq64 (Const64 [-c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst64 { + continue + } + t := v_0.Type + c := auxIntToInt64(v_0.AuxInt) + o := v_1 + if o.Op != OpNeg64 { + continue + } + x := o.Args[0] + if !(o.Uses == 1) { + continue + } + v.reset(OpNeq64) + v0 := b.NewValue0(v.Pos, OpConst64, t) + v0.AuxInt = int64ToAuxInt(-c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Neq64 (Const64 [c]) o:(Mul64 (Const64 [d]) x)) + // cond: uint64(d)%2 == 1 && o.Uses == 1 + // result: (Neq64 (Const64 [int64(uint64(c) * modularMultiplicativeInverse(uint64(d))) ]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst64 { + continue + } + t := v_0.Type + c := auxIntToInt64(v_0.AuxInt) + o := v_1 + if o.Op != OpMul64 { + continue + } + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst64 { + continue + } + d := auxIntToInt64(o_0.AuxInt) + x := o_1 + if !(uint64(d)%2 == 1 && o.Uses == 1) { + continue + } + v.reset(OpNeq64) + v0 := b.NewValue0(v.Pos, OpConst64, t) + v0.AuxInt = int64ToAuxInt(int64(uint64(c) * modularMultiplicativeInverse(uint64(d)))) + v.AddArg2(v0, x) + return true + } + } + break + } // match: (Neq64 (Const64 [c]) (Const64 [d])) // result: (ConstBool [c != d]) for { @@ -20746,7 +22076,8 @@ func rewriteValuegeneric_OpNeq8(v *Value) bool { v.AuxInt = boolToAuxInt(false) return true } - // match: (Neq8 (Const8 [c]) (Add8 (Const8 [d]) x)) + // match: (Neq8 (Const8 [c]) o:(Add8 (Const8 [d]) x)) + // cond: o.Uses == 1 // result: (Neq8 (Const8 [c-d]) x) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { @@ -20755,18 +22086,22 @@ func rewriteValuegeneric_OpNeq8(v *Value) bool { } t := v_0.Type c := auxIntToInt8(v_0.AuxInt) - if v_1.Op != OpAdd8 { + o := v_1 + if o.Op != OpAdd8 { continue } - _ = v_1.Args[1] - v_1_0 := v_1.Args[0] - v_1_1 := v_1.Args[1] - for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 { - if v_1_0.Op != OpConst8 || v_1_0.Type != t { + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst8 { + continue + } + d := auxIntToInt8(o_0.AuxInt) + x := o_1 + if !(o.Uses == 1) { continue } - d := auxIntToInt8(v_1_0.AuxInt) - x := v_1_1 v.reset(OpNeq8) v0 := b.NewValue0(v.Pos, OpConst8, t) v0.AuxInt = int8ToAuxInt(c - d) @@ -20776,6 +22111,191 @@ func rewriteValuegeneric_OpNeq8(v *Value) bool { } break } + // match: (Neq8 (Const8 [c]) o:(Sub8 x (Const8 [d]))) + // cond: o.Uses == 1 + // result: (Neq8 (Const8 [c+d]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst8 { + continue + } + t := v_0.Type + c := auxIntToInt8(v_0.AuxInt) + o := v_1 + if o.Op != OpSub8 { + continue + } + _ = o.Args[1] + x := o.Args[0] + o_1 := o.Args[1] + if o_1.Op != OpConst8 { + continue + } + d := auxIntToInt8(o_1.AuxInt) + if !(o.Uses == 1) { + continue + } + v.reset(OpNeq8) + v0 := b.NewValue0(v.Pos, OpConst8, t) + v0.AuxInt = int8ToAuxInt(c + d) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Neq8 (Const8 [c]) o:(Sub8 (Const8 [d]) x)) + // cond: o.Uses == 1 + // result: (Neq8 (Const8 [d-c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst8 { + continue + } + t := v_0.Type + c := auxIntToInt8(v_0.AuxInt) + o := v_1 + if o.Op != OpSub8 { + continue + } + x := o.Args[1] + o_0 := o.Args[0] + if o_0.Op != OpConst8 { + continue + } + d := auxIntToInt8(o_0.AuxInt) + if !(o.Uses == 1) { + continue + } + v.reset(OpNeq8) + v0 := b.NewValue0(v.Pos, OpConst8, t) + v0.AuxInt = int8ToAuxInt(d - c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Neq8 (Const8 [c]) o:(Xor8 (Const8 [d]) x)) + // cond: o.Uses == 1 + // result: (Neq8 (Const8 [d^c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst8 { + continue + } + t := v_0.Type + c := auxIntToInt8(v_0.AuxInt) + o := v_1 + if o.Op != OpXor8 { + continue + } + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst8 { + continue + } + d := auxIntToInt8(o_0.AuxInt) + x := o_1 + if !(o.Uses == 1) { + continue + } + v.reset(OpNeq8) + v0 := b.NewValue0(v.Pos, OpConst8, t) + v0.AuxInt = int8ToAuxInt(d ^ c) + v.AddArg2(v0, x) + return true + } + } + break + } + // match: (Neq8 (Const8 [c]) o:(Com8 x)) + // cond: o.Uses == 1 + // result: (Neq8 (Const8 [^c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst8 { + continue + } + t := v_0.Type + c := auxIntToInt8(v_0.AuxInt) + o := v_1 + if o.Op != OpCom8 { + continue + } + x := o.Args[0] + if !(o.Uses == 1) { + continue + } + v.reset(OpNeq8) + v0 := b.NewValue0(v.Pos, OpConst8, t) + v0.AuxInt = int8ToAuxInt(^c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Neq8 (Const8 [c]) o:(Neg8 x)) + // cond: o.Uses == 1 + // result: (Neq8 (Const8 [-c]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst8 { + continue + } + t := v_0.Type + c := auxIntToInt8(v_0.AuxInt) + o := v_1 + if o.Op != OpNeg8 { + continue + } + x := o.Args[0] + if !(o.Uses == 1) { + continue + } + v.reset(OpNeq8) + v0 := b.NewValue0(v.Pos, OpConst8, t) + v0.AuxInt = int8ToAuxInt(-c) + v.AddArg2(v0, x) + return true + } + break + } + // match: (Neq8 (Const8 [c]) o:(Mul8 (Const8 [d]) x)) + // cond: uint8( d)%2 == 1 && o.Uses == 1 + // result: (Neq8 (Const8 [int8( uint8( c) * uint8( modularMultiplicativeInverse(uint64(d))))]) x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst8 { + continue + } + t := v_0.Type + c := auxIntToInt8(v_0.AuxInt) + o := v_1 + if o.Op != OpMul8 { + continue + } + _ = o.Args[1] + o_0 := o.Args[0] + o_1 := o.Args[1] + for _i1 := 0; _i1 <= 1; _i1, o_0, o_1 = _i1+1, o_1, o_0 { + if o_0.Op != OpConst8 { + continue + } + d := auxIntToInt8(o_0.AuxInt) + x := o_1 + if !(uint8(d)%2 == 1 && o.Uses == 1) { + continue + } + v.reset(OpNeq8) + v0 := b.NewValue0(v.Pos, OpConst8, t) + v0.AuxInt = int8ToAuxInt(int8(uint8(c) * uint8(modularMultiplicativeInverse(uint64(d))))) + v.AddArg2(v0, x) + return true + } + } + break + } // match: (Neq8 (Const8 [c]) (Const8 [d])) // result: (ConstBool [c != d]) for { diff --git a/test/codegen/comparisons.go b/test/codegen/comparisons.go index ce08158d81..557817443a 100644 --- a/test/codegen/comparisons.go +++ b/test/codegen/comparisons.go @@ -930,3 +930,45 @@ func cmpstring2(x, y string) int { //amd64:-`MOVQ .*\(SP\)` return cmp.Compare(x, y) } + +func bijectiveAdd(x uint) bool { + // amd64: -"ADD" + // arm64: -"ADD" + return x+1337 == 42 +} + +func bijectiveSub1(x uint) bool { + // amd64: -"SUB" + // arm64: -"SUB" + return x-1337 == 42 +} + +func bijectiveSub2(x uint) bool { + // amd64: -"SUB" + // arm64: -"SUB" + return 1337-x == 42 +} + +func bijectiveXor(x uint) bool { + // amd64: -"XOR" + // arm64: -"EOR" + return x^1337 == 42 +} + +func bijectiveCom(x uint) bool { + // amd64: -"NOT" + // arm64: -"MVN" + return ^x == 42 +} + +func bijectiveNeg(x int) bool { + // amd64: -"NEG" + // arm64: -"NEG" + return -x == 42 +} + +func bijectiveMul(x uint) bool { + // amd64: -"MUL" + // arm64: -"MUL" + return x*1337 == 42 +}