Commit caef4496 authored by Alexandru Moșoi's avatar Alexandru Moșoi Committed by Alexandru Moșoi

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: 's avatarKeith Randall <khr@golang.org>
parent 3c1a4c19
......@@ -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() {
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment