From efe5929dbd23054395ea128325edba8d23b6d5fc Mon Sep 17 00:00:00 2001 From: eric fang Date: Fri, 29 Jul 2022 04:05:03 +0000 Subject: [PATCH] cmd/compile/internal/ssa: optimize ARM64 code with TST MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit For signed comparisons, the following four optimization rules hold: (CMPconst [0] z:(AND x y)) && z.Uses == 1 => (TST x y) (CMPWconst [0] z:(AND x y)) && z.Uses == 1 => (TSTW x y) (CMPconst [0] x:(ANDconst [c] y)) && x.Uses == 1 => (TSTconst [c] y) (CMPWconst [0] x:(ANDconst [c] y)) && x.Uses == 1 => (TSTWconst [int32(c)] y) But currently they only apply to jump instructions, not to conditional instructions within a block, such as cset, csel, etc. This CL extends the above rules into blocks so that conditional instructions can also be optimized. name old time/op new time/op delta DivisiblePow2constI64-160 1.04ns ± 0% 0.86ns ± 0% -17.30% (p=0.008 n=5+5) DivisiblePow2constI32-160 1.04ns ± 0% 0.87ns ± 0% -16.16% (p=0.016 n=4+5) DivisiblePow2constI16-160 1.04ns ± 0% 0.87ns ± 0% -16.03% (p=0.008 n=5+5) DivisiblePow2constI8-160 1.04ns ± 0% 0.86ns ± 0% -17.15% (p=0.008 n=5+5) Change-Id: I6bc34bff30862210e8dd001e0340b8fe502fe3de Reviewed-on: https://go-review.googlesource.com/c/go/+/420434 Reviewed-by: Cherry Mui TryBot-Result: Gopher Robot Reviewed-by: Dmitri Shuralyov Run-TryBot: Eric Fang --- src/cmd/compile/internal/ssa/gen/ARM64.rules | 55 +- src/cmd/compile/internal/ssa/rewriteARM64.go | 896 +++++++++++++++---- test/codegen/arithmetic.go | 22 +- 3 files changed, 774 insertions(+), 199 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index 3776b3ca02..e3d77be0b4 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -610,13 +610,6 @@ (TBNZ [0] (GreaterThanF cc) yes no) => (FGT cc yes no) (TBNZ [0] (GreaterEqualF cc) yes no) => (FGE cc yes no) -(EQ (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (EQ (TSTWconst [int32(c)] y) yes no) -(NE (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (NE (TSTWconst [int32(c)] y) yes no) -(LT (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (LT (TSTWconst [int32(c)] y) yes no) -(LE (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (LE (TSTWconst [int32(c)] y) yes no) -(GT (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (GT (TSTWconst [int32(c)] y) yes no) -(GE (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (GE (TSTWconst [int32(c)] y) yes no) - (EQ (CMPconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (EQ (TST x y) yes no) (NE (CMPconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (NE (TST x y) yes no) (LT (CMPconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (LT (TST x y) yes no) @@ -624,6 +617,13 @@ (GT (CMPconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (GT (TST x y) yes no) (GE (CMPconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (GE (TST x y) yes no) +(EQ (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (EQ (TSTconst [c] y) yes no) +(NE (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (NE (TSTconst [c] y) yes no) +(LT (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (LT (TSTconst [c] y) yes no) +(LE (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (LE (TSTconst [c] y) yes no) +(GT (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (GT (TSTconst [c] y) yes no) +(GE (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (GE (TSTconst [c] y) yes no) + (EQ (CMPWconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (EQ (TSTW x y) yes no) (NE (CMPWconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (NE (TSTW x y) yes no) (LT (CMPWconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (LT (TSTW x y) yes no) @@ -631,12 +631,41 @@ (GT (CMPWconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (GT (TSTW x y) yes no) (GE (CMPWconst [0] z:(AND x y)) yes no) && z.Uses == 1 => (GE (TSTW x y) yes no) -(EQ (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (EQ (TSTconst [c] y) yes no) -(NE (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (NE (TSTconst [c] y) yes no) -(LT (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (LT (TSTconst [c] y) yes no) -(LE (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (LE (TSTconst [c] y) yes no) -(GT (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (GT (TSTconst [c] y) yes no) -(GE (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (GE (TSTconst [c] y) yes no) +(EQ (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (EQ (TSTWconst [int32(c)] y) yes no) +(NE (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (NE (TSTWconst [int32(c)] y) yes no) +(LT (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (LT (TSTWconst [int32(c)] y) yes no) +(LE (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (LE (TSTWconst [int32(c)] y) yes no) +(GT (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (GT (TSTWconst [int32(c)] y) yes no) +(GE (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (GE (TSTWconst [int32(c)] y) yes no) + +// For conditional instructions such as CSET, CSEL. +(Equal (CMPconst [0] z:(AND x y))) && z.Uses == 1 => (Equal (TST x y)) +(NotEqual (CMPconst [0] z:(AND x y))) && z.Uses == 1 => (NotEqual (TST x y)) +(LessThan (CMPconst [0] z:(AND x y))) && z.Uses == 1 => (LessThan (TST x y)) +(LessEqual (CMPconst [0] z:(AND x y))) && z.Uses == 1 => (LessEqual (TST x y)) +(GreaterThan (CMPconst [0] z:(AND x y))) && z.Uses == 1 => (GreaterThan (TST x y)) +(GreaterEqual (CMPconst [0] z:(AND x y))) && z.Uses == 1 => (GreaterEqual (TST x y)) + +(Equal (CMPWconst [0] x:(ANDconst [c] y))) && x.Uses == 1 => (Equal (TSTWconst [int32(c)] y)) +(NotEqual (CMPWconst [0] x:(ANDconst [c] y))) && x.Uses == 1 => (NotEqual (TSTWconst [int32(c)] y)) +(LessThan (CMPWconst [0] x:(ANDconst [c] y))) && x.Uses == 1 => (LessThan (TSTWconst [int32(c)] y)) +(LessEqual (CMPWconst [0] x:(ANDconst [c] y))) && x.Uses == 1 => (LessEqual (TSTWconst [int32(c)] y)) +(GreaterThan (CMPWconst [0] x:(ANDconst [c] y))) && x.Uses == 1 => (GreaterThan (TSTWconst [int32(c)] y)) +(GreaterEqual (CMPWconst [0] x:(ANDconst [c] y))) && x.Uses == 1 => (GreaterEqual (TSTWconst [int32(c)] y)) + +(Equal (CMPWconst [0] z:(AND x y))) && z.Uses == 1 => (Equal (TSTW x y)) +(NotEqual (CMPWconst [0] z:(AND x y))) && z.Uses == 1 => (NotEqual (TSTW x y)) +(LessThan (CMPWconst [0] z:(AND x y))) && z.Uses == 1 => (LessThan (TSTW x y)) +(LessEqual (CMPWconst [0] z:(AND x y))) && z.Uses == 1 => (LessEqual (TSTW x y)) +(GreaterThan (CMPWconst [0] z:(AND x y))) && z.Uses == 1 => (GreaterThan (TSTW x y)) +(GreaterEqual (CMPWconst [0] z:(AND x y))) && z.Uses == 1 => (GreaterEqual (TSTW x y)) + +(Equal (CMPconst [0] x:(ANDconst [c] y))) && x.Uses == 1 => (Equal (TSTconst [c] y)) +(NotEqual (CMPconst [0] x:(ANDconst [c] y))) && x.Uses == 1 => (NotEqual (TSTconst [c] y)) +(LessThan (CMPWconst [0] x:(ANDconst [c] y))) && x.Uses == 1 => (LessThan (TSTconst [c] y)) +(LessEqual (CMPWconst [0] x:(ANDconst [c] y))) && x.Uses == 1 => (LessEqual (TSTconst [c] y)) +(GreaterThan (CMPWconst [0] x:(ANDconst [c] y))) && x.Uses == 1 => (GreaterThan (TSTconst [c] y)) +(GreaterEqual (CMPWconst [0] x:(ANDconst [c] y))) && x.Uses == 1 => (GreaterEqual (TSTconst [c] y)) (EQ (CMPconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 => (EQ (CMNconst [c] y) yes no) (NE (CMPconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 => (NE (CMNconst [c] y) yes no) diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index efeadf64cc..7845e9cf1d 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -4251,6 +4251,97 @@ func rewriteValueARM64_OpARM64EONshiftRO(v *Value) bool { } func rewriteValueARM64_OpARM64Equal(v *Value) bool { v_0 := v.Args[0] + b := v.Block + // match: (Equal (CMPconst [0] z:(AND x y))) + // cond: z.Uses == 1 + // result: (Equal (TST x y)) + for { + if v_0.Op != OpARM64CMPconst || auxIntToInt64(v_0.AuxInt) != 0 { + break + } + z := v_0.Args[0] + if z.Op != OpARM64AND { + break + } + y := z.Args[1] + x := z.Args[0] + if !(z.Uses == 1) { + break + } + v.reset(OpARM64Equal) + v0 := b.NewValue0(v.Pos, OpARM64TST, types.TypeFlags) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + // match: (Equal (CMPWconst [0] x:(ANDconst [c] y))) + // cond: x.Uses == 1 + // result: (Equal (TSTWconst [int32(c)] y)) + for { + if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 { + break + } + x := v_0.Args[0] + if x.Op != OpARM64ANDconst { + break + } + c := auxIntToInt64(x.AuxInt) + y := x.Args[0] + if !(x.Uses == 1) { + break + } + v.reset(OpARM64Equal) + v0 := b.NewValue0(v.Pos, OpARM64TSTWconst, types.TypeFlags) + v0.AuxInt = int32ToAuxInt(int32(c)) + v0.AddArg(y) + v.AddArg(v0) + return true + } + // match: (Equal (CMPWconst [0] z:(AND x y))) + // cond: z.Uses == 1 + // result: (Equal (TSTW x y)) + for { + if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 { + break + } + z := v_0.Args[0] + if z.Op != OpARM64AND { + break + } + y := z.Args[1] + x := z.Args[0] + if !(z.Uses == 1) { + break + } + v.reset(OpARM64Equal) + v0 := b.NewValue0(v.Pos, OpARM64TSTW, types.TypeFlags) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + // match: (Equal (CMPconst [0] x:(ANDconst [c] y))) + // cond: x.Uses == 1 + // result: (Equal (TSTconst [c] y)) + for { + if v_0.Op != OpARM64CMPconst || auxIntToInt64(v_0.AuxInt) != 0 { + break + } + x := v_0.Args[0] + if x.Op != OpARM64ANDconst { + break + } + c := auxIntToInt64(x.AuxInt) + y := x.Args[0] + if !(x.Uses == 1) { + break + } + v.reset(OpARM64Equal) + v0 := b.NewValue0(v.Pos, OpARM64TSTconst, types.TypeFlags) + v0.AuxInt = int64ToAuxInt(c) + v0.AddArg(y) + v.AddArg(v0) + return true + } // match: (Equal (FlagConstant [fc])) // result: (MOVDconst [b2i(fc.eq())]) for { @@ -5515,6 +5606,97 @@ func rewriteValueARM64_OpARM64FSUBS(v *Value) bool { } func rewriteValueARM64_OpARM64GreaterEqual(v *Value) bool { v_0 := v.Args[0] + b := v.Block + // match: (GreaterEqual (CMPconst [0] z:(AND x y))) + // cond: z.Uses == 1 + // result: (GreaterEqual (TST x y)) + for { + if v_0.Op != OpARM64CMPconst || auxIntToInt64(v_0.AuxInt) != 0 { + break + } + z := v_0.Args[0] + if z.Op != OpARM64AND { + break + } + y := z.Args[1] + x := z.Args[0] + if !(z.Uses == 1) { + break + } + v.reset(OpARM64GreaterEqual) + v0 := b.NewValue0(v.Pos, OpARM64TST, types.TypeFlags) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + // match: (GreaterEqual (CMPWconst [0] x:(ANDconst [c] y))) + // cond: x.Uses == 1 + // result: (GreaterEqual (TSTWconst [int32(c)] y)) + for { + if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 { + break + } + x := v_0.Args[0] + if x.Op != OpARM64ANDconst { + break + } + c := auxIntToInt64(x.AuxInt) + y := x.Args[0] + if !(x.Uses == 1) { + break + } + v.reset(OpARM64GreaterEqual) + v0 := b.NewValue0(v.Pos, OpARM64TSTWconst, types.TypeFlags) + v0.AuxInt = int32ToAuxInt(int32(c)) + v0.AddArg(y) + v.AddArg(v0) + return true + } + // match: (GreaterEqual (CMPWconst [0] z:(AND x y))) + // cond: z.Uses == 1 + // result: (GreaterEqual (TSTW x y)) + for { + if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 { + break + } + z := v_0.Args[0] + if z.Op != OpARM64AND { + break + } + y := z.Args[1] + x := z.Args[0] + if !(z.Uses == 1) { + break + } + v.reset(OpARM64GreaterEqual) + v0 := b.NewValue0(v.Pos, OpARM64TSTW, types.TypeFlags) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + // match: (GreaterEqual (CMPWconst [0] x:(ANDconst [c] y))) + // cond: x.Uses == 1 + // result: (GreaterEqual (TSTconst [c] y)) + for { + if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 { + break + } + x := v_0.Args[0] + if x.Op != OpARM64ANDconst { + break + } + c := auxIntToInt64(x.AuxInt) + y := x.Args[0] + if !(x.Uses == 1) { + break + } + v.reset(OpARM64GreaterEqual) + v0 := b.NewValue0(v.Pos, OpARM64TSTconst, types.TypeFlags) + v0.AuxInt = int64ToAuxInt(c) + v0.AddArg(y) + v.AddArg(v0) + return true + } // match: (GreaterEqual (FlagConstant [fc])) // result: (MOVDconst [b2i(fc.ge())]) for { @@ -5582,6 +5764,97 @@ func rewriteValueARM64_OpARM64GreaterEqualU(v *Value) bool { } func rewriteValueARM64_OpARM64GreaterThan(v *Value) bool { v_0 := v.Args[0] + b := v.Block + // match: (GreaterThan (CMPconst [0] z:(AND x y))) + // cond: z.Uses == 1 + // result: (GreaterThan (TST x y)) + for { + if v_0.Op != OpARM64CMPconst || auxIntToInt64(v_0.AuxInt) != 0 { + break + } + z := v_0.Args[0] + if z.Op != OpARM64AND { + break + } + y := z.Args[1] + x := z.Args[0] + if !(z.Uses == 1) { + break + } + v.reset(OpARM64GreaterThan) + v0 := b.NewValue0(v.Pos, OpARM64TST, types.TypeFlags) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + // match: (GreaterThan (CMPWconst [0] x:(ANDconst [c] y))) + // cond: x.Uses == 1 + // result: (GreaterThan (TSTWconst [int32(c)] y)) + for { + if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 { + break + } + x := v_0.Args[0] + if x.Op != OpARM64ANDconst { + break + } + c := auxIntToInt64(x.AuxInt) + y := x.Args[0] + if !(x.Uses == 1) { + break + } + v.reset(OpARM64GreaterThan) + v0 := b.NewValue0(v.Pos, OpARM64TSTWconst, types.TypeFlags) + v0.AuxInt = int32ToAuxInt(int32(c)) + v0.AddArg(y) + v.AddArg(v0) + return true + } + // match: (GreaterThan (CMPWconst [0] z:(AND x y))) + // cond: z.Uses == 1 + // result: (GreaterThan (TSTW x y)) + for { + if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 { + break + } + z := v_0.Args[0] + if z.Op != OpARM64AND { + break + } + y := z.Args[1] + x := z.Args[0] + if !(z.Uses == 1) { + break + } + v.reset(OpARM64GreaterThan) + v0 := b.NewValue0(v.Pos, OpARM64TSTW, types.TypeFlags) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + // match: (GreaterThan (CMPWconst [0] x:(ANDconst [c] y))) + // cond: x.Uses == 1 + // result: (GreaterThan (TSTconst [c] y)) + for { + if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 { + break + } + x := v_0.Args[0] + if x.Op != OpARM64ANDconst { + break + } + c := auxIntToInt64(x.AuxInt) + y := x.Args[0] + if !(x.Uses == 1) { + break + } + v.reset(OpARM64GreaterThan) + v0 := b.NewValue0(v.Pos, OpARM64TSTconst, types.TypeFlags) + v0.AuxInt = int64ToAuxInt(c) + v0.AddArg(y) + v.AddArg(v0) + return true + } // match: (GreaterThan (FlagConstant [fc])) // result: (MOVDconst [b2i(fc.gt())]) for { @@ -5649,6 +5922,97 @@ func rewriteValueARM64_OpARM64GreaterThanU(v *Value) bool { } func rewriteValueARM64_OpARM64LessEqual(v *Value) bool { v_0 := v.Args[0] + b := v.Block + // match: (LessEqual (CMPconst [0] z:(AND x y))) + // cond: z.Uses == 1 + // result: (LessEqual (TST x y)) + for { + if v_0.Op != OpARM64CMPconst || auxIntToInt64(v_0.AuxInt) != 0 { + break + } + z := v_0.Args[0] + if z.Op != OpARM64AND { + break + } + y := z.Args[1] + x := z.Args[0] + if !(z.Uses == 1) { + break + } + v.reset(OpARM64LessEqual) + v0 := b.NewValue0(v.Pos, OpARM64TST, types.TypeFlags) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + // match: (LessEqual (CMPWconst [0] x:(ANDconst [c] y))) + // cond: x.Uses == 1 + // result: (LessEqual (TSTWconst [int32(c)] y)) + for { + if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 { + break + } + x := v_0.Args[0] + if x.Op != OpARM64ANDconst { + break + } + c := auxIntToInt64(x.AuxInt) + y := x.Args[0] + if !(x.Uses == 1) { + break + } + v.reset(OpARM64LessEqual) + v0 := b.NewValue0(v.Pos, OpARM64TSTWconst, types.TypeFlags) + v0.AuxInt = int32ToAuxInt(int32(c)) + v0.AddArg(y) + v.AddArg(v0) + return true + } + // match: (LessEqual (CMPWconst [0] z:(AND x y))) + // cond: z.Uses == 1 + // result: (LessEqual (TSTW x y)) + for { + if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 { + break + } + z := v_0.Args[0] + if z.Op != OpARM64AND { + break + } + y := z.Args[1] + x := z.Args[0] + if !(z.Uses == 1) { + break + } + v.reset(OpARM64LessEqual) + v0 := b.NewValue0(v.Pos, OpARM64TSTW, types.TypeFlags) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + // match: (LessEqual (CMPWconst [0] x:(ANDconst [c] y))) + // cond: x.Uses == 1 + // result: (LessEqual (TSTconst [c] y)) + for { + if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 { + break + } + x := v_0.Args[0] + if x.Op != OpARM64ANDconst { + break + } + c := auxIntToInt64(x.AuxInt) + y := x.Args[0] + if !(x.Uses == 1) { + break + } + v.reset(OpARM64LessEqual) + v0 := b.NewValue0(v.Pos, OpARM64TSTconst, types.TypeFlags) + v0.AuxInt = int64ToAuxInt(c) + v0.AddArg(y) + v.AddArg(v0) + return true + } // match: (LessEqual (FlagConstant [fc])) // result: (MOVDconst [b2i(fc.le())]) for { @@ -5716,6 +6080,97 @@ func rewriteValueARM64_OpARM64LessEqualU(v *Value) bool { } func rewriteValueARM64_OpARM64LessThan(v *Value) bool { v_0 := v.Args[0] + b := v.Block + // match: (LessThan (CMPconst [0] z:(AND x y))) + // cond: z.Uses == 1 + // result: (LessThan (TST x y)) + for { + if v_0.Op != OpARM64CMPconst || auxIntToInt64(v_0.AuxInt) != 0 { + break + } + z := v_0.Args[0] + if z.Op != OpARM64AND { + break + } + y := z.Args[1] + x := z.Args[0] + if !(z.Uses == 1) { + break + } + v.reset(OpARM64LessThan) + v0 := b.NewValue0(v.Pos, OpARM64TST, types.TypeFlags) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + // match: (LessThan (CMPWconst [0] x:(ANDconst [c] y))) + // cond: x.Uses == 1 + // result: (LessThan (TSTWconst [int32(c)] y)) + for { + if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 { + break + } + x := v_0.Args[0] + if x.Op != OpARM64ANDconst { + break + } + c := auxIntToInt64(x.AuxInt) + y := x.Args[0] + if !(x.Uses == 1) { + break + } + v.reset(OpARM64LessThan) + v0 := b.NewValue0(v.Pos, OpARM64TSTWconst, types.TypeFlags) + v0.AuxInt = int32ToAuxInt(int32(c)) + v0.AddArg(y) + v.AddArg(v0) + return true + } + // match: (LessThan (CMPWconst [0] z:(AND x y))) + // cond: z.Uses == 1 + // result: (LessThan (TSTW x y)) + for { + if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 { + break + } + z := v_0.Args[0] + if z.Op != OpARM64AND { + break + } + y := z.Args[1] + x := z.Args[0] + if !(z.Uses == 1) { + break + } + v.reset(OpARM64LessThan) + v0 := b.NewValue0(v.Pos, OpARM64TSTW, types.TypeFlags) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + // match: (LessThan (CMPWconst [0] x:(ANDconst [c] y))) + // cond: x.Uses == 1 + // result: (LessThan (TSTconst [c] y)) + for { + if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 { + break + } + x := v_0.Args[0] + if x.Op != OpARM64ANDconst { + break + } + c := auxIntToInt64(x.AuxInt) + y := x.Args[0] + if !(x.Uses == 1) { + break + } + v.reset(OpARM64LessThan) + v0 := b.NewValue0(v.Pos, OpARM64TSTconst, types.TypeFlags) + v0.AuxInt = int64ToAuxInt(c) + v0.AddArg(y) + v.AddArg(v0) + return true + } // match: (LessThan (FlagConstant [fc])) // result: (MOVDconst [b2i(fc.lt())]) for { @@ -16196,6 +16651,97 @@ func rewriteValueARM64_OpARM64NEGshiftRL(v *Value) bool { } func rewriteValueARM64_OpARM64NotEqual(v *Value) bool { v_0 := v.Args[0] + b := v.Block + // match: (NotEqual (CMPconst [0] z:(AND x y))) + // cond: z.Uses == 1 + // result: (NotEqual (TST x y)) + for { + if v_0.Op != OpARM64CMPconst || auxIntToInt64(v_0.AuxInt) != 0 { + break + } + z := v_0.Args[0] + if z.Op != OpARM64AND { + break + } + y := z.Args[1] + x := z.Args[0] + if !(z.Uses == 1) { + break + } + v.reset(OpARM64NotEqual) + v0 := b.NewValue0(v.Pos, OpARM64TST, types.TypeFlags) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + // match: (NotEqual (CMPWconst [0] x:(ANDconst [c] y))) + // cond: x.Uses == 1 + // result: (NotEqual (TSTWconst [int32(c)] y)) + for { + if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 { + break + } + x := v_0.Args[0] + if x.Op != OpARM64ANDconst { + break + } + c := auxIntToInt64(x.AuxInt) + y := x.Args[0] + if !(x.Uses == 1) { + break + } + v.reset(OpARM64NotEqual) + v0 := b.NewValue0(v.Pos, OpARM64TSTWconst, types.TypeFlags) + v0.AuxInt = int32ToAuxInt(int32(c)) + v0.AddArg(y) + v.AddArg(v0) + return true + } + // match: (NotEqual (CMPWconst [0] z:(AND x y))) + // cond: z.Uses == 1 + // result: (NotEqual (TSTW x y)) + for { + if v_0.Op != OpARM64CMPWconst || auxIntToInt32(v_0.AuxInt) != 0 { + break + } + z := v_0.Args[0] + if z.Op != OpARM64AND { + break + } + y := z.Args[1] + x := z.Args[0] + if !(z.Uses == 1) { + break + } + v.reset(OpARM64NotEqual) + v0 := b.NewValue0(v.Pos, OpARM64TSTW, types.TypeFlags) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + // match: (NotEqual (CMPconst [0] x:(ANDconst [c] y))) + // cond: x.Uses == 1 + // result: (NotEqual (TSTconst [c] y)) + for { + if v_0.Op != OpARM64CMPconst || auxIntToInt64(v_0.AuxInt) != 0 { + break + } + x := v_0.Args[0] + if x.Op != OpARM64ANDconst { + break + } + c := auxIntToInt64(x.AuxInt) + y := x.Args[0] + if !(x.Uses == 1) { + break + } + v.reset(OpARM64NotEqual) + v0 := b.NewValue0(v.Pos, OpARM64TSTconst, types.TypeFlags) + v0.AuxInt = int64ToAuxInt(c) + v0.AddArg(y) + v.AddArg(v0) + return true + } // match: (NotEqual (FlagConstant [fc])) // result: (MOVDconst [b2i(fc.ne())]) for { @@ -27494,29 +28040,6 @@ func rewriteBlockARM64(b *Block) bool { typ := &b.Func.Config.Types switch b.Kind { case BlockARM64EQ: - // match: (EQ (CMPWconst [0] x:(ANDconst [c] y)) yes no) - // cond: x.Uses == 1 - // result: (EQ (TSTWconst [int32(c)] y) yes no) - for b.Controls[0].Op == OpARM64CMPWconst { - v_0 := b.Controls[0] - if auxIntToInt32(v_0.AuxInt) != 0 { - break - } - x := v_0.Args[0] - if x.Op != OpARM64ANDconst { - break - } - c := auxIntToInt64(x.AuxInt) - y := x.Args[0] - if !(x.Uses == 1) { - break - } - v0 := b.NewValue0(v_0.Pos, OpARM64TSTWconst, types.TypeFlags) - v0.AuxInt = int32ToAuxInt(int32(c)) - v0.AddArg(y) - b.resetWithControl(BlockARM64EQ, v0) - return true - } // match: (EQ (CMPconst [0] z:(AND x y)) yes no) // cond: z.Uses == 1 // result: (EQ (TST x y) yes no) @@ -27545,6 +28068,29 @@ func rewriteBlockARM64(b *Block) bool { } break } + // match: (EQ (CMPconst [0] x:(ANDconst [c] y)) yes no) + // cond: x.Uses == 1 + // result: (EQ (TSTconst [c] y) yes no) + for b.Controls[0].Op == OpARM64CMPconst { + v_0 := b.Controls[0] + if auxIntToInt64(v_0.AuxInt) != 0 { + break + } + x := v_0.Args[0] + if x.Op != OpARM64ANDconst { + break + } + c := auxIntToInt64(x.AuxInt) + y := x.Args[0] + if !(x.Uses == 1) { + break + } + v0 := b.NewValue0(v_0.Pos, OpARM64TSTconst, types.TypeFlags) + v0.AuxInt = int64ToAuxInt(c) + v0.AddArg(y) + b.resetWithControl(BlockARM64EQ, v0) + return true + } // match: (EQ (CMPWconst [0] z:(AND x y)) yes no) // cond: z.Uses == 1 // result: (EQ (TSTW x y) yes no) @@ -27573,12 +28119,12 @@ func rewriteBlockARM64(b *Block) bool { } break } - // match: (EQ (CMPconst [0] x:(ANDconst [c] y)) yes no) + // match: (EQ (CMPWconst [0] x:(ANDconst [c] y)) yes no) // cond: x.Uses == 1 - // result: (EQ (TSTconst [c] y) yes no) - for b.Controls[0].Op == OpARM64CMPconst { + // result: (EQ (TSTWconst [int32(c)] y) yes no) + for b.Controls[0].Op == OpARM64CMPWconst { v_0 := b.Controls[0] - if auxIntToInt64(v_0.AuxInt) != 0 { + if auxIntToInt32(v_0.AuxInt) != 0 { break } x := v_0.Args[0] @@ -27590,8 +28136,8 @@ func rewriteBlockARM64(b *Block) bool { if !(x.Uses == 1) { break } - v0 := b.NewValue0(v_0.Pos, OpARM64TSTconst, types.TypeFlags) - v0.AuxInt = int64ToAuxInt(c) + v0 := b.NewValue0(v_0.Pos, OpARM64TSTWconst, types.TypeFlags) + v0.AuxInt = int32ToAuxInt(int32(c)) v0.AddArg(y) b.resetWithControl(BlockARM64EQ, v0) return true @@ -27958,29 +28504,6 @@ func rewriteBlockARM64(b *Block) bool { return true } case BlockARM64GE: - // match: (GE (CMPWconst [0] x:(ANDconst [c] y)) yes no) - // cond: x.Uses == 1 - // result: (GE (TSTWconst [int32(c)] y) yes no) - for b.Controls[0].Op == OpARM64CMPWconst { - v_0 := b.Controls[0] - if auxIntToInt32(v_0.AuxInt) != 0 { - break - } - x := v_0.Args[0] - if x.Op != OpARM64ANDconst { - break - } - c := auxIntToInt64(x.AuxInt) - y := x.Args[0] - if !(x.Uses == 1) { - break - } - v0 := b.NewValue0(v_0.Pos, OpARM64TSTWconst, types.TypeFlags) - v0.AuxInt = int32ToAuxInt(int32(c)) - v0.AddArg(y) - b.resetWithControl(BlockARM64GE, v0) - return true - } // match: (GE (CMPconst [0] z:(AND x y)) yes no) // cond: z.Uses == 1 // result: (GE (TST x y) yes no) @@ -28007,7 +28530,30 @@ func rewriteBlockARM64(b *Block) bool { b.resetWithControl(BlockARM64GE, v0) return true } - break + break + } + // match: (GE (CMPconst [0] x:(ANDconst [c] y)) yes no) + // cond: x.Uses == 1 + // result: (GE (TSTconst [c] y) yes no) + for b.Controls[0].Op == OpARM64CMPconst { + v_0 := b.Controls[0] + if auxIntToInt64(v_0.AuxInt) != 0 { + break + } + x := v_0.Args[0] + if x.Op != OpARM64ANDconst { + break + } + c := auxIntToInt64(x.AuxInt) + y := x.Args[0] + if !(x.Uses == 1) { + break + } + v0 := b.NewValue0(v_0.Pos, OpARM64TSTconst, types.TypeFlags) + v0.AuxInt = int64ToAuxInt(c) + v0.AddArg(y) + b.resetWithControl(BlockARM64GE, v0) + return true } // match: (GE (CMPWconst [0] z:(AND x y)) yes no) // cond: z.Uses == 1 @@ -28037,12 +28583,12 @@ func rewriteBlockARM64(b *Block) bool { } break } - // match: (GE (CMPconst [0] x:(ANDconst [c] y)) yes no) + // match: (GE (CMPWconst [0] x:(ANDconst [c] y)) yes no) // cond: x.Uses == 1 - // result: (GE (TSTconst [c] y) yes no) - for b.Controls[0].Op == OpARM64CMPconst { + // result: (GE (TSTWconst [int32(c)] y) yes no) + for b.Controls[0].Op == OpARM64CMPWconst { v_0 := b.Controls[0] - if auxIntToInt64(v_0.AuxInt) != 0 { + if auxIntToInt32(v_0.AuxInt) != 0 { break } x := v_0.Args[0] @@ -28054,8 +28600,8 @@ func rewriteBlockARM64(b *Block) bool { if !(x.Uses == 1) { break } - v0 := b.NewValue0(v_0.Pos, OpARM64TSTconst, types.TypeFlags) - v0.AuxInt = int64ToAuxInt(c) + v0 := b.NewValue0(v_0.Pos, OpARM64TSTWconst, types.TypeFlags) + v0.AuxInt = int32ToAuxInt(int32(c)) v0.AddArg(y) b.resetWithControl(BlockARM64GE, v0) return true @@ -28354,29 +28900,6 @@ func rewriteBlockARM64(b *Block) bool { return true } case BlockARM64GT: - // match: (GT (CMPWconst [0] x:(ANDconst [c] y)) yes no) - // cond: x.Uses == 1 - // result: (GT (TSTWconst [int32(c)] y) yes no) - for b.Controls[0].Op == OpARM64CMPWconst { - v_0 := b.Controls[0] - if auxIntToInt32(v_0.AuxInt) != 0 { - break - } - x := v_0.Args[0] - if x.Op != OpARM64ANDconst { - break - } - c := auxIntToInt64(x.AuxInt) - y := x.Args[0] - if !(x.Uses == 1) { - break - } - v0 := b.NewValue0(v_0.Pos, OpARM64TSTWconst, types.TypeFlags) - v0.AuxInt = int32ToAuxInt(int32(c)) - v0.AddArg(y) - b.resetWithControl(BlockARM64GT, v0) - return true - } // match: (GT (CMPconst [0] z:(AND x y)) yes no) // cond: z.Uses == 1 // result: (GT (TST x y) yes no) @@ -28405,6 +28928,29 @@ func rewriteBlockARM64(b *Block) bool { } break } + // match: (GT (CMPconst [0] x:(ANDconst [c] y)) yes no) + // cond: x.Uses == 1 + // result: (GT (TSTconst [c] y) yes no) + for b.Controls[0].Op == OpARM64CMPconst { + v_0 := b.Controls[0] + if auxIntToInt64(v_0.AuxInt) != 0 { + break + } + x := v_0.Args[0] + if x.Op != OpARM64ANDconst { + break + } + c := auxIntToInt64(x.AuxInt) + y := x.Args[0] + if !(x.Uses == 1) { + break + } + v0 := b.NewValue0(v_0.Pos, OpARM64TSTconst, types.TypeFlags) + v0.AuxInt = int64ToAuxInt(c) + v0.AddArg(y) + b.resetWithControl(BlockARM64GT, v0) + return true + } // match: (GT (CMPWconst [0] z:(AND x y)) yes no) // cond: z.Uses == 1 // result: (GT (TSTW x y) yes no) @@ -28433,12 +28979,12 @@ func rewriteBlockARM64(b *Block) bool { } break } - // match: (GT (CMPconst [0] x:(ANDconst [c] y)) yes no) + // match: (GT (CMPWconst [0] x:(ANDconst [c] y)) yes no) // cond: x.Uses == 1 - // result: (GT (TSTconst [c] y) yes no) - for b.Controls[0].Op == OpARM64CMPconst { + // result: (GT (TSTWconst [int32(c)] y) yes no) + for b.Controls[0].Op == OpARM64CMPWconst { v_0 := b.Controls[0] - if auxIntToInt64(v_0.AuxInt) != 0 { + if auxIntToInt32(v_0.AuxInt) != 0 { break } x := v_0.Args[0] @@ -28450,8 +28996,8 @@ func rewriteBlockARM64(b *Block) bool { if !(x.Uses == 1) { break } - v0 := b.NewValue0(v_0.Pos, OpARM64TSTconst, types.TypeFlags) - v0.AuxInt = int64ToAuxInt(c) + v0 := b.NewValue0(v_0.Pos, OpARM64TSTWconst, types.TypeFlags) + v0.AuxInt = int32ToAuxInt(int32(c)) v0.AddArg(y) b.resetWithControl(BlockARM64GT, v0) return true @@ -28860,29 +29406,6 @@ func rewriteBlockARM64(b *Block) bool { return true } case BlockARM64LE: - // match: (LE (CMPWconst [0] x:(ANDconst [c] y)) yes no) - // cond: x.Uses == 1 - // result: (LE (TSTWconst [int32(c)] y) yes no) - for b.Controls[0].Op == OpARM64CMPWconst { - v_0 := b.Controls[0] - if auxIntToInt32(v_0.AuxInt) != 0 { - break - } - x := v_0.Args[0] - if x.Op != OpARM64ANDconst { - break - } - c := auxIntToInt64(x.AuxInt) - y := x.Args[0] - if !(x.Uses == 1) { - break - } - v0 := b.NewValue0(v_0.Pos, OpARM64TSTWconst, types.TypeFlags) - v0.AuxInt = int32ToAuxInt(int32(c)) - v0.AddArg(y) - b.resetWithControl(BlockARM64LE, v0) - return true - } // match: (LE (CMPconst [0] z:(AND x y)) yes no) // cond: z.Uses == 1 // result: (LE (TST x y) yes no) @@ -28911,6 +29434,29 @@ func rewriteBlockARM64(b *Block) bool { } break } + // match: (LE (CMPconst [0] x:(ANDconst [c] y)) yes no) + // cond: x.Uses == 1 + // result: (LE (TSTconst [c] y) yes no) + for b.Controls[0].Op == OpARM64CMPconst { + v_0 := b.Controls[0] + if auxIntToInt64(v_0.AuxInt) != 0 { + break + } + x := v_0.Args[0] + if x.Op != OpARM64ANDconst { + break + } + c := auxIntToInt64(x.AuxInt) + y := x.Args[0] + if !(x.Uses == 1) { + break + } + v0 := b.NewValue0(v_0.Pos, OpARM64TSTconst, types.TypeFlags) + v0.AuxInt = int64ToAuxInt(c) + v0.AddArg(y) + b.resetWithControl(BlockARM64LE, v0) + return true + } // match: (LE (CMPWconst [0] z:(AND x y)) yes no) // cond: z.Uses == 1 // result: (LE (TSTW x y) yes no) @@ -28939,12 +29485,12 @@ func rewriteBlockARM64(b *Block) bool { } break } - // match: (LE (CMPconst [0] x:(ANDconst [c] y)) yes no) + // match: (LE (CMPWconst [0] x:(ANDconst [c] y)) yes no) // cond: x.Uses == 1 - // result: (LE (TSTconst [c] y) yes no) - for b.Controls[0].Op == OpARM64CMPconst { + // result: (LE (TSTWconst [int32(c)] y) yes no) + for b.Controls[0].Op == OpARM64CMPWconst { v_0 := b.Controls[0] - if auxIntToInt64(v_0.AuxInt) != 0 { + if auxIntToInt32(v_0.AuxInt) != 0 { break } x := v_0.Args[0] @@ -28956,8 +29502,8 @@ func rewriteBlockARM64(b *Block) bool { if !(x.Uses == 1) { break } - v0 := b.NewValue0(v_0.Pos, OpARM64TSTconst, types.TypeFlags) - v0.AuxInt = int64ToAuxInt(c) + v0 := b.NewValue0(v_0.Pos, OpARM64TSTWconst, types.TypeFlags) + v0.AuxInt = int32ToAuxInt(int32(c)) v0.AddArg(y) b.resetWithControl(BlockARM64LE, v0) return true @@ -29232,29 +29778,6 @@ func rewriteBlockARM64(b *Block) bool { return true } case BlockARM64LT: - // match: (LT (CMPWconst [0] x:(ANDconst [c] y)) yes no) - // cond: x.Uses == 1 - // result: (LT (TSTWconst [int32(c)] y) yes no) - for b.Controls[0].Op == OpARM64CMPWconst { - v_0 := b.Controls[0] - if auxIntToInt32(v_0.AuxInt) != 0 { - break - } - x := v_0.Args[0] - if x.Op != OpARM64ANDconst { - break - } - c := auxIntToInt64(x.AuxInt) - y := x.Args[0] - if !(x.Uses == 1) { - break - } - v0 := b.NewValue0(v_0.Pos, OpARM64TSTWconst, types.TypeFlags) - v0.AuxInt = int32ToAuxInt(int32(c)) - v0.AddArg(y) - b.resetWithControl(BlockARM64LT, v0) - return true - } // match: (LT (CMPconst [0] z:(AND x y)) yes no) // cond: z.Uses == 1 // result: (LT (TST x y) yes no) @@ -29283,6 +29806,29 @@ func rewriteBlockARM64(b *Block) bool { } break } + // match: (LT (CMPconst [0] x:(ANDconst [c] y)) yes no) + // cond: x.Uses == 1 + // result: (LT (TSTconst [c] y) yes no) + for b.Controls[0].Op == OpARM64CMPconst { + v_0 := b.Controls[0] + if auxIntToInt64(v_0.AuxInt) != 0 { + break + } + x := v_0.Args[0] + if x.Op != OpARM64ANDconst { + break + } + c := auxIntToInt64(x.AuxInt) + y := x.Args[0] + if !(x.Uses == 1) { + break + } + v0 := b.NewValue0(v_0.Pos, OpARM64TSTconst, types.TypeFlags) + v0.AuxInt = int64ToAuxInt(c) + v0.AddArg(y) + b.resetWithControl(BlockARM64LT, v0) + return true + } // match: (LT (CMPWconst [0] z:(AND x y)) yes no) // cond: z.Uses == 1 // result: (LT (TSTW x y) yes no) @@ -29311,12 +29857,12 @@ func rewriteBlockARM64(b *Block) bool { } break } - // match: (LT (CMPconst [0] x:(ANDconst [c] y)) yes no) + // match: (LT (CMPWconst [0] x:(ANDconst [c] y)) yes no) // cond: x.Uses == 1 - // result: (LT (TSTconst [c] y) yes no) - for b.Controls[0].Op == OpARM64CMPconst { + // result: (LT (TSTWconst [int32(c)] y) yes no) + for b.Controls[0].Op == OpARM64CMPWconst { v_0 := b.Controls[0] - if auxIntToInt64(v_0.AuxInt) != 0 { + if auxIntToInt32(v_0.AuxInt) != 0 { break } x := v_0.Args[0] @@ -29328,8 +29874,8 @@ func rewriteBlockARM64(b *Block) bool { if !(x.Uses == 1) { break } - v0 := b.NewValue0(v_0.Pos, OpARM64TSTconst, types.TypeFlags) - v0.AuxInt = int64ToAuxInt(c) + v0 := b.NewValue0(v_0.Pos, OpARM64TSTWconst, types.TypeFlags) + v0.AuxInt = int32ToAuxInt(int32(c)) v0.AddArg(y) b.resetWithControl(BlockARM64LT, v0) return true @@ -29628,29 +30174,6 @@ func rewriteBlockARM64(b *Block) bool { return true } case BlockARM64NE: - // match: (NE (CMPWconst [0] x:(ANDconst [c] y)) yes no) - // cond: x.Uses == 1 - // result: (NE (TSTWconst [int32(c)] y) yes no) - for b.Controls[0].Op == OpARM64CMPWconst { - v_0 := b.Controls[0] - if auxIntToInt32(v_0.AuxInt) != 0 { - break - } - x := v_0.Args[0] - if x.Op != OpARM64ANDconst { - break - } - c := auxIntToInt64(x.AuxInt) - y := x.Args[0] - if !(x.Uses == 1) { - break - } - v0 := b.NewValue0(v_0.Pos, OpARM64TSTWconst, types.TypeFlags) - v0.AuxInt = int32ToAuxInt(int32(c)) - v0.AddArg(y) - b.resetWithControl(BlockARM64NE, v0) - return true - } // match: (NE (CMPconst [0] z:(AND x y)) yes no) // cond: z.Uses == 1 // result: (NE (TST x y) yes no) @@ -29679,6 +30202,29 @@ func rewriteBlockARM64(b *Block) bool { } break } + // match: (NE (CMPconst [0] x:(ANDconst [c] y)) yes no) + // cond: x.Uses == 1 + // result: (NE (TSTconst [c] y) yes no) + for b.Controls[0].Op == OpARM64CMPconst { + v_0 := b.Controls[0] + if auxIntToInt64(v_0.AuxInt) != 0 { + break + } + x := v_0.Args[0] + if x.Op != OpARM64ANDconst { + break + } + c := auxIntToInt64(x.AuxInt) + y := x.Args[0] + if !(x.Uses == 1) { + break + } + v0 := b.NewValue0(v_0.Pos, OpARM64TSTconst, types.TypeFlags) + v0.AuxInt = int64ToAuxInt(c) + v0.AddArg(y) + b.resetWithControl(BlockARM64NE, v0) + return true + } // match: (NE (CMPWconst [0] z:(AND x y)) yes no) // cond: z.Uses == 1 // result: (NE (TSTW x y) yes no) @@ -29707,12 +30253,12 @@ func rewriteBlockARM64(b *Block) bool { } break } - // match: (NE (CMPconst [0] x:(ANDconst [c] y)) yes no) + // match: (NE (CMPWconst [0] x:(ANDconst [c] y)) yes no) // cond: x.Uses == 1 - // result: (NE (TSTconst [c] y) yes no) - for b.Controls[0].Op == OpARM64CMPconst { + // result: (NE (TSTWconst [int32(c)] y) yes no) + for b.Controls[0].Op == OpARM64CMPWconst { v_0 := b.Controls[0] - if auxIntToInt64(v_0.AuxInt) != 0 { + if auxIntToInt32(v_0.AuxInt) != 0 { break } x := v_0.Args[0] @@ -29724,8 +30270,8 @@ func rewriteBlockARM64(b *Block) bool { if !(x.Uses == 1) { break } - v0 := b.NewValue0(v_0.Pos, OpARM64TSTconst, types.TypeFlags) - v0.AuxInt = int64ToAuxInt(c) + v0 := b.NewValue0(v_0.Pos, OpARM64TSTWconst, types.TypeFlags) + v0.AuxInt = int32ToAuxInt(int32(c)) v0.AddArg(y) b.resetWithControl(BlockARM64NE, v0) return true diff --git a/test/codegen/arithmetic.go b/test/codegen/arithmetic.go index 00841d52ae..3fb9ce646b 100644 --- a/test/codegen/arithmetic.go +++ b/test/codegen/arithmetic.go @@ -176,7 +176,7 @@ func MergeMuls2(n int) int { // amd64:"IMUL3Q\t[$]23","(ADDQ\t[$]29)|(LEAQ\t29)" // 386:"IMUL3L\t[$]23","ADDL\t[$]29" // ppc64le/power9:"MADDLD",-"MULLD\t[$]23",-"ADD\t[$]29" - // ppc64le/power8:"MULLD\t[$]23","ADD\t[$]29" + // ppc64le/power8:"MULLD\t[$]23","ADD\t[$]29" return 5*n + 7*(n+1) + 11*(n+2) // 23n + 29 } @@ -282,7 +282,7 @@ func Pow2DivisibleSigned(n1, n2 int) (bool, bool) { // 386:"TESTL\t[$]63",-"DIVL",-"SHRL" // amd64:"TESTQ\t[$]63",-"DIVQ",-"SHRQ" // arm:"AND\t[$]63",-".*udiv",-"SRA" - // arm64:"AND\t[$]63",-"UDIV",-"ASR" + // arm64:"TST\t[$]63",-"UDIV",-"ASR",-"AND" // ppc64:"ANDCC\t[$]63",-"SRAD" // ppc64le:"ANDCC\t[$]63",-"SRAD" a := n1%64 == 0 // signed divisible @@ -290,7 +290,7 @@ func Pow2DivisibleSigned(n1, n2 int) (bool, bool) { // 386:"TESTL\t[$]63",-"DIVL",-"SHRL" // amd64:"TESTQ\t[$]63",-"DIVQ",-"SHRQ" // arm:"AND\t[$]63",-".*udiv",-"SRA" - // arm64:"AND\t[$]63",-"UDIV",-"ASR" + // arm64:"TST\t[$]63",-"UDIV",-"ASR",-"AND" // ppc64:"ANDCC\t[$]63",-"SRAD" // ppc64le:"ANDCC\t[$]63",-"SRAD" b := n2%64 != 0 // signed indivisible @@ -572,16 +572,16 @@ func divInt(v int64) int64 { // "(z + C) -x -> C + (z - x)" can optimize the following cases. func constantFold1(i0, j0, i1, j1, i2, j2, i3, j3 int) (int, int, int, int) { // arm64:"SUB","ADD\t[$]2" - // ppc64:"SUB","ADD\t[$]2" - // ppc64le:"SUB","ADD\t[$]2" + // ppc64:"SUB","ADD\t[$]2" + // ppc64le:"SUB","ADD\t[$]2" r0 := (i0 + 3) - (j0 + 1) // arm64:"SUB","SUB\t[$]4" - // ppc64:"SUB","ADD\t[$]-4" - // ppc64le:"SUB","ADD\t[$]-4" + // ppc64:"SUB","ADD\t[$]-4" + // ppc64le:"SUB","ADD\t[$]-4" r1 := (i1 - 3) - (j1 + 1) // arm64:"SUB","ADD\t[$]4" - // ppc64:"SUB","ADD\t[$]4" - // ppc64le:"SUB","ADD\t[$]4" + // ppc64:"SUB","ADD\t[$]4" + // ppc64le:"SUB","ADD\t[$]4" r2 := (i2 + 3) - (j2 - 1) // arm64:"SUB","SUB\t[$]2" // ppc64:"SUB","ADD\t[$]-2" @@ -606,8 +606,8 @@ func constantFold2(i0, j0, i1, j1 int) (int, int) { func constantFold3(i, j int) int { // arm64: "MOVD\t[$]30","MUL",-"ADD",-"LSL" - // ppc64:"MULLD\t[$]30","MULLD" - // ppc64le:"MULLD\t[$]30","MULLD" + // ppc64:"MULLD\t[$]30","MULLD" + // ppc64le:"MULLD\t[$]30","MULLD" r := (5 * i) * (6 * j) return r } -- 2.50.0