mirror of
https://github.com/golang/go
synced 2024-11-13 18:30:26 -07:00
[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/19462 Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
parent
adc8d491c2
commit
65855cf640
@ -8,15 +8,7 @@ package ssa
|
||||
func copyelim(f *Func) {
|
||||
for _, b := range f.Blocks {
|
||||
for _, v := range b.Values {
|
||||
for i, w := range v.Args {
|
||||
x := w
|
||||
for x.Op == OpCopy {
|
||||
x = x.Args[0]
|
||||
}
|
||||
if x != w {
|
||||
v.Args[i] = x
|
||||
}
|
||||
}
|
||||
copyelimValue(v)
|
||||
}
|
||||
v := b.Control
|
||||
if v != nil {
|
||||
@ -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
|
||||
// and would that be useful?
|
||||
func phielim(f *Func) {
|
||||
for {
|
||||
changed := false
|
||||
change := false
|
||||
for _, b := range f.Blocks {
|
||||
nextv:
|
||||
for _, v := range b.Values {
|
||||
if v.Op != OpPhi {
|
||||
continue
|
||||
copyelimValue(v)
|
||||
change = phielimValue(v) || change
|
||||
}
|
||||
}
|
||||
if !change {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func phielimValue(v *Value) bool {
|
||||
if v.Op != OpPhi {
|
||||
return false
|
||||
}
|
||||
|
||||
// If there are two distinct args of v which
|
||||
// are not v itself, then the phi must remain.
|
||||
// Otherwise, we can replace it with a copy.
|
||||
var w *Value
|
||||
for _, x := range v.Args {
|
||||
for x.Op == OpCopy {
|
||||
x = x.Args[0]
|
||||
}
|
||||
if x == v {
|
||||
continue
|
||||
}
|
||||
@ -40,22 +48,17 @@ func phielim(f *Func) {
|
||||
continue
|
||||
}
|
||||
if w != nil {
|
||||
continue nextv
|
||||
return false
|
||||
}
|
||||
w = x
|
||||
}
|
||||
|
||||
if w == nil {
|
||||
// v references only itself. It must be in
|
||||
// a dead code loop. Don't bother modifying it.
|
||||
continue
|
||||
return false
|
||||
}
|
||||
v.Op = OpCopy
|
||||
v.SetArgs1(w)
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
if !changed {
|
||||
break
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -40,28 +40,8 @@ func applyRewrite(f *Func, rb func(*Block) bool, rv func(*Value, *Config) bool)
|
||||
}
|
||||
curb = nil
|
||||
for _, v := range b.Values {
|
||||
// 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 = a
|
||||
}
|
||||
advance = !advance
|
||||
}
|
||||
v.Args[i] = a
|
||||
}
|
||||
copyelimValue(v)
|
||||
change = phielimValue(v) || change
|
||||
|
||||
// apply rewrite function
|
||||
curv = v
|
||||
|
Loading…
Reference in New Issue
Block a user