Commit 65855cf6 authored by Alexandru Moșoi's avatar Alexandru Moșoi Committed by David Chase

[dev.ssa] cmd/compile/internal/ssa: factor out copyelimValue and phielimValue

* Merge copyelim into phielim.
* Add phielimValue to rewrite. cgoIsGoPointer is, for example, 2
instructions smaller now.

Change-Id: I8baeb206d1b3ef8aba4a6e3bcdc432959bcae2d5
Reviewed-on: https://go-review.googlesource.com/19462Reviewed-by: default avatarDavid Chase <drchase@google.com>
parent adc8d491
...@@ -8,15 +8,7 @@ package ssa ...@@ -8,15 +8,7 @@ package ssa
func copyelim(f *Func) { func copyelim(f *Func) {
for _, b := range f.Blocks { for _, b := range f.Blocks {
for _, v := range b.Values { for _, v := range b.Values {
for i, w := range v.Args { copyelimValue(v)
x := w
for x.Op == OpCopy {
x = x.Args[0]
}
if x != w {
v.Args[i] = x
}
}
} }
v := b.Control v := b.Control
if v != nil { if v != nil {
...@@ -41,3 +33,28 @@ func copyelim(f *Func) { ...@@ -41,3 +33,28 @@ func copyelim(f *Func) {
} }
} }
} }
func copyelimValue(v *Value) {
// elide any copies generated during rewriting
for i, a := range v.Args {
if a.Op != OpCopy {
continue
}
// Rewriting can generate OpCopy loops.
// They are harmless (see removePredecessor),
// but take care to stop if we find a cycle.
slow := a // advances every other iteration
var advance bool
for a.Op == OpCopy {
a = a.Args[0]
if slow == a {
break
}
if advance {
slow = slow.Args[0]
}
advance = !advance
}
v.Args[i] = a
}
}
...@@ -18,21 +18,29 @@ package ssa ...@@ -18,21 +18,29 @@ package ssa
// and would that be useful? // and would that be useful?
func phielim(f *Func) { func phielim(f *Func) {
for { for {
changed := false change := false
for _, b := range f.Blocks { for _, b := range f.Blocks {
nextv:
for _, v := range b.Values { for _, v := range b.Values {
copyelimValue(v)
change = phielimValue(v) || change
}
}
if !change {
break
}
}
}
func phielimValue(v *Value) bool {
if v.Op != OpPhi { if v.Op != OpPhi {
continue return false
} }
// If there are two distinct args of v which // If there are two distinct args of v which
// are not v itself, then the phi must remain. // are not v itself, then the phi must remain.
// Otherwise, we can replace it with a copy. // Otherwise, we can replace it with a copy.
var w *Value var w *Value
for _, x := range v.Args { for _, x := range v.Args {
for x.Op == OpCopy {
x = x.Args[0]
}
if x == v { if x == v {
continue continue
} }
...@@ -40,22 +48,17 @@ func phielim(f *Func) { ...@@ -40,22 +48,17 @@ func phielim(f *Func) {
continue continue
} }
if w != nil { if w != nil {
continue nextv return false
} }
w = x w = x
} }
if w == nil { if w == nil {
// v references only itself. It must be in // v references only itself. It must be in
// a dead code loop. Don't bother modifying it. // a dead code loop. Don't bother modifying it.
continue return false
} }
v.Op = OpCopy v.Op = OpCopy
v.SetArgs1(w) v.SetArgs1(w)
changed = true return true
}
}
if !changed {
break
}
}
} }
...@@ -40,28 +40,8 @@ func applyRewrite(f *Func, rb func(*Block) bool, rv func(*Value, *Config) bool) ...@@ -40,28 +40,8 @@ func applyRewrite(f *Func, rb func(*Block) bool, rv func(*Value, *Config) bool)
} }
curb = nil curb = nil
for _, v := range b.Values { for _, v := range b.Values {
// elide any copies generated during rewriting copyelimValue(v)
for i, a := range v.Args { change = phielimValue(v) || change
if a.Op != OpCopy {
continue
}
// Rewriting can generate OpCopy loops.
// They are harmless (see removePredecessor),
// but take care to stop if we find a cycle.
slow := a // advances every other iteration
var advance bool
for a.Op == OpCopy {
a = a.Args[0]
if slow == a {
break
}
if advance {
slow = a
}
advance = !advance
}
v.Args[i] = a
}
// apply rewrite function // apply rewrite function
curv = v curv = v
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment