]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/ssa: optimize ARM64 code with TST
authoreric fang <eric.fang@arm.com>
Fri, 29 Jul 2022 04:05:03 +0000 (04:05 +0000)
committerEric Fang <eric.fang@arm.com>
Wed, 10 Aug 2022 02:13:53 +0000 (02:13 +0000)
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 <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Run-TryBot: Eric Fang <eric.fang@arm.com>

src/cmd/compile/internal/ssa/gen/ARM64.rules
src/cmd/compile/internal/ssa/rewriteARM64.go
test/codegen/arithmetic.go

index 3776b3ca026d4ac3a71b8c361c2227fa156af4a4..e3d77be0b47fd8980c449082587060bb6cab3f47 100644 (file)
 (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)
 (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)
 (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)
index efeadf64cc8ea893346c03d3ccd4e264fd4f07e0..7845e9cf1d65f9f696a19d7afc225525c5a3daf5 100644 (file)
@@ -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
index 00841d52ae27db5c9be6f59fefd9512103c26e8e..3fb9ce646b81c371968ed3062f8f1467a6ef7b17 100644 (file)
@@ -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
 }