mirror of
https://github.com/golang/go
synced 2024-10-02 22:25:08 +00:00
cmd/compile: convert some Phis into And8.
See discussion at [1]. True value must have a fixed non-zero representation meaning that a && b can be implemented as a & b. [1] https://groups.google.com/forum/#!topic/golang-dev/xV0vPuFP9Vg This change helps with m := a && b, but it's more common to see if a && b { do something } which is not handled. Change-Id: Ib6f9ff898a0a8c05d12466e2464e4fe781035394 Reviewed-on: https://go-review.googlesource.com/22313 Run-TryBot: Alexandru Moșoi <alexandru@mosoi.ro> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
3c1a4c1902
commit
caef4496fc
|
@ -26,6 +26,7 @@ package ssa
|
|||
func phiopt(f *Func) {
|
||||
for _, b := range f.Blocks {
|
||||
if len(b.Preds) != 2 || len(b.Values) == 0 {
|
||||
// TODO: handle more than 2 predecessors, e.g. a || b || c.
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -91,6 +92,22 @@ func phiopt(f *Func) {
|
|||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Replaces
|
||||
// if a { x = value } else { x = false } with x = a && value.
|
||||
// Requires that value dominates x, meaning that regardless of a,
|
||||
// value is always computed. This guarantees that the side effects
|
||||
// of value are not seen if a is false.
|
||||
if v.Args[1-reverse].Op == OpConstBool && v.Args[1-reverse].AuxInt == 0 {
|
||||
if tmp := v.Args[reverse]; f.sdom.isAncestorEq(tmp.Block, b) {
|
||||
v.reset(OpAnd8)
|
||||
v.SetArgs2(b0.Control, tmp)
|
||||
if f.pass.debug > 0 {
|
||||
f.Config.Warnl(b.Line, "converted OpPhi to %v", v.Op)
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,23 +53,56 @@ func f4(a, b bool) bool {
|
|||
}
|
||||
|
||||
//go:noinline
|
||||
func f5(a int, b bool) bool {
|
||||
x := b
|
||||
func f5or(a int, b bool) bool {
|
||||
var x bool
|
||||
if a == 0 {
|
||||
x = true
|
||||
} else {
|
||||
x = b
|
||||
}
|
||||
return x // ERROR "converted OpPhi to Or8$"
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func f6(a int, b bool) bool {
|
||||
func f5and(a int, b bool) bool {
|
||||
var x bool
|
||||
if a == 0 {
|
||||
x = b
|
||||
} else {
|
||||
x = false
|
||||
}
|
||||
return x // ERROR "converted OpPhi to And8$"
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func f6or(a int, b bool) bool {
|
||||
x := b
|
||||
if a == 0 {
|
||||
// f6 has side effects so the OpPhi should not be converted.
|
||||
x = f6(a, b)
|
||||
// f6or has side effects so the OpPhi should not be converted.
|
||||
x = f6or(a, b)
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func f6and(a int, b bool) bool {
|
||||
x := b
|
||||
if a == 0 {
|
||||
// f6and has side effects so the OpPhi should not be converted.
|
||||
x = f6and(a, b)
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func f7or(a bool, b bool) bool {
|
||||
return a || b // ERROR "converted OpPhi to Or8$"
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func f7and(a bool, b bool) bool {
|
||||
return a && b // ERROR "converted OpPhi to And8$"
|
||||
}
|
||||
|
||||
func main() {
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue