aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/ssa/deadcode.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/ssa/deadcode.go')
-rw-r--r--src/cmd/compile/internal/ssa/deadcode.go64
1 files changed, 27 insertions, 37 deletions
diff --git a/src/cmd/compile/internal/ssa/deadcode.go b/src/cmd/compile/internal/ssa/deadcode.go
index ae990026f5..5ccf39027f 100644
--- a/src/cmd/compile/internal/ssa/deadcode.go
+++ b/src/cmd/compile/internal/ssa/deadcode.go
@@ -25,7 +25,8 @@ func reachableBlocks(f *Func) []bool {
if b.Kind == BlockFirst {
s = s[:1]
}
- for _, c := range s {
+ for _, e := range s {
+ c := e.b
if !reachable[c.ID] {
reachable[c.ID] = true
p = append(p, c) // push
@@ -69,7 +70,7 @@ func liveValues(f *Func, reachable []bool) []bool {
v := q[len(q)-1]
q = q[:len(q)-1]
for i, x := range v.Args {
- if v.Op == OpPhi && !reachable[v.Block.Preds[i].ID] {
+ if v.Op == OpPhi && !reachable[v.Block.Preds[i].b.ID] {
continue
}
if !live[x.ID] {
@@ -100,9 +101,12 @@ func deadcode(f *Func) {
if reachable[b.ID] {
continue
}
- for _, c := range b.Succs {
- if reachable[c.ID] {
- c.removePred(b)
+ for i := 0; i < len(b.Succs); {
+ e := b.Succs[i]
+ if reachable[e.b.ID] {
+ b.removeEdge(i)
+ } else {
+ i++
}
}
}
@@ -115,16 +119,9 @@ func deadcode(f *Func) {
if b.Kind != BlockFirst {
continue
}
- c := b.Succs[1]
- b.Succs[1] = nil
- b.Succs = b.Succs[:1]
+ b.removeEdge(1)
b.Kind = BlockPlain
b.Likely = BranchUnknown
-
- if reachable[c.ID] {
- // Note: c must be reachable through some other edge.
- c.removePred(b)
- }
}
// Splice out any copies introduced during dead block removal.
@@ -217,35 +214,28 @@ func deadcode(f *Func) {
f.Blocks = f.Blocks[:i]
}
-// removePred removes the predecessor p from b's predecessor list.
-func (b *Block) removePred(p *Block) {
- var i int
- found := false
- for j, q := range b.Preds {
- if q == p {
- i = j
- found = true
- break
- }
- }
- // TODO: the above loop could make the deadcode pass take quadratic time
- if !found {
- b.Fatalf("can't find predecessor %v of %v\n", p, b)
- }
+// removeEdge removes the i'th outgoing edge from b (and
+// the corresponding incoming edge from b.Succs[i].b).
+func (b *Block) removeEdge(i int) {
+ e := b.Succs[i]
+ c := e.b
+ j := e.i
+
+ // Adjust b.Succs
+ b.removeSucc(i)
- n := len(b.Preds) - 1
- b.Preds[i] = b.Preds[n]
- b.Preds[n] = nil // aid GC
- b.Preds = b.Preds[:n]
+ // Adjust c.Preds
+ c.removePred(j)
- // rewrite phi ops to match the new predecessor list
- for _, v := range b.Values {
+ // Remove phi args from c's phis.
+ n := len(c.Preds)
+ for _, v := range c.Values {
if v.Op != OpPhi {
continue
}
- v.Args[i].Uses--
- v.Args[i] = v.Args[n]
- v.Args[n] = nil // aid GC
+ v.Args[j].Uses--
+ v.Args[j] = v.Args[n]
+ v.Args[n] = nil
v.Args = v.Args[:n]
phielimValue(v)
// Note: this is trickier than it looks. Replacing