mirror of
https://github.com/golang/go
synced 2024-10-05 18:21:21 -06:00
[dev.ssa] cmd/compile: respect phi values in tighten
Given (say) b1: <- b2 b3 v1 = Phi <t> v2 v3 b2: v2 = ... b3: ... tighten will move v2 to b1, since it is only used in b1. This is wrong; v2 needs to be evaluated before entering b1. Fix it. Change-Id: I2cc3b30e3ffd221cf594e36cec534dfd9cf3c6a7 Reviewed-on: https://go-review.googlesource.com/13264 Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
f91ff1a509
commit
e5fe33e546
@ -8,7 +8,8 @@ package ssa
|
|||||||
// This can reduce the amount of register spilling required,
|
// This can reduce the amount of register spilling required,
|
||||||
// if it doesn't also create more live values.
|
// if it doesn't also create more live values.
|
||||||
// For now, it handles only the trivial case in which a
|
// For now, it handles only the trivial case in which a
|
||||||
// Value with one or fewer args is only used in a single Block.
|
// Value with one or fewer args is only used in a single Block,
|
||||||
|
// and not in a phi value.
|
||||||
// TODO: Do something smarter.
|
// TODO: Do something smarter.
|
||||||
// A Value can be moved to any block that
|
// A Value can be moved to any block that
|
||||||
// dominates all blocks in which it is used.
|
// dominates all blocks in which it is used.
|
||||||
@ -17,6 +18,9 @@ func tighten(f *Func) {
|
|||||||
// For each value, the number of blocks in which it is used.
|
// For each value, the number of blocks in which it is used.
|
||||||
uses := make([]int, f.NumValues())
|
uses := make([]int, f.NumValues())
|
||||||
|
|
||||||
|
// For each value, whether that value is ever an arg to a phi value.
|
||||||
|
phi := make([]bool, f.NumValues())
|
||||||
|
|
||||||
// For each value, one block in which that value is used.
|
// For each value, one block in which that value is used.
|
||||||
home := make([]*Block, f.NumValues())
|
home := make([]*Block, f.NumValues())
|
||||||
|
|
||||||
@ -28,11 +32,15 @@ func tighten(f *Func) {
|
|||||||
for i := range uses {
|
for i := range uses {
|
||||||
uses[i] = 0
|
uses[i] = 0
|
||||||
}
|
}
|
||||||
// No need to reset home; any relevant values will be written anew anyway
|
// No need to reset home; any relevant values will be written anew anyway.
|
||||||
|
// No need to reset phi; once used in a phi, always used in a phi.
|
||||||
|
|
||||||
for _, b := range f.Blocks {
|
for _, b := range f.Blocks {
|
||||||
for _, v := range b.Values {
|
for _, v := range b.Values {
|
||||||
for _, w := range v.Args {
|
for _, w := range v.Args {
|
||||||
|
if v.Op == OpPhi {
|
||||||
|
phi[w.ID] = true
|
||||||
|
}
|
||||||
uses[w.ID]++
|
uses[w.ID]++
|
||||||
home[w.ID] = b
|
home[w.ID] = b
|
||||||
}
|
}
|
||||||
@ -49,7 +57,7 @@ func tighten(f *Func) {
|
|||||||
if v.Op == OpPhi {
|
if v.Op == OpPhi {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if uses[v.ID] == 1 && home[v.ID] != b && len(v.Args) < 2 {
|
if uses[v.ID] == 1 && !phi[v.ID] && home[v.ID] != b && len(v.Args) < 2 {
|
||||||
// v is used in exactly one block, and it is not b.
|
// v is used in exactly one block, and it is not b.
|
||||||
// Furthermore, it takes at most one input,
|
// Furthermore, it takes at most one input,
|
||||||
// so moving it will not increase the
|
// so moving it will not increase the
|
||||||
|
Loading…
Reference in New Issue
Block a user