Go: x/tools/go/ssa: regression in "eliminate dead 蠁-nodes in cycles"

Created on 20 Mar 2017  路  4Comments  路  Source: golang/go

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

FrozenDueToAge

Most helpful comment

CL https://golang.org/cl/45832 mentions this issue.

All 4 comments

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.

Was this page helpful?
0 / 5 - 0 ratings