diff --git a/src/cmd/compile/internal/ssa/_gen/ARM64.rules b/src/cmd/compile/internal/ssa/_gen/ARM64.rules
index 01fe3a7..cabc308 100644
--- a/src/cmd/compile/internal/ssa/_gen/ARM64.rules
+++ b/src/cmd/compile/internal/ssa/_gen/ARM64.rules
@@ -680,8 +680,13 @@
((CMPconst|CMNconst) [c] y) && c < 0 && c != -1<<63 => ((CMNconst|CMPconst) [-c] y)
((CMPWconst|CMNWconst) [c] y) && c < 0 && c != -1<<31 => ((CMNWconst|CMPWconst) [-c] y)
-((EQ|NE) (CMPconst [0] x) yes no) => ((Z|NZ) x yes no)
-((EQ|NE) (CMPWconst [0] x) yes no) => ((ZW|NZW) x yes no)
+((EQ|NE|ULE|UGT) (CMPconst [0] (SUB x y)) yes no) => ((EQ|NE|EQ|NE) (CMP x y) yes no)
+((EQ|NE|ULE|UGT) (CMPWconst [0] (SUB x y)) yes no) => ((EQ|NE|EQ|NE) (CMPW x y) yes no)
+((EQ|NE|ULE|UGT) (CMPconst [0] (SUBconst [c] y)) yes no) => ((EQ|NE|EQ|NE) (CMPconst [c] y) yes no)
+((EQ|NE|ULE|UGT) (CMPWconst [0] (SUBconst [c] y)) yes no) => ((EQ|NE|EQ|NE) (CMPWconst [int32(c)] y) yes no)
+
+((EQ|NE|ULE|UGT) (CMPconst [0] x) yes no) => ((Z|NZ|Z|NZ) x yes no)
+((EQ|NE|ULE|UGT) (CMPWconst [0] x) yes no) => ((ZW|NZW|ZW|NZW) x yes no)
((EQ|NE|LT|LE|GT|GE) (CMPconst [0] z:(MADD a x y)) yes no) && z.Uses==1 => ((EQ|NE|LTnoov|LEnoov|GTnoov|GEnoov) (CMN a (MUL <x.Type> x y)) yes no)
((EQ|NE|LT|LE|GT|GE) (CMPconst [0] z:(MSUB a x y)) yes no) && z.Uses==1 => ((EQ|NE|LTnoov|LEnoov|GTnoov|GEnoov) (CMP a (MUL <x.Type> x y)) yes no)
diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go
index 792967c..1b5cb4f 100644
--- a/src/cmd/compile/internal/ssa/rewriteARM64.go
+++ b/src/cmd/compile/internal/ssa/rewriteARM64.go
@@ -22615,6 +22615,80 @@
b.resetWithControl(BlockARM64EQ, v0)
return true
}
+ // match: (EQ (CMPconst [0] (SUB x y)) yes no)
+ // result: (EQ (CMP x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SUB {
+ break
+ }
+ y := v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
+ // match: (EQ (CMPWconst [0] (SUB x y)) yes no)
+ // result: (EQ (CMPW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SUB {
+ break
+ }
+ y := v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
+ // match: (EQ (CMPconst [0] (SUBconst [c] y)) yes no)
+ // result: (EQ (CMPconst [c] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SUBconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ y := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMPconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
+ // match: (EQ (CMPWconst [0] (SUBconst [c] y)) yes no)
+ // result: (EQ (CMPWconst [int32(c)] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SUBconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ y := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMPWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
// match: (EQ (CMPconst [0] x) yes no)
// result: (Z x yes no)
for b.Controls[0].Op == OpARM64CMPconst {
@@ -24749,6 +24823,80 @@
b.resetWithControl(BlockARM64NE, v0)
return true
}
+ // match: (NE (CMPconst [0] (SUB x y)) yes no)
+ // result: (NE (CMP x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SUB {
+ break
+ }
+ y := v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
+ // match: (NE (CMPWconst [0] (SUB x y)) yes no)
+ // result: (NE (CMPW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SUB {
+ break
+ }
+ y := v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
+ // match: (NE (CMPconst [0] (SUBconst [c] y)) yes no)
+ // result: (NE (CMPconst [c] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SUBconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ y := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMPconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
+ // match: (NE (CMPWconst [0] (SUBconst [c] y)) yes no)
+ // result: (NE (CMPWconst [int32(c)] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SUBconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ y := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMPWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
// match: (NE (CMPconst [0] x) yes no)
// result: (NZ x yes no)
for b.Controls[0].Op == OpARM64CMPconst {
@@ -25312,6 +25460,102 @@
return true
}
case BlockARM64UGT:
+ // match: (UGT (CMPconst [0] (SUB x y)) yes no)
+ // result: (NE (CMP x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SUB {
+ break
+ }
+ y := v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
+ // match: (UGT (CMPWconst [0] (SUB x y)) yes no)
+ // result: (NE (CMPW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SUB {
+ break
+ }
+ y := v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
+ // match: (UGT (CMPconst [0] (SUBconst [c] y)) yes no)
+ // result: (NE (CMPconst [c] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SUBconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ y := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMPconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
+ // match: (UGT (CMPWconst [0] (SUBconst [c] y)) yes no)
+ // result: (NE (CMPWconst [int32(c)] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SUBconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ y := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMPWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64NE, v0)
+ return true
+ }
+ // match: (UGT (CMPconst [0] x) yes no)
+ // result: (NZ x 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]
+ b.resetWithControl(BlockARM64NZ, x)
+ return true
+ }
+ // match: (UGT (CMPWconst [0] x) yes no)
+ // result: (NZW x 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]
+ b.resetWithControl(BlockARM64NZW, x)
+ return true
+ }
// match: (UGT (FlagConstant [fc]) yes no)
// cond: fc.ugt()
// result: (First yes no)
@@ -25346,6 +25590,102 @@
return true
}
case BlockARM64ULE:
+ // match: (ULE (CMPconst [0] (SUB x y)) yes no)
+ // result: (EQ (CMP x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SUB {
+ break
+ }
+ y := v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMP, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
+ // match: (ULE (CMPWconst [0] (SUB x y)) yes no)
+ // result: (EQ (CMPW x y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SUB {
+ break
+ }
+ y := v_0_0.Args[1]
+ x := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMPW, types.TypeFlags)
+ v0.AddArg2(x, y)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
+ // match: (ULE (CMPconst [0] (SUBconst [c] y)) yes no)
+ // result: (EQ (CMPconst [c] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt64(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SUBconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ y := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMPconst, types.TypeFlags)
+ v0.AuxInt = int64ToAuxInt(c)
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
+ // match: (ULE (CMPWconst [0] (SUBconst [c] y)) yes no)
+ // result: (EQ (CMPWconst [int32(c)] y) yes no)
+ for b.Controls[0].Op == OpARM64CMPWconst {
+ v_0 := b.Controls[0]
+ if auxIntToInt32(v_0.AuxInt) != 0 {
+ break
+ }
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpARM64SUBconst {
+ break
+ }
+ c := auxIntToInt64(v_0_0.AuxInt)
+ y := v_0_0.Args[0]
+ v0 := b.NewValue0(v_0.Pos, OpARM64CMPWconst, types.TypeFlags)
+ v0.AuxInt = int32ToAuxInt(int32(c))
+ v0.AddArg(y)
+ b.resetWithControl(BlockARM64EQ, v0)
+ return true
+ }
+ // match: (ULE (CMPconst [0] x) yes no)
+ // result: (Z x 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]
+ b.resetWithControl(BlockARM64Z, x)
+ return true
+ }
+ // match: (ULE (CMPWconst [0] x) yes no)
+ // result: (ZW x 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]
+ b.resetWithControl(BlockARM64ZW, x)
+ return true
+ }
// match: (ULE (FlagConstant [fc]) yes no)
// cond: fc.ule()
// result: (First yes no)
diff --git a/test/codegen/slices.go b/test/codegen/slices.go
index 9e8990c..4804c80 100644
--- a/test/codegen/slices.go
+++ b/test/codegen/slices.go
@@ -429,3 +429,21 @@
// amd64:-"MULQ"
return unsafe.Slice(p, i)
}
+
+// --------------------------------------- //
+// Code generation for slice bounds //
+// checking comparison //
+// --------------------------------------- //
+
+func SlicePut(a []byte, c uint8) []byte {
+ // arm64:`CBZ\tR1`
+ a[0] = c
+ a = a[1:]
+ // arm64:`CMP\t\$1, R1`
+ a[0] = c
+ a = a[1:]
+ // arm64:`CMP\t\$2, R1`
+ a[0] = c
+ a = a[1:]
+ return a
+}