aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/ssa/regalloc.go
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2018-04-02 16:08:09 -0400
committerAustin Clements <austin@google.com>2018-04-20 18:46:39 +0000
commit8871c930bead174b942ce934677054f8958d0631 (patch)
treeabfeb931342027082931e6d1997566a4bf4d55fe /src/cmd/compile/internal/ssa/regalloc.go
parentc1a466b158d5bfa47993d52e5151588d23c45ab0 (diff)
downloadgo-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.go24
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
}