diff options
author | Austin Clements <austin@google.com> | 2018-04-02 16:08:09 -0400 |
---|---|---|
committer | Austin Clements <austin@google.com> | 2018-04-20 18:46:39 +0000 |
commit | 8871c930bead174b942ce934677054f8958d0631 (patch) | |
tree | abfeb931342027082931e6d1997566a4bf4d55fe /src/cmd/compile/internal/ssa/regalloc.go | |
parent | c1a466b158d5bfa47993d52e5151588d23c45ab0 (diff) | |
download | go-8871c930bead174b942ce934677054f8958d0631.tar.gz go-8871c930bead174b942ce934677054f8958d0631.zip |
cmd/compile: don't lower OpConvert
Currently, each architecture lowers OpConvert to an arch-specific
OpXXXconvert. This is silly because OpConvert means the same thing on
all architectures and is logically a no-op that exists only to keep
track of conversions to and from unsafe.Pointer. Furthermore, lowering
it makes it harder to recognize in other analyses, particularly
liveness analysis.
This CL eliminates the lowering of OpConvert, leaving it as the
generic op until code generation time.
The main complexity here is that we still need to register-allocate
OpConvert operations. Currently, each arch's lowered OpConvert
specifies all GP registers in its register mask. Ideally, OpConvert
wouldn't affect value homing at all, and we could just copy the home
of OpConvert's source, but this can potentially home an OpConvert in a
LocalSlot, which neither regalloc nor stackalloc expect. Rather than
try to disentangle this assumption from regalloc and stackalloc, we
continue to register-allocate OpConvert, but teach regalloc that
OpConvert can be allocated to any allocatable GP register.
For #24543.
Change-Id: I795a6aee5fd94d4444a7bafac3838a400c9f7bb6
Reviewed-on: https://go-review.googlesource.com/108496
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Diffstat (limited to 'src/cmd/compile/internal/ssa/regalloc.go')
-rw-r--r-- | src/cmd/compile/internal/ssa/regalloc.go | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index 3fe170ac55..7e35526f19 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -714,6 +714,18 @@ func (s *regAllocState) compatRegs(t *types.Type) regMask { return m & s.allocatable } +// regspec returns the regInfo for operation op. +func (s *regAllocState) regspec(op Op) regInfo { + if op == OpConvert { + // OpConvert is a generic op, so it doesn't have a + // register set in the static table. It can use any + // allocatable integer register. + m := s.allocatable & s.f.Config.gpRegMask + return regInfo{inputs: []inputInfo{{regs: m}}, outputs: []outputInfo{{regs: m}}} + } + return opcodeTable[op].reg +} + func (s *regAllocState) regalloc(f *Func) { regValLiveSet := f.newSparseSet(f.NumValues()) // set of values that may be live in register defer f.retSparseSet(regValLiveSet) @@ -1035,8 +1047,9 @@ func (s *regAllocState) regalloc(f *Func) { for i := len(oldSched) - 1; i >= 0; i-- { v := oldSched[i] prefs := desired.remove(v.ID) - desired.clobber(opcodeTable[v.Op].reg.clobbers) - for _, j := range opcodeTable[v.Op].reg.inputs { + regspec := s.regspec(v.Op) + desired.clobber(regspec.clobbers) + for _, j := range regspec.inputs { if countRegs(j.regs) != 1 { continue } @@ -1064,7 +1077,7 @@ func (s *regAllocState) regalloc(f *Func) { if s.f.pass.debug > regDebug { fmt.Printf(" processing %s\n", v.LongString()) } - regspec := opcodeTable[v.Op].reg + regspec := s.regspec(v.Op) if v.Op == OpPhi { f.Fatalf("phi %s not at start of block", v) } @@ -2274,10 +2287,11 @@ func (s *regAllocState) computeLive() { // desired registers back though phi nodes. continue } + regspec := s.regspec(v.Op) // Cancel desired registers if they get clobbered. - desired.clobber(opcodeTable[v.Op].reg.clobbers) + desired.clobber(regspec.clobbers) // Update desired registers if there are any fixed register inputs. - for _, j := range opcodeTable[v.Op].reg.inputs { + for _, j := range regspec.inputs { if countRegs(j.regs) != 1 { continue } |