(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
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)
--- /dev/null
+// 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})
+}