]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile: fix incorrect truncating when converting CMP to TST on arm64
authorerifan01 <eric.fang@arm.com>
Tue, 7 Mar 2023 00:44:08 +0000 (08:44 +0800)
committerEric Fang <eric.fang@arm.com>
Wed, 22 Mar 2023 08:32:53 +0000 (08:32 +0000)
CL 420434 optimized CMP into TST in some situations, but it has a bug,
these four rules are not correct:
(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))

But due to the existence of this rule
(LessThan (CMPWconst [0] x:(ANDconst [c] y))) && x.Uses == 1 =>
(LessThan (TSTWconst [int32(c)] y)), the above rules have never been
fired. This CL corrects them as:
(LessThan (CMPconst [0] x:(ANDconst [c] y))) && x.Uses == 1 => (LessThan (TSTconst [c] y))
(LessEqual (CMPconst [0] x:(ANDconst [c] y))) && x.Uses == 1 => (LessEqual (TSTconst [c] y))
(GreaterThan (CMPconst [0] x:(ANDconst [c] y))) && x.Uses == 1 => (GreaterThan (TSTconst [c] y))
(GreaterEqual (CMPconst [0] x:(ANDconst [c] y))) && x.Uses == 1 => (GreaterEqual (TSTconst [c] y))

Change-Id: I7d60bcc9a266ee58388baeaab9f493b57cf1ad55
Reviewed-on: https://go-review.googlesource.com/c/go/+/473617
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
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/comparisons.go

index a896e7c8bd7491511d2107f501fd9fe24612f515..fdfd7858fb0788fd91d8dcb0c7c49725b2d9cb0a 100644 (file)
 
 (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))
+(LessThan (CMPconst [0] x:(ANDconst [c] y))) && x.Uses == 1 => (LessThan (TSTconst [c] y))
+(LessEqual (CMPconst [0] x:(ANDconst [c] y))) && x.Uses == 1 => (LessEqual (TSTconst [c] y))
+(GreaterThan (CMPconst [0] x:(ANDconst [c] y))) && x.Uses == 1 => (GreaterThan (TSTconst [c] y))
+(GreaterEqual (CMPconst [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 f84d7b3c198eb8abb9cb44bb01c345313ce0d9c6..41d9513160e2e41671ff34dfceacd7f893f04494 100644 (file)
@@ -5698,11 +5698,11 @@ func rewriteValueARM64_OpARM64GreaterEqual(v *Value) bool {
                v.AddArg(v0)
                return true
        }
-       // match: (GreaterEqual (CMPWconst [0] x:(ANDconst [c] y)))
+       // match: (GreaterEqual (CMPconst [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 {
+               if v_0.Op != OpARM64CMPconst || auxIntToInt64(v_0.AuxInt) != 0 {
                        break
                }
                x := v_0.Args[0]
@@ -5856,11 +5856,11 @@ func rewriteValueARM64_OpARM64GreaterThan(v *Value) bool {
                v.AddArg(v0)
                return true
        }
-       // match: (GreaterThan (CMPWconst [0] x:(ANDconst [c] y)))
+       // match: (GreaterThan (CMPconst [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 {
+               if v_0.Op != OpARM64CMPconst || auxIntToInt64(v_0.AuxInt) != 0 {
                        break
                }
                x := v_0.Args[0]
@@ -6064,11 +6064,11 @@ func rewriteValueARM64_OpARM64LessEqual(v *Value) bool {
                v.AddArg(v0)
                return true
        }
-       // match: (LessEqual (CMPWconst [0] x:(ANDconst [c] y)))
+       // match: (LessEqual (CMPconst [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 {
+               if v_0.Op != OpARM64CMPconst || auxIntToInt64(v_0.AuxInt) != 0 {
                        break
                }
                x := v_0.Args[0]
@@ -6222,11 +6222,11 @@ func rewriteValueARM64_OpARM64LessThan(v *Value) bool {
                v.AddArg(v0)
                return true
        }
-       // match: (LessThan (CMPWconst [0] x:(ANDconst [c] y)))
+       // match: (LessThan (CMPconst [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 {
+               if v_0.Op != OpARM64CMPconst || auxIntToInt64(v_0.AuxInt) != 0 {
                        break
                }
                x := v_0.Args[0]
index c613e13ced74d7e5c99d6cd974518960d9654f02..ee732e06d9acaf1f03b0de3383d5e6f0a6a585d3 100644 (file)
@@ -234,6 +234,8 @@ func CmpToZero(a, b, d int32, e, f int64, deOptC0, deOptC1 bool) int32 {
        c7 := e&(f<<3) < 0
        // arm64:`CMN\sR[0-9]+<<3,\sR[0-9]+`
        c8 := e+(f<<3) < 0
+       // arm64:`TST\sR[0-9],\sR[0-9]+`
+       c9 := e&17 < 0
        if c0 {
                return 1
        } else if c1 {
@@ -252,6 +254,8 @@ func CmpToZero(a, b, d int32, e, f int64, deOptC0, deOptC1 bool) int32 {
                return 9
        } else if c8 {
                return 10
+       } else if c9 {
+               return 11
        } else if deOptC0 {
                return b + d
        } else if deOptC1 {