From: Keith Randall Date: Mon, 19 Oct 2015 17:57:03 +0000 (-0700) Subject: [dev.ssa] cmd/compile: Rematerialize in regalloc X-Git-Tag: go1.7beta1~1623^2^2~138 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=c64a6f636282e1db66e6bda681be9b76069b1918;p=gostls13.git [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 Reviewed-by: David Chase --- diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index 9d0aab64cc..6418bb375d 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -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