1
0
mirror of https://github.com/golang/go synced 2024-10-05 16:31:21 -06:00

[dev.ssa] cmd/compile: assign unused registers to phi ops

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>
This commit is contained in:
Keith Randall 2015-10-19 12:24:22 -07:00
parent fbfc18c522
commit f206b16ff7

View File

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