Commit e5fe33e5 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

[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/13264Reviewed-by: 's avatarKeith Randall <khr@golang.org>
parent f91ff1a5
...@@ -8,7 +8,8 @@ package ssa ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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
......
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