aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2015-08-04 21:59:15 -0700
committerKeith Randall <khr@golang.org>2015-08-06 17:33:19 +0000
commitcfd8dfaa10ab387c6b9c9e620aadab5852a4c76e (patch)
tree23a724cf024e03f366a29971a833a44a4f8173bd /src/cmd/compile/internal
parentddeee0eed33a675faa4eee289aabfdb25055cbef (diff)
downloadgo-cfd8dfaa10ab387c6b9c9e620aadab5852a4c76e.tar.xz
[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 <josharian@gmail.com>
Diffstat (limited to 'src/cmd/compile/internal')
-rw-r--r--src/cmd/compile/internal/ssa/check.go29
-rw-r--r--src/cmd/compile/internal/ssa/deadcode.go16
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,13 +137,36 @@ 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] {
f.Fatalf("used block b%d in free list", 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]