mirror of https://github.com/golang/go.git
cmd/compile: more fix on boolean ops on ARM64
Following CL 405114, the extension rule is also wrong. It is safe to drop the extension if the value is from a boolean-generating instruction, but not a boolean-typed Value in general (e.g. a Phi or a in-register parameter). Fix it. Updates #52788. Change-Id: Icf3028fe8e90806f9f57fbe2b38d47da27a97e2a Reviewed-on: https://go-review.googlesource.com/c/go/+/405115 Reviewed-by: David Chase <drchase@google.com> Run-TryBot: Cherry Mui <cherryyz@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
f566fe3910
commit
90a11e921b
|
|
@ -1578,9 +1578,9 @@
|
||||||
(GreaterThanF (InvertFlags x)) => (LessThanF x)
|
(GreaterThanF (InvertFlags x)) => (LessThanF x)
|
||||||
(GreaterEqualF (InvertFlags x)) => (LessEqualF x)
|
(GreaterEqualF (InvertFlags x)) => (LessEqualF x)
|
||||||
|
|
||||||
// Boolean-generating instructions always
|
// Boolean-generating instructions (NOTE: NOT all boolean Values) always
|
||||||
// zero upper bit of the register; no need to zero-extend
|
// zero upper bit of the register; no need to zero-extend
|
||||||
(MOVBUreg x) && x.Type.IsBoolean() => (MOVDreg x)
|
(MOVBUreg x:((Equal|NotEqual|LessThan|LessThanU|LessThanF|LessEqual|LessEqualU|LessEqualF|GreaterThan|GreaterThanU|GreaterThanF|GreaterEqual|GreaterEqualU|GreaterEqualF) _)) => (MOVDreg x)
|
||||||
|
|
||||||
// absorb flag constants into conditional instructions
|
// absorb flag constants into conditional instructions
|
||||||
(CSEL [cc] x _ flag) && ccARM64Eval(cc, flag) > 0 => x
|
(CSEL [cc] x _ flag) && ccARM64Eval(cc, flag) > 0 => x
|
||||||
|
|
|
||||||
|
|
@ -7339,12 +7339,154 @@ func rewriteValueARM64_OpARM64MOVBUreg(v *Value) bool {
|
||||||
v.AuxInt = int64ToAuxInt(int64(uint8(c)))
|
v.AuxInt = int64ToAuxInt(int64(uint8(c)))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (MOVBUreg x)
|
// match: (MOVBUreg x:(Equal _))
|
||||||
// cond: x.Type.IsBoolean()
|
|
||||||
// result: (MOVDreg x)
|
// result: (MOVDreg x)
|
||||||
for {
|
for {
|
||||||
x := v_0
|
x := v_0
|
||||||
if !(x.Type.IsBoolean()) {
|
if x.Op != OpARM64Equal {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64MOVDreg)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (MOVBUreg x:(NotEqual _))
|
||||||
|
// result: (MOVDreg x)
|
||||||
|
for {
|
||||||
|
x := v_0
|
||||||
|
if x.Op != OpARM64NotEqual {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64MOVDreg)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (MOVBUreg x:(LessThan _))
|
||||||
|
// result: (MOVDreg x)
|
||||||
|
for {
|
||||||
|
x := v_0
|
||||||
|
if x.Op != OpARM64LessThan {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64MOVDreg)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (MOVBUreg x:(LessThanU _))
|
||||||
|
// result: (MOVDreg x)
|
||||||
|
for {
|
||||||
|
x := v_0
|
||||||
|
if x.Op != OpARM64LessThanU {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64MOVDreg)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (MOVBUreg x:(LessThanF _))
|
||||||
|
// result: (MOVDreg x)
|
||||||
|
for {
|
||||||
|
x := v_0
|
||||||
|
if x.Op != OpARM64LessThanF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64MOVDreg)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (MOVBUreg x:(LessEqual _))
|
||||||
|
// result: (MOVDreg x)
|
||||||
|
for {
|
||||||
|
x := v_0
|
||||||
|
if x.Op != OpARM64LessEqual {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64MOVDreg)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (MOVBUreg x:(LessEqualU _))
|
||||||
|
// result: (MOVDreg x)
|
||||||
|
for {
|
||||||
|
x := v_0
|
||||||
|
if x.Op != OpARM64LessEqualU {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64MOVDreg)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (MOVBUreg x:(LessEqualF _))
|
||||||
|
// result: (MOVDreg x)
|
||||||
|
for {
|
||||||
|
x := v_0
|
||||||
|
if x.Op != OpARM64LessEqualF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64MOVDreg)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (MOVBUreg x:(GreaterThan _))
|
||||||
|
// result: (MOVDreg x)
|
||||||
|
for {
|
||||||
|
x := v_0
|
||||||
|
if x.Op != OpARM64GreaterThan {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64MOVDreg)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (MOVBUreg x:(GreaterThanU _))
|
||||||
|
// result: (MOVDreg x)
|
||||||
|
for {
|
||||||
|
x := v_0
|
||||||
|
if x.Op != OpARM64GreaterThanU {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64MOVDreg)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (MOVBUreg x:(GreaterThanF _))
|
||||||
|
// result: (MOVDreg x)
|
||||||
|
for {
|
||||||
|
x := v_0
|
||||||
|
if x.Op != OpARM64GreaterThanF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64MOVDreg)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (MOVBUreg x:(GreaterEqual _))
|
||||||
|
// result: (MOVDreg x)
|
||||||
|
for {
|
||||||
|
x := v_0
|
||||||
|
if x.Op != OpARM64GreaterEqual {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64MOVDreg)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (MOVBUreg x:(GreaterEqualU _))
|
||||||
|
// result: (MOVDreg x)
|
||||||
|
for {
|
||||||
|
x := v_0
|
||||||
|
if x.Op != OpARM64GreaterEqualU {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64MOVDreg)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (MOVBUreg x:(GreaterEqualF _))
|
||||||
|
// result: (MOVDreg x)
|
||||||
|
for {
|
||||||
|
x := v_0
|
||||||
|
if x.Op != OpARM64GreaterEqualF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpARM64MOVDreg)
|
v.reset(OpARM64MOVDreg)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
// run
|
||||||
|
|
||||||
|
// Copyright 2022 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.
|
||||||
|
|
||||||
|
// Issue 52788: miscompilation for boolean ops on ARM64.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func f(next func() bool) {
|
||||||
|
for b := next(); b; b = next() {
|
||||||
|
fmt.Printf("%v\n", b)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
next := reflect.MakeFunc(reflect.TypeOf((func() bool)(nil)), func(_ []reflect.Value) []reflect.Value {
|
||||||
|
return []reflect.Value{reflect.ValueOf(true)}
|
||||||
|
})
|
||||||
|
reflect.ValueOf(f).Call([]reflect.Value{next})
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
true
|
||||||
Loading…
Reference in New Issue