]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.ssa] cmd/compile/internal/ssa: more checks on ssa structure
authorKeith Randall <khr@golang.org>
Wed, 5 Aug 2015 04:59:15 +0000 (21:59 -0700)
committerKeith Randall <khr@golang.org>
Thu, 6 Aug 2015 17:33:19 +0000 (17:33 +0000)
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>
src/cmd/compile/internal/ssa/check.go
src/cmd/compile/internal/ssa/deadcode.go

index 1f6ffc0129ae2dbd6ee9d65939ef68c0eb4767f6..668828fcd1545c34f5a9c252e206db372d0f620b 100644 (file)
@@ -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)
index 04e5b71ceb66bf920ea411ef6f24aea5d841e4f1..426e6865c025de8bfecf1706ff7b7bd2fe9e1d91 100644 (file)
@@ -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]