]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix use of original spill name after sinking
authorDavid Chase <drchase@google.com>
Wed, 13 Apr 2016 17:30:03 +0000 (13:30 -0400)
committerDavid Chase <drchase@google.com>
Thu, 14 Apr 2016 18:24:54 +0000 (18:24 +0000)
This is a fix for the ssacheck builder
http://build.golang.org/log/baa00f70c34e41186051cfe90568de3d91f115d7
after CL 21307 for sinking spills down loop exits
https://go-review.googlesource.com/#/c/21037/

The fix is to reuse (move) the original spill, thus preserving
the definition of the variable and its use count. Original and
copy both use the same stack slot, but ssacheck needs to see
a definition for the variable itself.

Fixes #15279.

Change-Id: I286285490193dc211b312d64dbc5a54867730bd6
Reviewed-on: https://go-review.googlesource.com/21995
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/ssa/check.go
src/cmd/compile/internal/ssa/regalloc.go

index 5a17735304418283f5810a6079452b49389acde5..e4b8cb05f4281aece1b8fc98e8d8c56abdfbdc55 100644 (file)
@@ -162,7 +162,7 @@ func checkFunc(f *Func) {
                        // variable length args)
                        nArgs := opcodeTable[v.Op].argLen
                        if nArgs != -1 && int32(len(v.Args)) != nArgs {
-                               f.Fatalf("value %v has %d args, expected %d", v.LongString(),
+                               f.Fatalf("value %s has %d args, expected %d", v.LongString(),
                                        len(v.Args), nArgs)
                        }
 
@@ -207,15 +207,15 @@ func checkFunc(f *Func) {
                                f.Fatalf("unknown aux type for %s", v.Op)
                        }
                        if !canHaveAux && v.Aux != nil {
-                               f.Fatalf("value %v has an Aux value %v but shouldn't", v.LongString(), v.Aux)
+                               f.Fatalf("value %s has an Aux value %v but shouldn't", v.LongString(), v.Aux)
                        }
                        if !canHaveAuxInt && v.AuxInt != 0 {
-                               f.Fatalf("value %v has an AuxInt value %d but shouldn't", v.LongString(), v.AuxInt)
+                               f.Fatalf("value %s has an AuxInt value %d but shouldn't", v.LongString(), v.AuxInt)
                        }
 
                        for _, arg := range v.Args {
                                if arg == nil {
-                                       f.Fatalf("value %v has nil arg", v.LongString())
+                                       f.Fatalf("value %s has nil arg", v.LongString())
                                }
                        }
 
@@ -271,7 +271,7 @@ func checkFunc(f *Func) {
                for _, v := range b.Values {
                        for i, a := range v.Args {
                                if !valueMark[a.ID] {
-                                       f.Fatalf("%v, arg %d of %v, is missing", a, i, v)
+                                       f.Fatalf("%v, arg %d of %s, is missing", a, i, v.LongString())
                                }
                        }
                }
index d1de3646d9ff51c662de7f1813602085d3f11d70..7be1cf593c3957376201a79923f97b50ea2ab36e 100644 (file)
 // there is one spill site (one StoreReg) targeting stack slot X, after
 // sinking there may be multiple spill sites targeting stack slot X,
 // with no phi functions at any join points reachable by the multiple
-// spill sites.
+// spill sites.  In addition, uses of the spill from copies of the original
+// will not name the copy in their reference; instead they will name
+// the original, though both will have the same spill location.  The
+// first sunk spill will be the original, but moved, to an exit block,
+// thus ensuring that there is a definition somewhere corresponding to
+// the original spill's uses.
 
 package ssa
 
@@ -1354,6 +1359,7 @@ sinking:
                }
                b.Values = b.Values[:i]
 
+               first := true
                for i := uint(0); i < 32 && dests != 0; i++ {
 
                        if dests&(1<<i) == 0 {
@@ -1363,18 +1369,28 @@ sinking:
                        dests ^= 1 << i
 
                        d := loop.exits[i]
-                       vspnew := d.NewValue1(e.Line, OpStoreReg, e.Type, e)
-
-                       if s.f.pass.debug > moveSpills {
-                               s.f.Config.Warnl(e.Line, "moved spill %v in %v for %v to %v in %v",
-                                       vsp, b, e, vspnew, d)
+                       vspnew := vsp // reuse original for first sunk spill, saves tracking down and renaming uses
+                       if !first {   // any sunk spills after first must make a copy
+                               vspnew = d.NewValue1(e.Line, OpStoreReg, e.Type, e)
+                               f.setHome(vspnew, f.getHome(vsp.ID)) // copy stack home
+                               if s.f.pass.debug > moveSpills {
+                                       s.f.Config.Warnl(e.Line, "copied spill %v in %v for %v to %v in %v",
+                                               vsp, b, e, vspnew, d)
+                               }
+                       } else {
+                               first = false
+                               vspnew.Block = d
+                               d.Values = append(d.Values, vspnew)
+                               if s.f.pass.debug > moveSpills {
+                                       s.f.Config.Warnl(e.Line, "moved spill %v in %v for %v to %v in %v",
+                                               vsp, b, e, vspnew, d)
+                               }
                        }
 
-                       f.setHome(vspnew, f.getHome(vsp.ID)) // copy stack home
-
                        // shuffle vspnew to the beginning of its block
                        copy(d.Values[1:], d.Values[0:len(d.Values)-1])
                        d.Values[0] = vspnew
+
                }
        }