From e5fe33e546589d57616cf9603781299a3c5751dc Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Wed, 5 Aug 2015 15:51:05 -0700 Subject: [PATCH] [dev.ssa] cmd/compile: respect phi values in tighten Given (say) b1: <- b2 b3 v1 = Phi 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 --- src/cmd/compile/internal/ssa/tighten.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/ssa/tighten.go b/src/cmd/compile/internal/ssa/tighten.go index 9cf9a44590..a43218095e 100644 --- a/src/cmd/compile/internal/ssa/tighten.go +++ b/src/cmd/compile/internal/ssa/tighten.go @@ -8,7 +8,8 @@ package ssa // This can reduce the amount of register spilling required, // if it doesn't also create more live values. // 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. // A Value can be moved to any block that // 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. 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. home := make([]*Block, f.NumValues()) @@ -28,11 +32,15 @@ func tighten(f *Func) { for i := range uses { 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 _, v := range b.Values { for _, w := range v.Args { + if v.Op == OpPhi { + phi[w.ID] = true + } uses[w.ID]++ home[w.ID] = b } @@ -49,7 +57,7 @@ func tighten(f *Func) { if v.Op == OpPhi { 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. // Furthermore, it takes at most one input, // so moving it will not increase the -- 2.48.1