]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.ssa] cmd/compile: respect phi values in tighten
authorJosh Bleecher Snyder <josharian@gmail.com>
Wed, 5 Aug 2015 22:51:05 +0000 (15:51 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Thu, 6 Aug 2015 17:07:14 +0000 (17:07 +0000)
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>
src/cmd/compile/internal/ssa/tighten.go

index 9cf9a4459006f7ee8e2ed3f0cee7533d64c8b14c..a43218095e615094f2692dfc838e56ebaf94d77e 100644 (file)
@@ -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