cmd/compile: fix bug of conditional instructions on arm64

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>
This commit is contained in:
eric fang 2021-04-06 07:23:38 +00:00
parent 972e883925
commit 8d77e45064
3 changed files with 136 additions and 0 deletions

View File

@ -1570,6 +1570,14 @@
(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 =>

View 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 {

View File

@ -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
}
}