From d04f38e3ee7b7948c4fd18a0a26ad351d2b88670 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 29 Oct 2015 13:41:02 -0700 Subject: [PATCH] [dev.ssa] cmd/compile: flag recomputing: find original values correctly We "spill" flag values by recomputing them from their original inputs. The "find original inputs" part of the algorithm was a hack. It was broken by rematerialization. This change does the real job of keeping track of original values for each spill/restore/flagrecompute/rematerialization we issue. Change-Id: I95088326a4ee4958c98148b063e518c80e863e4c Reviewed-on: https://go-review.googlesource.com/16500 Run-TryBot: Keith Randall Reviewed-by: Josh Bleecher Snyder TryBot-Result: Gobot Gobot --- src/cmd/compile/internal/ssa/regalloc.go | 32 +++++++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index 8181f8d39b..89deb14a4a 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -241,6 +241,10 @@ type regAllocState struct { // current state of each (preregalloc) Value values []valState + // For each Value, map from its value ID back to the + // preregalloc Value it was derived from. + orig []*Value + // current state of each register regs []regState @@ -298,6 +302,18 @@ func (s *regAllocState) getHome(v *Value) register { return register(s.home[v.ID].(*Register).Num) } +// setOrig records that c's original value is the same as +// v's original value. +func (s *regAllocState) setOrig(c *Value, v *Value) { + for int(c.ID) >= len(s.orig) { + s.orig = append(s.orig, nil) + } + if s.orig[c.ID] != nil { + s.f.Fatalf("orig value set twice %s %s", c, v) + } + s.orig[c.ID] = s.orig[v.ID] +} + // assignReg assigns register r to hold c, a copy of v. // r must be unused. func (s *regAllocState) assignReg(r register, v *Value, c *Value) { @@ -421,11 +437,8 @@ func (s *regAllocState) allocValToReg(v *Value, mask regMask, nospill bool) *Val args := make([]*Value, 0, len(v.Args)) regspec := opcodeTable[v.Op].reg for _, i := range regspec.inputs { - a := v.Args[i.idx] // Extract the original arguments to v - for a.Op == OpLoadReg || a.Op == OpStoreReg || a.Op == OpCopy { - a = a.Args[0] - } + a := s.orig[v.Args[i.idx].ID] if a.Type.IsFlags() { s.f.Fatalf("cannot load flags value with flags arg: %v has unwrapped arg %v", v.LongString(), a.LongString()) } @@ -457,6 +470,7 @@ func (s *regAllocState) allocValToReg(v *Value, mask regMask, nospill bool) *Val s.f.Fatalf("attempt to load unspilled value %v", v.LongString()) } } + s.setOrig(c, v) s.assignReg(r, v, c) if nospill { s.nospill |= regMask(1) << r @@ -475,6 +489,12 @@ func (s *regAllocState) init(f *Func) { for i := range s.values { s.values[i].uses = s.values[i].usestorage[:0] } + s.orig = make([]*Value, f.NumValues()) + for _, b := range f.Blocks { + for _, v := range b.Values { + s.orig[v.ID] = v + } + } s.live = f.live() // Compute block order. This array allows us to distinguish forward edges @@ -709,6 +729,7 @@ func (s *regAllocState) regalloc(f *Func) { s.assignReg(r, v, v) // Spill the phi in case we need to restore it later. spill := b.NewValue1(v.Line, OpStoreReg, v.Type, v) + s.setOrig(spill, v) s.values[v.ID].spill = spill s.values[v.ID].spillUsed = false } @@ -793,6 +814,7 @@ func (s *regAllocState) regalloc(f *Func) { // then at the end of regalloc delete the ones we never use. if !v.Type.IsFlags() { spill := b.NewValue1(v.Line, OpStoreReg, v.Type, v) + s.setOrig(spill, v) s.values[v.ID].spill = spill s.values[v.ID].spillUsed = false } @@ -883,6 +905,7 @@ func (s *regAllocState) regalloc(f *Func) { // value so that we don't clobber it prematurely. c := s.allocValToReg(v, s.compatRegs(v), false) d := p.NewValue1(v.Line, OpStoreReg, v.Type, c) + s.setOrig(d, v) s.values[v.ID].spill2 = d } @@ -895,6 +918,7 @@ func (s *regAllocState) regalloc(f *Func) { w := v.Args[i] c := s.allocValToReg(w, s.compatRegs(w), false) v.Args[i] = p.NewValue1(v.Line, OpStoreReg, v.Type, c) + s.setOrig(v.Args[i], w) } // Figure out what value goes in each register. for r := register(0); r < numRegs; r++ {