mirror of
https://github.com/golang/go.git
synced 2025-05-27 18:31:35 +00:00
[dev.ssa] cmd/compile: Rematerialize in regalloc
Rematerialize constants instead of spilling and loading them. "Constants" includes constant offsets from SP and SB. Should help somewhat with stack frame sizes. I'm not sure exactly how much yet. Change-Id: I44dbad97aae870cf31cb6e89c92fe4f6a2b9586f Reviewed-on: https://go-review.googlesource.com/16029 Run-TryBot: Keith Randall <khr@golang.org> Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
parent
d076ef749b
commit
c64a6f6362
@ -399,6 +399,12 @@ func (s *regAllocState) allocValToReg(v *Value, mask regMask, nospill bool) *Val
|
||||
panic("bad register state")
|
||||
}
|
||||
c = s.curBlock.NewValue1(v.Line, OpCopy, v.Type, s.regs[r2].c)
|
||||
} else if v.rematerializeable() {
|
||||
// Rematerialize instead of loading from the spill location.
|
||||
c = s.curBlock.NewValue0(v.Line, v.Op, v.Type)
|
||||
c.Aux = v.Aux
|
||||
c.AuxInt = v.AuxInt
|
||||
c.AddArgs(v.Args...)
|
||||
} else {
|
||||
switch {
|
||||
// It is difficult to spill and reload flags on many architectures.
|
||||
@ -433,7 +439,6 @@ func (s *regAllocState) allocValToReg(v *Value, mask regMask, nospill bool) *Val
|
||||
c.AddArgs(args...)
|
||||
|
||||
// Load v from its spill location.
|
||||
// TODO: rematerialize if we can.
|
||||
case vi.spill2 != nil:
|
||||
if logSpills {
|
||||
fmt.Println("regalloc: load spill2")
|
||||
@ -737,8 +742,13 @@ func (s *regAllocState) regalloc(f *Func) {
|
||||
continue
|
||||
}
|
||||
|
||||
// TODO: If value is rematerializeable, don't issue it here.
|
||||
// Instead, rely on argument loading code to put it in a register when needed.
|
||||
if v.rematerializeable() {
|
||||
// Value is rematerializeable, don't issue it here.
|
||||
// It will get issued just before each use (see
|
||||
// allocValueToReg).
|
||||
pc++
|
||||
continue
|
||||
}
|
||||
|
||||
// Move arguments to registers
|
||||
for _, i := range regspec.inputs {
|
||||
@ -962,6 +972,26 @@ func (s *regAllocState) regalloc(f *Func) {
|
||||
f.RegAlloc = s.home
|
||||
}
|
||||
|
||||
func (v *Value) rematerializeable() bool {
|
||||
// TODO: add a flags field to opInfo for this test?
|
||||
|
||||
// rematerializeable ops must be able to fill any register.
|
||||
outputs := opcodeTable[v.Op].reg.outputs
|
||||
if len(outputs) == 0 || countRegs(outputs[0]) <= 1 {
|
||||
// Note: this case handles OpAMD64LoweredGetClosurePtr
|
||||
// which can't be moved.
|
||||
return false
|
||||
}
|
||||
// TODO: maybe not OpAMD64LoweredGetG?
|
||||
if len(v.Args) == 0 {
|
||||
return true
|
||||
}
|
||||
if len(v.Args) == 1 && (v.Args[0].Op == OpSP || v.Args[0].Op == OpSB) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// live returns a map from block ID and successor edge index to a list
|
||||
// of value IDs live on that edge.
|
||||
// TODO: this could be quadratic if lots of variables are live across lots of
|
||||
|
Loading…
x
Reference in New Issue
Block a user