mirror of
https://github.com/golang/go
synced 2024-10-05 20:21:21 -06:00
[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>
This commit is contained in:
parent
ddeee0eed3
commit
cfd8dfaa10
@ -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 {
|
for _, b := range f.Blocks {
|
||||||
if b.Control != nil {
|
for _, c := range b.Preds {
|
||||||
if !valueMark[b.Control.ID] {
|
if !blockMark[c.ID] {
|
||||||
f.Fatalf("control value for %s is missing: %v", b, b.Control)
|
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 {
|
for _, id := range f.bid.free {
|
||||||
if blockMark[id] {
|
if blockMark[id] {
|
||||||
|
@ -6,7 +6,6 @@ package ssa
|
|||||||
|
|
||||||
// deadcode removes dead code from f.
|
// deadcode removes dead code from f.
|
||||||
func deadcode(f *Func) {
|
func deadcode(f *Func) {
|
||||||
|
|
||||||
// Find all reachable basic blocks.
|
// Find all reachable basic blocks.
|
||||||
reachable := make([]bool, f.NumBlocks())
|
reachable := make([]bool, f.NumBlocks())
|
||||||
reachable[f.Entry.ID] = true
|
reachable[f.Entry.ID] = true
|
||||||
@ -85,6 +84,11 @@ func deadcode(f *Func) {
|
|||||||
if len(b.Values) > 0 {
|
if len(b.Values) > 0 {
|
||||||
b.Fatalf("live values in unreachable block %v: %v", b, b.Values)
|
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)
|
f.bid.put(b.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,14 +112,22 @@ func (f *Func) removePredecessor(b, c *Block) {
|
|||||||
b, c := work[0][0], work[0][1]
|
b, c := work[0][0], work[0][1]
|
||||||
work = work[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
|
var i int
|
||||||
|
found := false
|
||||||
for j, p := range c.Preds {
|
for j, p := range c.Preds {
|
||||||
if p == b {
|
if p == b {
|
||||||
i = j
|
i = j
|
||||||
|
found = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !found {
|
||||||
|
f.Fatalf("can't find predecessor %v of %v\n", b, c)
|
||||||
|
}
|
||||||
|
|
||||||
n := len(c.Preds) - 1
|
n := len(c.Preds) - 1
|
||||||
c.Preds[i] = c.Preds[n]
|
c.Preds[i] = c.Preds[n]
|
||||||
|
Loading…
Reference in New Issue
Block a user