[dev.ssa] cmd/compile/internal/ssa: New register allocator

Implement a global (whole function) register allocator.
This replaces the local (per basic block) register allocator.

Clobbering of registers by instructions is handled properly.
A separate change will add the correct clobbers to all the instructions.

Change-Id: I38ce4dc7dccb8303c1c0e0295fe70247b0a3f2ea
Reviewed-on: https://go-review.googlesource.com/13622
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: Todd Neal <todd@tneal.org>
This commit is contained in:
Keith Randall 2015-08-11 12:51:33 -07:00
parent 759b9c3b80
commit 0b46b42943
12 changed files with 1447 additions and 750 deletions

View file

@ -15,6 +15,7 @@ import (
"io/ioutil"
"log"
"regexp"
"sort"
)
type arch struct {
@ -125,11 +126,22 @@ func genOp() {
fmt.Fprintf(w, "asm: x86.A%s,\n", v.asm)
}
fmt.Fprintln(w, "reg:regInfo{")
// reg inputs
if len(v.reg.inputs) > 0 {
fmt.Fprintln(w, "inputs: []regMask{")
for _, r := range v.reg.inputs {
fmt.Fprintf(w, "%d,%s\n", r, a.regMaskComment(r))
// Compute input allocation order. We allocate from the
// most to the least constrained input. This order guarantees
// that we will always be able to find a register.
var s []intPair
for i, r := range v.reg.inputs {
if r != 0 {
s = append(s, intPair{countRegs(r), i})
}
}
if len(s) > 0 {
sort.Sort(byKey(s))
fmt.Fprintln(w, "inputs: []inputInfo{")
for _, p := range s {
r := v.reg.inputs[p.val]
fmt.Fprintf(w, "{%d,%d},%s\n", p.val, r, a.regMaskComment(r))
}
fmt.Fprintln(w, "},")
}
@ -205,3 +217,23 @@ func genLower() {
genRules(a)
}
}
// countRegs returns the number of set bits in the register mask.
func countRegs(r regMask) int {
n := 0
for r != 0 {
n += int(r & 1)
r >>= 1
}
return n
}
// for sorting a pair of integers by key
type intPair struct {
key, val int
}
type byKey []intPair
func (a byKey) Len() int { return len(a) }
func (a byKey) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a byKey) Less(i, j int) bool { return a[i].key < a[j].key }