cmd/compile: optimize arm64's comparison
Add more optimization with TST/CMN.
1. A tiny benchmark shows more than 12% improvement.
TSTCMN-4 378µs ± 0% 332µs ± 0% -12.15% (p=0.000 n=30+27)
(https://github.com/benshi001/ugo1/blob/master/tstcmn_test.go)
2. There is little regression in the go1 benchmark, excluding noise.
name old time/op new time/op delta
BinaryTree17-4 19.1s ± 0% 19.1s ± 0% ~ (p=0.994 n=28+29)
Fannkuch11-4 10.0s ± 0% 10.0s ± 0% ~ (p=0.198 n=30+25)
FmtFprintfEmpty-4 233ns ± 0% 233ns ± 0% +0.14% (p=0.002 n=24+30)
FmtFprintfString-4 428ns ± 0% 428ns ± 0% ~ (all equal)
FmtFprintfInt-4 472ns ± 0% 472ns ± 0% ~ (all equal)
FmtFprintfIntInt-4 725ns ± 0% 725ns ± 0% ~ (all equal)
FmtFprintfPrefixedInt-4 889ns ± 0% 888ns ± 0% ~ (p=0.632 n=28+30)
FmtFprintfFloat-4 1.20µs ± 0% 1.20µs ± 0% +0.05% (p=0.001 n=18+30)
FmtManyArgs-4 3.00µs ± 0% 2.99µs ± 0% -0.07% (p=0.001 n=27+30)
GobDecode-4 42.1ms ± 0% 42.2ms ± 0% +0.29% (p=0.000 n=28+28)
GobEncode-4 38.6ms ± 9% 38.8ms ± 9% ~ (p=0.912 n=30+30)
Gzip-4 2.07s ± 1% 2.05s ± 1% -0.64% (p=0.000 n=29+30)
Gunzip-4 175ms ± 0% 175ms ± 0% -0.15% (p=0.001 n=30+30)
HTTPClientServer-4 872µs ± 5% 880µs ± 6% ~ (p=0.196 n=30+29)
JSONEncode-4 88.5ms ± 1% 89.8ms ± 1% +1.49% (p=0.000 n=23+24)
JSONDecode-4 393ms ± 1% 390ms ± 1% -0.89% (p=0.000 n=28+30)
Mandelbrot200-4 19.5ms ± 0% 19.5ms ± 0% ~ (p=0.405 n=29+28)
GoParse-4 19.9ms ± 0% 20.0ms ± 0% +0.27% (p=0.000 n=30+30)
RegexpMatchEasy0_32-4 431ns ± 0% 431ns ± 0% ~ (p=1.000 n=30+30)
RegexpMatchEasy0_1K-4 1.61µs ± 0% 1.61µs ± 0% ~ (p=0.527 n=26+26)
RegexpMatchEasy1_32-4 443ns ± 0% 443ns ± 0% ~ (all equal)
RegexpMatchEasy1_1K-4 2.58µs ± 1% 2.58µs ± 1% ~ (p=0.578 n=27+25)
RegexpMatchMedium_32-4 740ns ± 0% 740ns ± 0% ~ (p=0.357 n=30+30)
RegexpMatchMedium_1K-4 223µs ± 0% 223µs ± 0% +0.16% (p=0.000 n=30+29)
RegexpMatchHard_32-4 12.3µs ± 0% 12.3µs ± 0% ~ (p=0.236 n=27+27)
RegexpMatchHard_1K-4 371µs ± 0% 371µs ± 0% +0.09% (p=0.000 n=30+27)
Revcomp-4 2.85s ± 0% 2.85s ± 0% ~ (p=0.057 n=28+25)
Template-4 408ms ± 1% 409ms ± 1% ~ (p=0.117 n=29+29)
TimeParse-4 1.93µs ± 0% 1.93µs ± 0% ~ (p=0.535 n=29+28)
TimeFormat-4 1.99µs ± 0% 1.99µs ± 0% ~ (p=0.168 n=29+28)
[Geo mean] 306µs 307µs +0.07%
name old speed new speed delta
GobDecode-4 18.3MB/s ± 0% 18.2MB/s ± 0% -0.31% (p=0.000 n=28+29)
GobEncode-4 19.9MB/s ± 8% 19.8MB/s ± 9% ~ (p=0.923 n=30+30)
Gzip-4 9.39MB/s ± 1% 9.45MB/s ± 1% +0.65% (p=0.000 n=29+30)
Gunzip-4 111MB/s ± 0% 111MB/s ± 0% +0.15% (p=0.001 n=30+30)
JSONEncode-4 21.9MB/s ± 1% 21.6MB/s ± 1% -1.45% (p=0.000 n=23+23)
JSONDecode-4 4.94MB/s ± 1% 4.98MB/s ± 1% +0.84% (p=0.000 n=27+30)
GoParse-4 2.91MB/s ± 0% 2.90MB/s ± 0% -0.34% (p=0.000 n=21+22)
RegexpMatchEasy0_32-4 74.1MB/s ± 0% 74.1MB/s ± 0% ~ (p=0.469 n=29+28)
RegexpMatchEasy0_1K-4 634MB/s ± 0% 634MB/s ± 0% ~ (p=0.978 n=24+28)
RegexpMatchEasy1_32-4 72.2MB/s ± 0% 72.2MB/s ± 0% ~ (p=0.064 n=27+29)
RegexpMatchEasy1_1K-4 396MB/s ± 1% 396MB/s ± 1% ~ (p=0.583 n=27+25)
RegexpMatchMedium_32-4 1.35MB/s ± 0% 1.35MB/s ± 0% ~ (all equal)
RegexpMatchMedium_1K-4 4.60MB/s ± 0% 4.59MB/s ± 0% -0.14% (p=0.000 n=30+26)
RegexpMatchHard_32-4 2.61MB/s ± 0% 2.61MB/s ± 0% ~ (all equal)
RegexpMatchHard_1K-4 2.76MB/s ± 0% 2.76MB/s ± 0% ~ (all equal)
Revcomp-4 89.1MB/s ± 0% 89.1MB/s ± 0% ~ (p=0.059 n=28+25)
Template-4 4.75MB/s ± 1% 4.75MB/s ± 1% ~ (p=0.106 n=29+29)
[Geo mean] 18.3MB/s 18.3MB/s -0.07%
Change-Id: I3cd76ce63e84b0c3cebabf9fa3573b76a7343899
Reviewed-on: https://go-review.googlesource.com/124935
Run-TryBot: Ben Shi <powerman1st@163.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules
index 374ece2..ede7ed3 100644
--- a/src/cmd/compile/internal/ssa/gen/ARM64.rules
+++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules
@@ -574,8 +574,17 @@
(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)
+(LE (CMPconst [0] z:(AND x y)) yes no) && z.Uses == 1 -> (LE (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 (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)
+(LE (CMPWconst [0] z:(AND x y)) yes no) && z.Uses == 1 -> (LE (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)
@@ -584,10 +593,47 @@
(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 (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)
+(LT (CMPconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (LT (CMNconst [c] y) yes no)
+(LE (CMPconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (LE (CMNconst [c] y) yes no)
+(GT (CMPconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (GT (CMNconst [c] y) yes no)
+(GE (CMPconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (GE (CMNconst [c] y) yes no)
+
+(EQ (CMPWconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (EQ (CMNWconst [c] y) yes no)
+(NE (CMPWconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (NE (CMNWconst [c] y) yes no)
+(LT (CMPWconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (LT (CMNWconst [c] y) yes no)
+(LE (CMPWconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (LE (CMNWconst [c] y) yes no)
+(GT (CMPWconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (GT (CMNWconst [c] y) yes no)
+(GE (CMPWconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (GE (CMNWconst [c] y) yes no)
+
(EQ (CMPconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (EQ (CMN x y) yes no)
(NE (CMPconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (NE (CMN x y) yes no)
+(LT (CMPconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (LT (CMN x y) yes no)
+(LE (CMPconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (LE (CMN x y) yes no)
+(GT (CMPconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (GT (CMN x y) yes no)
+(GE (CMPconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (GE (CMN x y) yes no)
+
+(EQ (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (EQ (CMNW x y) yes no)
+(NE (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (NE (CMNW x y) yes no)
+(LT (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (LT (CMNW x y) yes no)
+(LE (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (LE (CMNW x y) yes no)
+(GT (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (GT (CMNW x y) yes no)
+(GE (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (GE (CMNW x y) yes no)
+
(EQ (CMP x z:(NEG y)) yes no) && z.Uses == 1 -> (EQ (CMN x y) yes no)
(NE (CMP x z:(NEG y)) yes no) && z.Uses == 1 -> (NE (CMN x y) yes no)
+(LT (CMP x z:(NEG y)) yes no) && z.Uses == 1 -> (LT (CMN x y) yes no)
+(LE (CMP x z:(NEG y)) yes no) && z.Uses == 1 -> (LE (CMN x y) yes no)
+(GT (CMP x z:(NEG y)) yes no) && z.Uses == 1 -> (GT (CMN x y) yes no)
+(GE (CMP x z:(NEG y)) yes no) && z.Uses == 1 -> (GE (CMN x y) yes no)
+
+(EQ (CMPW x z:(NEG y)) yes no) && z.Uses == 1 -> (EQ (CMNW x y) yes no)
+(NE (CMPW x z:(NEG y)) yes no) && z.Uses == 1 -> (NE (CMNW x y) yes no)
+(LT (CMPW x z:(NEG y)) yes no) && z.Uses == 1 -> (LT (CMNW x y) yes no)
+(LE (CMPW x z:(NEG y)) yes no) && z.Uses == 1 -> (LE (CMNW x y) yes no)
+(GT (CMPW x z:(NEG y)) yes no) && z.Uses == 1 -> (GT (CMNW x y) yes no)
+(GE (CMPW x z:(NEG y)) yes no) && z.Uses == 1 -> (GE (CMNW x y) yes no)
(EQ (CMPconst [0] x) yes no) -> (Z x yes no)
(NE (CMPconst [0] x) yes no) -> (NZ x yes no)
@@ -1066,7 +1112,9 @@
(OR x (MOVDconst [c])) -> (ORconst [c] x)
(XOR x (MOVDconst [c])) -> (XORconst [c] x)
(TST x (MOVDconst [c])) -> (TSTconst [c] x)
+(TSTW x (MOVDconst [c])) -> (TSTWconst [c] x)
(CMN x (MOVDconst [c])) -> (CMNconst [c] x)
+(CMNW x (MOVDconst [c])) -> (CMNWconst [c] x)
(BIC x (MOVDconst [c])) -> (ANDconst [^c] x)
(EON x (MOVDconst [c])) -> (XORconst [^c] x)
(ORN x (MOVDconst [c])) -> (ORconst [^c] x)
diff --git a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go
index 2c434f4..eb0ad53 100644
--- a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go
+++ b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go
@@ -258,13 +258,13 @@
{name: "CMPconst", argLength: 1, reg: gp1flags, asm: "CMP", aux: "Int64", typ: "Flags"}, // arg0 compare to auxInt
{name: "CMPW", argLength: 2, reg: gp2flags, asm: "CMPW", typ: "Flags"}, // arg0 compare to arg1, 32 bit
{name: "CMPWconst", argLength: 1, reg: gp1flags, asm: "CMPW", aux: "Int32", typ: "Flags"}, // arg0 compare to auxInt, 32 bit
- {name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags"}, // arg0 compare to -arg1
+ {name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags", commutative: true}, // arg0 compare to -arg1
{name: "CMNconst", argLength: 1, reg: gp1flags, asm: "CMN", aux: "Int64", typ: "Flags"}, // arg0 compare to -auxInt
- {name: "CMNW", argLength: 2, reg: gp2flags, asm: "CMNW", typ: "Flags"}, // arg0 compare to -arg1, 32 bit
+ {name: "CMNW", argLength: 2, reg: gp2flags, asm: "CMNW", typ: "Flags", commutative: true}, // arg0 compare to -arg1, 32 bit
{name: "CMNWconst", argLength: 1, reg: gp1flags, asm: "CMNW", aux: "Int32", typ: "Flags"}, // arg0 compare to -auxInt, 32 bit
- {name: "TST", argLength: 2, reg: gp2flags, asm: "TST", typ: "Flags"}, // arg0 & arg1 compare to 0
+ {name: "TST", argLength: 2, reg: gp2flags, asm: "TST", typ: "Flags", commutative: true}, // arg0 & arg1 compare to 0
{name: "TSTconst", argLength: 1, reg: gp1flags, asm: "TST", aux: "Int64", typ: "Flags"}, // arg0 & auxInt compare to 0
- {name: "TSTW", argLength: 2, reg: gp2flags, asm: "TSTW", typ: "Flags"}, // arg0 & arg1 compare to 0, 32 bit
+ {name: "TSTW", argLength: 2, reg: gp2flags, asm: "TSTW", typ: "Flags", commutative: true}, // arg0 & arg1 compare to 0, 32 bit
{name: "TSTWconst", argLength: 1, reg: gp1flags, asm: "TSTW", aux: "Int32", typ: "Flags"}, // arg0 & auxInt compare to 0, 32 bit
{name: "FCMPS", argLength: 2, reg: fp2flags, asm: "FCMPS", typ: "Flags"}, // arg0 compare to arg1, float32
{name: "FCMPD", argLength: 2, reg: fp2flags, asm: "FCMPD", typ: "Flags"}, // arg0 compare to arg1, float64
diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go
index 6243bfc..0ff15db 100644
--- a/src/cmd/compile/internal/ssa/opGen.go
+++ b/src/cmd/compile/internal/ssa/opGen.go
@@ -15205,9 +15205,10 @@
},
},
{
- name: "CMN",
- argLen: 2,
- asm: arm64.ACMN,
+ name: "CMN",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.ACMN,
reg: regInfo{
inputs: []inputInfo{
{0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
@@ -15227,9 +15228,10 @@
},
},
{
- name: "CMNW",
- argLen: 2,
- asm: arm64.ACMNW,
+ name: "CMNW",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.ACMNW,
reg: regInfo{
inputs: []inputInfo{
{0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
@@ -15249,9 +15251,10 @@
},
},
{
- name: "TST",
- argLen: 2,
- asm: arm64.ATST,
+ name: "TST",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.ATST,
reg: regInfo{
inputs: []inputInfo{
{0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
@@ -15271,9 +15274,10 @@
},
},
{
- name: "TSTW",
- argLen: 2,
- asm: arm64.ATSTW,
+ name: "TSTW",
+ argLen: 2,
+ commutative: true,
+ asm: arm64.ATSTW,
reg: regInfo{
inputs: []inputInfo{
{0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go
index a84d1af..fbdf352 100644
--- a/src/cmd/compile/internal/ssa/rewriteARM64.go
+++ b/src/cmd/compile/internal/ssa/rewriteARM64.go
@@ -45,6 +45,8 @@
return rewriteValueARM64_OpARM64BICshiftRL_0(v)
case OpARM64CMN:
return rewriteValueARM64_OpARM64CMN_0(v)
+ case OpARM64CMNW:
+ return rewriteValueARM64_OpARM64CMNW_0(v)
case OpARM64CMNWconst:
return rewriteValueARM64_OpARM64CMNWconst_0(v)
case OpARM64CMNconst:
@@ -295,6 +297,8 @@
return rewriteValueARM64_OpARM64SUBshiftRL_0(v)
case OpARM64TST:
return rewriteValueARM64_OpARM64TST_0(v)
+ case OpARM64TSTW:
+ return rewriteValueARM64_OpARM64TSTW_0(v)
case OpARM64TSTWconst:
return rewriteValueARM64_OpARM64TSTWconst_0(v)
case OpARM64TSTconst:
@@ -2375,6 +2379,57 @@
v.AddArg(x)
return true
}
+ // match: (CMN (MOVDconst [c]) x)
+ // cond:
+ // result: (CMNconst [c] x)
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v.Args[1]
+ v.reset(OpARM64CMNconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64CMNW_0(v *Value) bool {
+ // match: (CMNW x (MOVDconst [c]))
+ // cond:
+ // result: (CMNWconst [c] x)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ v.reset(OpARM64CMNWconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
+ // match: (CMNW (MOVDconst [c]) x)
+ // cond:
+ // result: (CMNWconst [c] x)
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v.Args[1]
+ v.reset(OpARM64CMNWconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
return false
}
func rewriteValueARM64_OpARM64CMNWconst_0(v *Value) bool {
@@ -25219,6 +25274,57 @@
v.AddArg(x)
return true
}
+ // match: (TST (MOVDconst [c]) x)
+ // cond:
+ // result: (TSTconst [c] x)
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v.Args[1]
+ v.reset(OpARM64TSTconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
+ return false
+}
+func rewriteValueARM64_OpARM64TSTW_0(v *Value) bool {
+ // match: (TSTW x (MOVDconst [c]))
+ // cond:
+ // result: (TSTWconst [c] x)
+ for {
+ _ = v.Args[1]
+ x := v.Args[0]
+ v_1 := v.Args[1]
+ if v_1.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_1.AuxInt
+ v.reset(OpARM64TSTWconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
+ // match: (TSTW (MOVDconst [c]) x)
+ // cond:
+ // result: (TSTWconst [c] x)
+ for {
+ _ = v.Args[1]
+ v_0 := v.Args[0]
+ if v_0.Op != OpARM64MOVDconst {
+ break
+ }
+ c := v_0.AuxInt
+ x := v.Args[1]
+ v.reset(OpARM64TSTWconst)
+ v.AuxInt = c
+ v.AddArg(x)
+ return true
+ }
return false
}
func rewriteValueARM64_OpARM64TSTWconst_0(v *Value) bool {
@@ -32789,6 +32895,62 @@
b.Aux = nil
return true
}
+ // match: (EQ (CMPconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (EQ (CMNconst [c] y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ x := v.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := x.AuxInt
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64EQ
+ v0 := b.NewValue0(v.Pos, OpARM64CMNconst, types.TypeFlags)
+ v0.AuxInt = c
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (EQ (CMPWconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (EQ (CMNWconst [c] y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPWconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ x := v.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := x.AuxInt
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64EQ
+ v0 := b.NewValue0(v.Pos, OpARM64CMNWconst, types.TypeFlags)
+ v0.AuxInt = c
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
// match: (EQ (CMPconst [0] z:(ADD x y)) yes no)
// cond: z.Uses == 1
// result: (EQ (CMN x y) yes no)
@@ -32818,6 +32980,35 @@
b.Aux = nil
return true
}
+ // match: (EQ (CMPWconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (EQ (CMNW x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPWconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ z := v.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ x := z.Args[0]
+ y := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64EQ
+ v0 := b.NewValue0(v.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
// match: (EQ (CMP x z:(NEG y)) yes no)
// cond: z.Uses == 1
// result: (EQ (CMN x y) yes no)
@@ -32844,6 +33035,32 @@
b.Aux = nil
return true
}
+ // match: (EQ (CMPW x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (EQ (CMNW x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPW {
+ break
+ }
+ _ = v.Args[1]
+ x := v.Args[0]
+ z := v.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64EQ
+ v0 := b.NewValue0(v.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
// match: (EQ (CMPconst [0] x) yes no)
// cond:
// result: (Z x yes no)
@@ -33158,6 +33375,64 @@
b.Aux = nil
return true
}
+ // match: (GE (CMPconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GE (TST x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ z := v.Args[0]
+ if z.Op != OpARM64AND {
+ break
+ }
+ _ = z.Args[1]
+ x := z.Args[0]
+ y := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64GE
+ v0 := b.NewValue0(v.Pos, OpARM64TST, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (GE (CMPWconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GE (TSTW x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPWconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ z := v.Args[0]
+ if z.Op != OpARM64AND {
+ break
+ }
+ _ = z.Args[1]
+ x := z.Args[0]
+ y := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64GE
+ v0 := b.NewValue0(v.Pos, OpARM64TSTW, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
// match: (GE (CMPconst [0] x:(ANDconst [c] y)) yes no)
// cond: x.Uses == 1
// result: (GE (TSTconst [c] y) yes no)
@@ -33186,6 +33461,172 @@
b.Aux = nil
return true
}
+ // match: (GE (CMPconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (GE (CMNconst [c] y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ x := v.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := x.AuxInt
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64GE
+ v0 := b.NewValue0(v.Pos, OpARM64CMNconst, types.TypeFlags)
+ v0.AuxInt = c
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (GE (CMPWconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (GE (CMNWconst [c] y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPWconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ x := v.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := x.AuxInt
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64GE
+ v0 := b.NewValue0(v.Pos, OpARM64CMNWconst, types.TypeFlags)
+ v0.AuxInt = c
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (GE (CMPconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GE (CMN x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ z := v.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ x := z.Args[0]
+ y := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64GE
+ v0 := b.NewValue0(v.Pos, OpARM64CMN, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (GE (CMPWconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GE (CMNW x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPWconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ z := v.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ x := z.Args[0]
+ y := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64GE
+ v0 := b.NewValue0(v.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (GE (CMP x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GE (CMN x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMP {
+ break
+ }
+ _ = v.Args[1]
+ x := v.Args[0]
+ z := v.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64GE
+ v0 := b.NewValue0(v.Pos, OpARM64CMN, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (GE (CMPW x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GE (CMNW x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPW {
+ break
+ }
+ _ = v.Args[1]
+ x := v.Args[0]
+ z := v.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64GE
+ v0 := b.NewValue0(v.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
// match: (GE (CMPconst [0] z:(MADD a x y)) yes no)
// cond: z.Uses==1
// result: (GE (CMN a (MUL <x.Type> x y)) yes no)
@@ -33462,6 +33903,64 @@
b.Aux = nil
return true
}
+ // match: (GT (CMPconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GT (TST x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ z := v.Args[0]
+ if z.Op != OpARM64AND {
+ break
+ }
+ _ = z.Args[1]
+ x := z.Args[0]
+ y := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64GT
+ v0 := b.NewValue0(v.Pos, OpARM64TST, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (GT (CMPWconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GT (TSTW x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPWconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ z := v.Args[0]
+ if z.Op != OpARM64AND {
+ break
+ }
+ _ = z.Args[1]
+ x := z.Args[0]
+ y := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64GT
+ v0 := b.NewValue0(v.Pos, OpARM64TSTW, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
// match: (GT (CMPconst [0] x:(ANDconst [c] y)) yes no)
// cond: x.Uses == 1
// result: (GT (TSTconst [c] y) yes no)
@@ -33490,6 +33989,172 @@
b.Aux = nil
return true
}
+ // match: (GT (CMPconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (GT (CMNconst [c] y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ x := v.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := x.AuxInt
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64GT
+ v0 := b.NewValue0(v.Pos, OpARM64CMNconst, types.TypeFlags)
+ v0.AuxInt = c
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (GT (CMPWconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (GT (CMNWconst [c] y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPWconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ x := v.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := x.AuxInt
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64GT
+ v0 := b.NewValue0(v.Pos, OpARM64CMNWconst, types.TypeFlags)
+ v0.AuxInt = c
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (GT (CMPconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GT (CMN x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ z := v.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ x := z.Args[0]
+ y := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64GT
+ v0 := b.NewValue0(v.Pos, OpARM64CMN, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (GT (CMPWconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GT (CMNW x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPWconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ z := v.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ x := z.Args[0]
+ y := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64GT
+ v0 := b.NewValue0(v.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (GT (CMP x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GT (CMN x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMP {
+ break
+ }
+ _ = v.Args[1]
+ x := v.Args[0]
+ z := v.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64GT
+ v0 := b.NewValue0(v.Pos, OpARM64CMN, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (GT (CMPW x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (GT (CMNW x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPW {
+ break
+ }
+ _ = v.Args[1]
+ x := v.Args[0]
+ z := v.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64GT
+ v0 := b.NewValue0(v.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
// match: (GT (CMPconst [0] z:(MADD a x y)) yes no)
// cond: z.Uses==1
// result: (GT (CMN a (MUL <x.Type> x y)) yes no)
@@ -33886,6 +34551,64 @@
b.Aux = nil
return true
}
+ // match: (LE (CMPconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LE (TST x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ z := v.Args[0]
+ if z.Op != OpARM64AND {
+ break
+ }
+ _ = z.Args[1]
+ x := z.Args[0]
+ y := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64LE
+ v0 := b.NewValue0(v.Pos, OpARM64TST, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (LE (CMPWconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LE (TSTW x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPWconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ z := v.Args[0]
+ if z.Op != OpARM64AND {
+ break
+ }
+ _ = z.Args[1]
+ x := z.Args[0]
+ y := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64LE
+ v0 := b.NewValue0(v.Pos, OpARM64TSTW, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
// match: (LE (CMPconst [0] x:(ANDconst [c] y)) yes no)
// cond: x.Uses == 1
// result: (LE (TSTconst [c] y) yes no)
@@ -33914,6 +34637,172 @@
b.Aux = nil
return true
}
+ // match: (LE (CMPconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (LE (CMNconst [c] y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ x := v.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := x.AuxInt
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64LE
+ v0 := b.NewValue0(v.Pos, OpARM64CMNconst, types.TypeFlags)
+ v0.AuxInt = c
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (LE (CMPWconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (LE (CMNWconst [c] y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPWconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ x := v.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := x.AuxInt
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64LE
+ v0 := b.NewValue0(v.Pos, OpARM64CMNWconst, types.TypeFlags)
+ v0.AuxInt = c
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (LE (CMPconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LE (CMN x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ z := v.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ x := z.Args[0]
+ y := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64LE
+ v0 := b.NewValue0(v.Pos, OpARM64CMN, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (LE (CMPWconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LE (CMNW x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPWconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ z := v.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ x := z.Args[0]
+ y := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64LE
+ v0 := b.NewValue0(v.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (LE (CMP x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LE (CMN x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMP {
+ break
+ }
+ _ = v.Args[1]
+ x := v.Args[0]
+ z := v.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64LE
+ v0 := b.NewValue0(v.Pos, OpARM64CMN, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (LE (CMPW x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LE (CMNW x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPW {
+ break
+ }
+ _ = v.Args[1]
+ x := v.Args[0]
+ z := v.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64LE
+ v0 := b.NewValue0(v.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
// match: (LE (CMPconst [0] z:(MADD a x y)) yes no)
// cond: z.Uses==1
// result: (LE (CMN a (MUL <x.Type> x y)) yes no)
@@ -34156,6 +35045,64 @@
b.Aux = nil
return true
}
+ // match: (LT (CMPconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LT (TST x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ z := v.Args[0]
+ if z.Op != OpARM64AND {
+ break
+ }
+ _ = z.Args[1]
+ x := z.Args[0]
+ y := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64LT
+ v0 := b.NewValue0(v.Pos, OpARM64TST, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (LT (CMPWconst [0] z:(AND x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LT (TSTW x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPWconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ z := v.Args[0]
+ if z.Op != OpARM64AND {
+ break
+ }
+ _ = z.Args[1]
+ x := z.Args[0]
+ y := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64LT
+ v0 := b.NewValue0(v.Pos, OpARM64TSTW, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
// match: (LT (CMPconst [0] x:(ANDconst [c] y)) yes no)
// cond: x.Uses == 1
// result: (LT (TSTconst [c] y) yes no)
@@ -34184,6 +35131,172 @@
b.Aux = nil
return true
}
+ // match: (LT (CMPconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (LT (CMNconst [c] y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ x := v.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := x.AuxInt
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64LT
+ v0 := b.NewValue0(v.Pos, OpARM64CMNconst, types.TypeFlags)
+ v0.AuxInt = c
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (LT (CMPWconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (LT (CMNWconst [c] y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPWconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ x := v.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := x.AuxInt
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64LT
+ v0 := b.NewValue0(v.Pos, OpARM64CMNWconst, types.TypeFlags)
+ v0.AuxInt = c
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (LT (CMPconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LT (CMN x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ z := v.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ x := z.Args[0]
+ y := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64LT
+ v0 := b.NewValue0(v.Pos, OpARM64CMN, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (LT (CMPWconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LT (CMNW x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPWconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ z := v.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ x := z.Args[0]
+ y := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64LT
+ v0 := b.NewValue0(v.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (LT (CMP x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LT (CMN x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMP {
+ break
+ }
+ _ = v.Args[1]
+ x := v.Args[0]
+ z := v.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64LT
+ v0 := b.NewValue0(v.Pos, OpARM64CMN, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (LT (CMPW x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (LT (CMNW x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPW {
+ break
+ }
+ _ = v.Args[1]
+ x := v.Args[0]
+ z := v.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64LT
+ v0 := b.NewValue0(v.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
// match: (LT (CMPconst [0] z:(MADD a x y)) yes no)
// cond: z.Uses==1
// result: (LT (CMN a (MUL <x.Type> x y)) yes no)
@@ -34547,6 +35660,62 @@
b.Aux = nil
return true
}
+ // match: (NE (CMPconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (NE (CMNconst [c] y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ x := v.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := x.AuxInt
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64NE
+ v0 := b.NewValue0(v.Pos, OpARM64CMNconst, types.TypeFlags)
+ v0.AuxInt = c
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
+ // match: (NE (CMPWconst [0] x:(ADDconst [c] y)) yes no)
+ // cond: x.Uses == 1
+ // result: (NE (CMNWconst [c] y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPWconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ x := v.Args[0]
+ if x.Op != OpARM64ADDconst {
+ break
+ }
+ c := x.AuxInt
+ y := x.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64NE
+ v0 := b.NewValue0(v.Pos, OpARM64CMNWconst, types.TypeFlags)
+ v0.AuxInt = c
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
// match: (NE (CMPconst [0] z:(ADD x y)) yes no)
// cond: z.Uses == 1
// result: (NE (CMN x y) yes no)
@@ -34576,6 +35745,35 @@
b.Aux = nil
return true
}
+ // match: (NE (CMPWconst [0] z:(ADD x y)) yes no)
+ // cond: z.Uses == 1
+ // result: (NE (CMNW x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPWconst {
+ break
+ }
+ if v.AuxInt != 0 {
+ break
+ }
+ z := v.Args[0]
+ if z.Op != OpARM64ADD {
+ break
+ }
+ _ = z.Args[1]
+ x := z.Args[0]
+ y := z.Args[1]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64NE
+ v0 := b.NewValue0(v.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
// match: (NE (CMP x z:(NEG y)) yes no)
// cond: z.Uses == 1
// result: (NE (CMN x y) yes no)
@@ -34602,6 +35800,32 @@
b.Aux = nil
return true
}
+ // match: (NE (CMPW x z:(NEG y)) yes no)
+ // cond: z.Uses == 1
+ // result: (NE (CMNW x y) yes no)
+ for {
+ v := b.Control
+ if v.Op != OpARM64CMPW {
+ break
+ }
+ _ = v.Args[1]
+ x := v.Args[0]
+ z := v.Args[1]
+ if z.Op != OpARM64NEG {
+ break
+ }
+ y := z.Args[0]
+ if !(z.Uses == 1) {
+ break
+ }
+ b.Kind = BlockARM64NE
+ v0 := b.NewValue0(v.Pos, OpARM64CMNW, types.TypeFlags)
+ v0.AddArg(x)
+ v0.AddArg(y)
+ b.SetControl(v0)
+ b.Aux = nil
+ return true
+ }
// match: (NE (CMPconst [0] x) yes no)
// cond:
// result: (NZ x yes no)
diff --git a/test/codegen/comparisons.go b/test/codegen/comparisons.go
index 22d0636..8475b13 100644
--- a/test/codegen/comparisons.go
+++ b/test/codegen/comparisons.go
@@ -158,13 +158,39 @@
}
}
-func CmpToZero(a, b int32) int32 {
- if a&b < 0 { // arm:`TST`,-`AND`
+func CmpToZero(a, b, d int32) int32 {
+ // arm:`TST`,-`AND`
+ // arm64:`TSTW`,-`AND`
+ c0 := a&b < 0
+ // arm:`CMN`,-`ADD`
+ // arm64:`CMNW`,-`ADD`
+ c1 := a+b < 0
+ // arm:`TEQ`,-`XOR`
+ c2 := a^b < 0
+ // arm64:`TST`,-`AND`
+ c3 := int64(a)&int64(b) < 0
+ // arm64:`CMN`,-`ADD`
+ c4 := int64(a)+int64(b) < 0
+ // not optimized to CMNW/CMN due to further use of b+d
+ // arm64:`ADD`,-`CMNW`
+ c5 := b+d == 0
+ // not optimized to TSTW/TST due to further use of a&d
+ // arm64:`AND`,-`TSTW`
+ c6 := a&d >= 0
+ if c0 {
return 1
- } else if a+b < 0 { // arm:`CMN`,-`ADD`
+ } else if c1 {
return 2
- } else if a^b < 0 { // arm:`TEQ`,-`XOR`
+ } else if c2 {
return 3
+ } else if c3 {
+ return 4
+ } else if c4 {
+ return 5
+ } else if c5 {
+ return b + d
+ } else if c6 {
+ return a & d
} else {
return 0
}