From cfd8dfaa10ab387c6b9c9e620aadab5852a4c76e Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 4 Aug 2015 21:59:15 -0700 Subject: [PATCH] [dev.ssa] cmd/compile/internal/ssa: more checks on ssa structure Make sure all referenced Blocks and Values are really there. Fix deadcode to generate SSA graphs that pass this new test. Change-Id: Ib002ce20e33490eb8c919bd189d209f769d61517 Reviewed-on: https://go-review.googlesource.com/13147 Reviewed-by: Josh Bleecher Snyder --- src/cmd/compile/internal/ssa/check.go | 29 +++++++++++++++++++++--- src/cmd/compile/internal/ssa/deadcode.go | 16 +++++++++++-- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/cmd/compile/internal/ssa/check.go b/src/cmd/compile/internal/ssa/check.go index 1f6ffc0129..668828fcd1 100644 --- a/src/cmd/compile/internal/ssa/check.go +++ b/src/cmd/compile/internal/ssa/check.go @@ -137,12 +137,35 @@ func checkFunc(f *Func) { } } + // Check to make sure all Blocks referenced are in the function. + if !blockMark[f.Entry.ID] { + f.Fatalf("entry block %v is missing", f.Entry) + } for _, b := range f.Blocks { - if b.Control != nil { - if !valueMark[b.Control.ID] { - f.Fatalf("control value for %s is missing: %v", b, b.Control) + for _, c := range b.Preds { + if !blockMark[c.ID] { + f.Fatalf("predecessor block %v for %v is missing", c, b) } } + for _, c := range b.Succs { + if !blockMark[c.ID] { + f.Fatalf("successor block %v for %v is missing", c, b) + } + } + } + + // Check to make sure all Values referenced are in the function. + for _, b := range f.Blocks { + for _, v := range b.Values { + for i, a := range v.Args { + if !valueMark[a.ID] { + f.Fatalf("%v, arg %d of %v, is missing", a, i, v) + } + } + } + if b.Control != nil && !valueMark[b.Control.ID] { + f.Fatalf("control value for %s is missing: %v", b, b.Control) + } } for _, id := range f.bid.free { if blockMark[id] { diff --git a/src/cmd/compile/internal/ssa/deadcode.go b/src/cmd/compile/internal/ssa/deadcode.go index 04e5b71ceb..426e6865c0 100644 --- a/src/cmd/compile/internal/ssa/deadcode.go +++ b/src/cmd/compile/internal/ssa/deadcode.go @@ -6,7 +6,6 @@ package ssa // deadcode removes dead code from f. func deadcode(f *Func) { - // Find all reachable basic blocks. reachable := make([]bool, f.NumBlocks()) reachable[f.Entry.ID] = true @@ -85,6 +84,11 @@ func deadcode(f *Func) { if len(b.Values) > 0 { b.Fatalf("live values in unreachable block %v: %v", b, b.Values) } + s := b.Succs + b.Succs = nil + for _, c := range s { + f.removePredecessor(b, c) + } f.bid.put(b.ID) } } @@ -108,14 +112,22 @@ func (f *Func) removePredecessor(b, c *Block) { b, c := work[0][0], work[0][1] work = work[1:] - // find index of b in c's predecessor list + // Find index of b in c's predecessor list + // TODO: This could conceivably cause O(n^2) work. Imagine a very + // wide phi in (for example) the return block. If we determine that + // lots of panics won't happen, we remove each edge at a cost of O(n) each. var i int + found := false for j, p := range c.Preds { if p == b { i = j + found = true break } } + if !found { + f.Fatalf("can't find predecessor %v of %v\n", b, c) + } n := len(c.Preds) - 1 c.Preds[i] = c.Preds[n]