]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix bug of conditional instructions on arm64
authoreric fang <eric.fang@arm.com>
Tue, 6 Apr 2021 07:23:38 +0000 (07:23 +0000)
committereric fang <eric.fang@arm.com>
Wed, 7 Apr 2021 02:05:55 +0000 (02:05 +0000)
CL 302231 added some optimization rules with instructions CSETM, CSINC,
CSINV, and CSNEG, but did not deal with the situation where flag is
constant, resulting in some cases that could be more optimized cannot
be optimized, and the FlagConstant value is passed to codegen pass. This
CL adds these missing rules.

Fixes #45359

Change-Id: I700608cfb9a6a768a18d1fd5d374d7e92aa6f838
Reviewed-on: https://go-review.googlesource.com/c/go/+/307650
Reviewed-by: eric fang <eric.fang@arm.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Alberto Donizetti <alb.donizetti@gmail.com>
Run-TryBot: eric fang <eric.fang@arm.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: eric fang <eric.fang@arm.com>
Trust: Alberto Donizetti <alb.donizetti@gmail.com>

src/cmd/compile/internal/ssa/gen/ARM64.rules
src/cmd/compile/internal/ssa/rewriteARM64.go
test/fixedbugs/issue45359.go [new file with mode: 0644]

index cb997776db9d083ddbfe2d86923f92e76173f60d..3d2759493e5a230bf5c80945a670f297ab37faaf 100644 (file)
 (CSEL [cc] _ y flag) && ccARM64Eval(cc, flag) < 0 => y
 (CSEL0 [cc] x flag) && ccARM64Eval(cc, flag) > 0 => x
 (CSEL0 [cc] _ flag) && ccARM64Eval(cc, flag) < 0 => (MOVDconst [0])
+(CSNEG [cc] x _ flag) && ccARM64Eval(cc, flag) > 0 => x
+(CSNEG [cc] _ y flag) && ccARM64Eval(cc, flag) < 0 => (NEG y)
+(CSINV [cc] x _ flag) && ccARM64Eval(cc, flag) > 0 => x
+(CSINV [cc] _ y flag) && ccARM64Eval(cc, flag) < 0 => (Not y)
+(CSINC [cc] x _ flag) && ccARM64Eval(cc, flag) > 0 => x
+(CSINC [cc] _ y flag) && ccARM64Eval(cc, flag) < 0 => (ADDconst [1] y)
+(CSETM [cc] flag) && ccARM64Eval(cc, flag) > 0 => (MOVDconst [-1])
+(CSETM [cc] flag) && ccARM64Eval(cc, flag) < 0 => (MOVDconst [0])
 
 // absorb flags back into boolean CSEL
 (CSEL [cc] x y (CMPWconst [0] boolval)) && cc == OpARM64NotEqual && flagArg(boolval) != nil =>
index cdc246205ccffb927a20d7e4b84c5a5c91a9bf9a..0ba3951df57418ffce9c9b9db3239b8fd4c7a4df 100644 (file)
@@ -3619,6 +3619,32 @@ func rewriteValueARM64_OpARM64CSETM(v *Value) bool {
                v.AddArg(cmp)
                return true
        }
+       // match: (CSETM [cc] flag)
+       // cond: ccARM64Eval(cc, flag) > 0
+       // result: (MOVDconst [-1])
+       for {
+               cc := auxIntToOp(v.AuxInt)
+               flag := v_0
+               if !(ccARM64Eval(cc, flag) > 0) {
+                       break
+               }
+               v.reset(OpARM64MOVDconst)
+               v.AuxInt = int64ToAuxInt(-1)
+               return true
+       }
+       // match: (CSETM [cc] flag)
+       // cond: ccARM64Eval(cc, flag) < 0
+       // result: (MOVDconst [0])
+       for {
+               cc := auxIntToOp(v.AuxInt)
+               flag := v_0
+               if !(ccARM64Eval(cc, flag) < 0) {
+                       break
+               }
+               v.reset(OpARM64MOVDconst)
+               v.AuxInt = int64ToAuxInt(0)
+               return true
+       }
        return false
 }
 func rewriteValueARM64_OpARM64CSINC(v *Value) bool {
@@ -3640,6 +3666,34 @@ func rewriteValueARM64_OpARM64CSINC(v *Value) bool {
                v.AddArg3(x, y, cmp)
                return true
        }
+       // match: (CSINC [cc] x _ flag)
+       // cond: ccARM64Eval(cc, flag) > 0
+       // result: x
+       for {
+               cc := auxIntToOp(v.AuxInt)
+               x := v_0
+               flag := v_2
+               if !(ccARM64Eval(cc, flag) > 0) {
+                       break
+               }
+               v.copyOf(x)
+               return true
+       }
+       // match: (CSINC [cc] _ y flag)
+       // cond: ccARM64Eval(cc, flag) < 0
+       // result: (ADDconst [1] y)
+       for {
+               cc := auxIntToOp(v.AuxInt)
+               y := v_1
+               flag := v_2
+               if !(ccARM64Eval(cc, flag) < 0) {
+                       break
+               }
+               v.reset(OpARM64ADDconst)
+               v.AuxInt = int64ToAuxInt(1)
+               v.AddArg(y)
+               return true
+       }
        return false
 }
 func rewriteValueARM64_OpARM64CSINV(v *Value) bool {
@@ -3661,6 +3715,33 @@ func rewriteValueARM64_OpARM64CSINV(v *Value) bool {
                v.AddArg3(x, y, cmp)
                return true
        }
+       // match: (CSINV [cc] x _ flag)
+       // cond: ccARM64Eval(cc, flag) > 0
+       // result: x
+       for {
+               cc := auxIntToOp(v.AuxInt)
+               x := v_0
+               flag := v_2
+               if !(ccARM64Eval(cc, flag) > 0) {
+                       break
+               }
+               v.copyOf(x)
+               return true
+       }
+       // match: (CSINV [cc] _ y flag)
+       // cond: ccARM64Eval(cc, flag) < 0
+       // result: (Not y)
+       for {
+               cc := auxIntToOp(v.AuxInt)
+               y := v_1
+               flag := v_2
+               if !(ccARM64Eval(cc, flag) < 0) {
+                       break
+               }
+               v.reset(OpNot)
+               v.AddArg(y)
+               return true
+       }
        return false
 }
 func rewriteValueARM64_OpARM64CSNEG(v *Value) bool {
@@ -3682,6 +3763,33 @@ func rewriteValueARM64_OpARM64CSNEG(v *Value) bool {
                v.AddArg3(x, y, cmp)
                return true
        }
+       // match: (CSNEG [cc] x _ flag)
+       // cond: ccARM64Eval(cc, flag) > 0
+       // result: x
+       for {
+               cc := auxIntToOp(v.AuxInt)
+               x := v_0
+               flag := v_2
+               if !(ccARM64Eval(cc, flag) > 0) {
+                       break
+               }
+               v.copyOf(x)
+               return true
+       }
+       // match: (CSNEG [cc] _ y flag)
+       // cond: ccARM64Eval(cc, flag) < 0
+       // result: (NEG y)
+       for {
+               cc := auxIntToOp(v.AuxInt)
+               y := v_1
+               flag := v_2
+               if !(ccARM64Eval(cc, flag) < 0) {
+                       break
+               }
+               v.reset(OpARM64NEG)
+               v.AddArg(y)
+               return true
+       }
        return false
 }
 func rewriteValueARM64_OpARM64DIV(v *Value) bool {
diff --git a/test/fixedbugs/issue45359.go b/test/fixedbugs/issue45359.go
new file mode 100644 (file)
index 0000000..5448556
--- /dev/null
@@ -0,0 +1,20 @@
+// compile
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func f() {
+       var i, j int
+       var b bool
+       i = -(i &^ i)
+       for 1>>uint(i) == 0 {
+               _ = func() {
+                       i, b = 0, true
+               }
+               _ = b
+               i %= j
+       }
+}