]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: ignore all unreachable values during simple phi insertion
authorJosh Bleecher Snyder <josharian@gmail.com>
Fri, 24 Mar 2017 17:36:13 +0000 (10:36 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Fri, 24 Mar 2017 18:00:15 +0000 (18:00 +0000)
Simple phi insertion already had a heuristic to check
for dead blocks, namely having no predecessors.
When we stopped generating code for dead blocks,
we eliminated some values contained in more subtle
dead blocks, which confused phi insertion.
Compensate by beefing up the reachability check.

Fixes #19678

Change-Id: I0081e4a46f7ce2f69b131a34a0553874a0cb373e
Reviewed-on: https://go-review.googlesource.com/38602
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/gc/phi.go
src/cmd/compile/internal/ssa/deadcode.go
test/fixedbugs/issue19678.go [new file with mode: 0644]

index 2f1d70a3ee44ef3cf1bafcd7f89648055745ee5e..0ba2de80e2ce4c6b05e57f448fbeee44223c944e 100644 (file)
@@ -437,6 +437,8 @@ type simplePhiState struct {
 }
 
 func (s *simplePhiState) insertPhis() {
+       reachable := ssa.ReachableBlocks(s.f)
+
        // Find FwdRef ops.
        for _, b := range s.f.Blocks {
                for _, v := range b.Values {
@@ -459,12 +461,12 @@ loop:
                s.fwdrefs = s.fwdrefs[:len(s.fwdrefs)-1]
                b := v.Block
                var_ := v.Aux.(*Node)
-               if len(b.Preds) == 0 {
-                       if b == s.f.Entry {
-                               // No variable should be live at entry.
-                               s.s.Fatalf("Value live at entry. It shouldn't be. func %s, node %v, value %v", s.f.Name, var_, v)
-                       }
-                       // This block is dead; it has no predecessors and it is not the entry block.
+               if b == s.f.Entry {
+                       // No variable should be live at entry.
+                       s.s.Fatalf("Value live at entry. It shouldn't be. func %s, node %v, value %v", s.f.Name, var_, v)
+               }
+               if !reachable[b.ID] {
+                       // This block is dead.
                        // It doesn't matter what we use here as long as it is well-formed.
                        v.Op = ssa.OpUnknown
                        v.Aux = nil
index ce786a964b48e2e825a21c95b388e729f8d2c5f4..b24ecaa4c4bb721cab910e88cb48de02e2367e73 100644 (file)
@@ -6,13 +6,13 @@ package ssa
 
 // findlive returns the reachable blocks and live values in f.
 func findlive(f *Func) (reachable []bool, live []bool) {
-       reachable = reachableBlocks(f)
+       reachable = ReachableBlocks(f)
        live = liveValues(f, reachable)
        return
 }
 
-// reachableBlocks returns the reachable blocks in f.
-func reachableBlocks(f *Func) []bool {
+// ReachableBlocks returns the reachable blocks in f.
+func ReachableBlocks(f *Func) []bool {
        reachable := make([]bool, f.NumBlocks())
        reachable[f.Entry.ID] = true
        p := []*Block{f.Entry} // stack-like worklist
@@ -106,7 +106,7 @@ func deadcode(f *Func) {
        }
 
        // Find reachable blocks.
-       reachable := reachableBlocks(f)
+       reachable := ReachableBlocks(f)
 
        // Get rid of edges from dead to live code.
        for _, b := range f.Blocks {
diff --git a/test/fixedbugs/issue19678.go b/test/fixedbugs/issue19678.go
new file mode 100644 (file)
index 0000000..81ef331
--- /dev/null
@@ -0,0 +1,21 @@
+// compile
+
+// Copyright 2017 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.
+
+// Used to crash when compiling functions containing
+// forward refs in dead code.
+
+package p
+
+var f func(int)
+
+func g() {
+l1:
+       i := 0
+       goto l1
+l2:
+       f(i)
+       goto l2
+}