}
func (s *simplePhiState) insertPhis() {
+ reachable := ssa.ReachableBlocks(s.f)
+
// Find FwdRef ops.
for _, b := range s.f.Blocks {
for _, v := range b.Values {
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
// 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
}
// Find reachable blocks.
- reachable := reachableBlocks(f)
+ reachable := ReachableBlocks(f)
// Get rid of edges from dead to live code.
for _, b := range f.Blocks {
--- /dev/null
+// 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
+}