Input file:
package pkg
func Send(arg1 int, arg2 bool, arg3 bool) {
var distinctSpans bool
if arg2 {
distinctSpans = arg1 == 0
}
println(arg3 && distinctSpans)
}
ssadump on 219e654b~1 (last working commit):
# Name: pkg.Send
# Package: pkg
# Location: /tmp/foo.go:3:6
func Send(arg1 int, arg2 bool, arg3 bool):
0: entry P:0 S:2
; var distinctSpans bool @ 4:6 is false:bool
; var arg2 bool @ 5:5 is arg2
if arg2 goto 1 else 2
1: if.then P:1 S:1
; var arg1 int @ 6:19 is arg1
t0 = arg1 == 0:int bool
; *ast.BinaryExpr @ 6:19 is t0
; var distinctSpans bool @ 6:3 is t0
jump 2
2: if.done P:2 S:2
t1 = phi [0: false:bool, 1: t0] #distinctSpans bool
; var arg3 bool @ 8:10 is arg3
if arg3 goto 3 else 4
3: binop.rhs P:1 S:1
; var distinctSpans bool @ 8:18 is t1
jump 4
4: binop.done P:2 S:0
t2 = phi [2: false:bool, 3: t1] #&& bool
; *ast.BinaryExpr @ 8:10 is t2
t3 = println(t2) ()
; *ast.CallExpr @ 8:2 is t3
return
ssadump on 219e654b (first broken commit):
# Name: pkg.Send
# Package: pkg
# Location: /tmp/foo.go:3:6
func Send(arg1 int, arg2 bool, arg3 bool):
0: entry P:0 S:2
; var distinctSpans bool @ 4:6 is false:bool
; var arg2 bool @ 5:5 is arg2
if arg2 goto 1 else 2
1: if.then P:1 S:1
; var arg1 int @ 6:19 is arg1
t0 = arg1 == 0:int bool
; *ast.BinaryExpr @ 6:19 is t0
; var distinctSpans bool @ 6:3 is t0
jump 2
2: if.done P:2 S:2
; var arg3 bool @ 8:10 is arg3
if arg3 goto 3 else 4
3: binop.rhs P:1 S:1
; var distinctSpans bool @ 8:18 is t1000
jump 4
4: binop.done P:2 S:0
t1 = phi [2: false:bool, 3: t1000] #&& bool
; *ast.BinaryExpr @ 8:10 is t1
t2 = println(t1) ()
; *ast.CallExpr @ 8:2 is t2
return
Problem:
t0 - the result of the assignment to distinctSpans - isn't being used, block 2 is missing a phi node, and the phi node t1 refers to an ominous t1000.
/cc @alandonovan
This is still an issue, and kind of makes go/ssa unusable for a lot of its users. Is there a way to get this on the radar of the people who actually understand the code?
The problem seems to be that the reachability part of 蠁-elimination considers only "new phis" and ignores 蠁-nodes already present due to && and || operators. I'll prepare a fix. Sorry for the delay.
Minimal testcase:
func f(a bool) bool {
c := false
if true {
c = true
}
return true && c
}
CL https://golang.org/cl/45832 mentions this issue.
Most helpful comment
CL https://golang.org/cl/45832 mentions this issue.