]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.ssa] cmd/compile: assign unused registers to phi ops
authorKeith Randall <khr@golang.org>
Mon, 19 Oct 2015 19:24:22 +0000 (12:24 -0700)
committerKeith Randall <khr@golang.org>
Thu, 22 Oct 2015 17:06:10 +0000 (17:06 +0000)
Register phis are better than stack phis.  If we have
unused registers available, use them for phis.

Change-Id: I3045711c65caa1b6d0be29131b87b57466320cc2
Reviewed-on: https://go-review.googlesource.com/16080
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: David Chase <drchase@google.com>
src/cmd/compile/internal/ssa/regalloc.go

index 9cf589b215b3c27c608b161de262d536014712c6..abbb540a7e9848126798ad149c70553f3f18f804 100644 (file)
@@ -567,14 +567,12 @@ func (s *regAllocState) setState(state []regState) {
        }
 }
 
-// compatReg returns a register compatible with the a value and is used when
-// spilling/loading.
-// TODO: choose a better default register (set of reg by type?).
-func compatReg(v *Value) regMask {
+// compatRegs returns the set of registers which can store v.
+func (v *Value) compatRegs() regMask {
        if v.Type.IsFloat() {
-               return 1 << 16 // X0
+               return 0xffff << 16 // X0-X15
        }
-       return 1 << 0 // AX
+       return 0xffef << 0 // AX-R15, except SP
 }
 
 func (s *regAllocState) regalloc(f *Func) {
@@ -688,15 +686,21 @@ func (s *regAllocState) regalloc(f *Func) {
                                }
                                r := phiRegs[i]
                                if r == noRegister {
-                                       // stack-based phi
-                                       // Spills will be inserted in all the predecessors below.
-                                       s.values[v.ID].spill = v        // v starts life spilled
-                                       s.values[v.ID].spillUsed = true // use is guaranteed
-                                       continue
+                                       m := v.compatRegs() & ^s.used
+                                       if m == 0 {
+                                               // stack-based phi
+                                               // Spills will be inserted in all the predecessors below.
+                                               s.values[v.ID].spill = v        // v starts life spilled
+                                               s.values[v.ID].spillUsed = true // use is guaranteed
+                                               continue
+                                       }
+                                       // Allocate phi to an unused register.
+                                       r = pickReg(m)
+                               } else {
+                                       s.freeReg(r)
                                }
                                // register-based phi
                                // Transfer ownership of register from input arg to phi.
-                               s.freeReg(r)
                                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)
@@ -872,7 +876,7 @@ func (s *regAllocState) regalloc(f *Func) {
                                // This stack-based phi is the argument of some other
                                // phi in this block.  We must make a copy of its
                                // value so that we don't clobber it prematurely.
-                               c := s.allocValToReg(v, s.values[v.ID].regs|compatReg(v), false)
+                               c := s.allocValToReg(v, v.compatRegs(), false)
                                d := p.NewValue1(v.Line, OpStoreReg, v.Type, c)
                                s.values[v.ID].spill2 = d
                        }
@@ -884,7 +888,7 @@ func (s *regAllocState) regalloc(f *Func) {
                                // If already in a register, use that.  If not, pick a compatible
                                // register.
                                w := v.Args[i]
-                               c := s.allocValToReg(w, s.values[w.ID].regs|compatReg(w), false)
+                               c := s.allocValToReg(w, w.compatRegs(), false)
                                v.Args[i] = p.NewValue1(v.Line, OpStoreReg, v.Type, c)
                        }
                        // Figure out what value goes in each register.