mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
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)
|
||||
(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
|
||||
(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
|
||||
(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)))
|
||||
return true
|
||||
}
|
||||
// match: (MOVBUreg x)
|
||||
// cond: x.Type.IsBoolean()
|
||||
// match: (MOVBUreg x:(Equal _))
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
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
|
||||
}
|
||||
v.reset(OpARM64MOVDreg)
|
||||
|
29
test/fixedbugs/issue52788a.go
Normal file
29
test/fixedbugs/issue52788a.go
Normal file
@ -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})
|
||||
}
|
1
test/fixedbugs/issue52788a.out
Normal file
1
test/fixedbugs/issue52788a.out
Normal file
@ -0,0 +1 @@
|
||||
true
|
Loading…
x
Reference in New Issue
Block a user