Commit 833ed7c4 authored by Keith Randall's avatar Keith Randall

cmd/compile: reorganize SSA register numbering

Teach SSA about the cmd/internal/obj/$ARCH register numbering.
It can then return that numbering when requested.  Each architecture
now does not need to know anything about the internal SSA numbering
of registers.

Change-Id: I34472a2736227c15482e60994eebcdd2723fa52d
Reviewed-on: https://go-review.googlesource.com/29249Reviewed-by: default avatarDavid Chase <drchase@google.com>
parent b87d7a5c
......@@ -25,7 +25,6 @@ func Main() {
gc.Thearch.Defframe = defframe
gc.Thearch.Proginfo = proginfo
gc.Thearch.SSARegToReg = ssaRegToReg
gc.Thearch.SSAMarkMoves = ssaMarkMoves
gc.Thearch.SSAGenValue = ssaGenValue
gc.Thearch.SSAGenBlock = ssaGenBlock
......
This diff is collapsed.
......@@ -19,7 +19,6 @@ func Main() {
gc.Thearch.Defframe = defframe
gc.Thearch.Proginfo = proginfo
gc.Thearch.SSARegToReg = ssaRegToReg
gc.Thearch.SSAMarkMoves = func(s *gc.SSAGenState, b *ssa.Block) {}
gc.Thearch.SSAGenValue = ssaGenValue
gc.Thearch.SSAGenBlock = ssaGenBlock
......
This diff is collapsed.
......@@ -19,7 +19,6 @@ func Main() {
gc.Thearch.Defframe = defframe
gc.Thearch.Proginfo = proginfo
gc.Thearch.SSARegToReg = ssaRegToReg
gc.Thearch.SSAMarkMoves = func(s *gc.SSAGenState, b *ssa.Block) {}
gc.Thearch.SSAGenValue = ssaGenValue
gc.Thearch.SSAGenBlock = ssaGenBlock
......
This diff is collapsed.
......@@ -363,9 +363,6 @@ type Arch struct {
Proginfo func(*obj.Prog) // fills in Prog.Info
Use387 bool // should 8g use 387 FP instructions instead of sse2.
// SSARegToReg maps ssa register numbers to obj register numbers.
SSARegToReg []int16
// SSAMarkMoves marks any MOVXconst ops that need to avoid clobbering flags.
SSAMarkMoves func(*SSAGenState, *ssa.Block)
......
......@@ -4459,48 +4459,6 @@ func (s *state) extendIndex(v *ssa.Value, panicfn *Node) *ssa.Value {
return s.newValue1(op, Types[TINT], v)
}
// SSAReg returns the register to which v has been allocated.
func SSAReg(v *ssa.Value) *ssa.Register {
reg := v.Block.Func.RegAlloc[v.ID]
if reg == nil {
v.Fatalf("nil register for value: %s\n%s\n", v.LongString(), v.Block.Func)
}
return reg.(*ssa.Register)
}
// SSAReg0 returns the register to which the first output of v has been allocated.
func SSAReg0(v *ssa.Value) *ssa.Register {
reg := v.Block.Func.RegAlloc[v.ID].(ssa.LocPair)[0]
if reg == nil {
v.Fatalf("nil first register for value: %s\n%s\n", v.LongString(), v.Block.Func)
}
return reg.(*ssa.Register)
}
// SSAReg1 returns the register to which the second output of v has been allocated.
func SSAReg1(v *ssa.Value) *ssa.Register {
reg := v.Block.Func.RegAlloc[v.ID].(ssa.LocPair)[1]
if reg == nil {
v.Fatalf("nil second register for value: %s\n%s\n", v.LongString(), v.Block.Func)
}
return reg.(*ssa.Register)
}
// SSARegNum returns the register number (in cmd/internal/obj numbering) to which v has been allocated.
func SSARegNum(v *ssa.Value) int16 {
return Thearch.SSARegToReg[SSAReg(v).Num]
}
// SSARegNum0 returns the register number (in cmd/internal/obj numbering) to which the first output of v has been allocated.
func SSARegNum0(v *ssa.Value) int16 {
return Thearch.SSARegToReg[SSAReg0(v).Num]
}
// SSARegNum1 returns the register number (in cmd/internal/obj numbering) to which the second output of v has been allocated.
func SSARegNum1(v *ssa.Value) int16 {
return Thearch.SSARegToReg[SSAReg1(v).Num]
}
// CheckLoweredPhi checks that regalloc and stackalloc correctly handled phi values.
// Called during ssaGenValue.
func CheckLoweredPhi(v *ssa.Value) {
......
......@@ -23,7 +23,6 @@ func Main() {
gc.Thearch.Defframe = defframe
gc.Thearch.Proginfo = proginfo
gc.Thearch.SSARegToReg = ssaRegToReg
gc.Thearch.SSAMarkMoves = func(s *gc.SSAGenState, b *ssa.Block) {}
gc.Thearch.SSAGenValue = ssaGenValue
gc.Thearch.SSAGenBlock = ssaGenBlock
......
This diff is collapsed.
......@@ -22,7 +22,6 @@ func Main() {
gc.Thearch.Defframe = defframe
gc.Thearch.Proginfo = proginfo
gc.Thearch.SSARegToReg = ssaRegToReg
gc.Thearch.SSAMarkMoves = ssaMarkMoves
gc.Thearch.SSAGenValue = ssaGenValue
gc.Thearch.SSAGenBlock = ssaGenBlock
......
This diff is collapsed.
......@@ -18,7 +18,6 @@ func Main() {
gc.Thearch.Defframe = defframe
gc.Thearch.Proginfo = proginfo
gc.Thearch.SSARegToReg = ssaRegToReg
gc.Thearch.SSAMarkMoves = ssaMarkMoves
gc.Thearch.SSAGenValue = ssaGenValue
gc.Thearch.SSAGenBlock = ssaGenBlock
......
This diff is collapsed.
......@@ -269,7 +269,20 @@ func genOp() {
}
fmt.Fprintf(w, "var registers%s = [...]Register {\n", a.name)
for i, r := range a.regnames {
fmt.Fprintf(w, " {%d, \"%s\"},\n", i, r)
pkg := a.pkg[len("cmd/internal/obj/"):]
var objname string // name in cmd/internal/obj/$ARCH
switch r {
case "SB":
// SB isn't a real register. cmd/internal/obj expects 0 in this case.
objname = "0"
case "SP":
objname = pkg + ".REGSP"
case "g":
objname = pkg + ".REGG"
default:
objname = pkg + ".REG_" + r
}
fmt.Fprintf(w, " {%d, %s, \"%s\"},\n", i, objname, r)
}
fmt.Fprintln(w, "}")
fmt.Fprintf(w, "var gpRegMask%s = regMask(%d)\n", a.name, a.gpregmask)
......
......@@ -14,8 +14,9 @@ type Location interface {
// A Register is a machine register, like %rax.
// They are numbered densely from 0 (for each architecture).
type Register struct {
Num int32
name string
num int32
objNum int16 // register number from cmd/internal/obj/$ARCH
name string
}
func (r *Register) Name() string {
......
This diff is collapsed.
......@@ -941,7 +941,7 @@ func (s *regAllocState) regalloc(f *Func) {
if !ok {
continue
}
desired.add(v.Args[pidx].ID, register(rp.Num))
desired.add(v.Args[pidx].ID, register(rp.num))
}
}
// Walk values backwards computing desired register info.
......@@ -1000,7 +1000,7 @@ func (s *regAllocState) regalloc(f *Func) {
if v.Op == OpSelect1 {
i = 1
}
s.assignReg(register(s.f.getHome(v.Args[0].ID).(LocPair)[i].(*Register).Num), v, v)
s.assignReg(register(s.f.getHome(v.Args[0].ID).(LocPair)[i].(*Register).num), v, v)
}
b.Values = append(b.Values, v)
s.advanceUses(v)
......@@ -1210,12 +1210,12 @@ func (s *regAllocState) regalloc(f *Func) {
if opcodeTable[v.Op].resultInArg0 && out.idx == 0 {
if !opcodeTable[v.Op].commutative {
// Output must use the same register as input 0.
r := register(s.f.getHome(args[0].ID).(*Register).Num)
r := register(s.f.getHome(args[0].ID).(*Register).num)
mask = regMask(1) << r
} else {
// Output must use the same register as input 0 or 1.
r0 := register(s.f.getHome(args[0].ID).(*Register).Num)
r1 := register(s.f.getHome(args[1].ID).(*Register).Num)
r0 := register(s.f.getHome(args[0].ID).(*Register).num)
r1 := register(s.f.getHome(args[1].ID).(*Register).num)
// Check r0 and r1 for desired output register.
found := false
for _, r := range dinfo[idx].out {
......@@ -2015,16 +2015,16 @@ func (e *edgeState) set(loc Location, vid ID, c *Value, final bool, line int32)
a = append(a, c)
e.cache[vid] = a
if r, ok := loc.(*Register); ok {
e.usedRegs |= regMask(1) << uint(r.Num)
e.usedRegs |= regMask(1) << uint(r.num)
if final {
e.finalRegs |= regMask(1) << uint(r.Num)
e.finalRegs |= regMask(1) << uint(r.num)
}
if len(a) == 1 {
e.uniqueRegs |= regMask(1) << uint(r.Num)
e.uniqueRegs |= regMask(1) << uint(r.num)
}
if len(a) == 2 {
if t, ok := e.s.f.getHome(a[0].ID).(*Register); ok {
e.uniqueRegs &^= regMask(1) << uint(t.Num)
e.uniqueRegs &^= regMask(1) << uint(t.num)
}
}
}
......@@ -2064,14 +2064,14 @@ func (e *edgeState) erase(loc Location) {
// Update register masks.
if r, ok := loc.(*Register); ok {
e.usedRegs &^= regMask(1) << uint(r.Num)
e.usedRegs &^= regMask(1) << uint(r.num)
if cr.final {
e.finalRegs &^= regMask(1) << uint(r.Num)
e.finalRegs &^= regMask(1) << uint(r.num)
}
}
if len(a) == 1 {
if r, ok := e.s.f.getHome(a[0].ID).(*Register); ok {
e.uniqueRegs |= regMask(1) << uint(r.Num)
e.uniqueRegs |= regMask(1) << uint(r.num)
}
}
}
......@@ -2114,7 +2114,7 @@ func (e *edgeState) findRegFor(typ Type) Location {
for _, vid := range e.cachedVals {
a := e.cache[vid]
for _, c := range a {
if r, ok := e.s.f.getHome(c.ID).(*Register); ok && m>>uint(r.Num)&1 != 0 {
if r, ok := e.s.f.getHome(c.ID).(*Register); ok && m>>uint(r.num)&1 != 0 {
x := e.p.NewValue1(c.Line, OpStoreReg, c.Type, c)
e.set(t, vid, x, false, c.Line)
if e.s.f.pass.debug > regDebug {
......
......@@ -268,3 +268,38 @@ func (s *ArgSymbol) String() string {
func (s *AutoSymbol) String() string {
return s.Node.String()
}
// Reg returns the register assigned to v, in cmd/internal/obj/$ARCH numbering.
func (v *Value) Reg() int16 {
reg := v.Block.Func.RegAlloc[v.ID]
if reg == nil {
v.Fatalf("nil register for value: %s\n%s\n", v.LongString(), v.Block.Func)
}
return reg.(*Register).objNum
}
// Reg0 returns the register assigned to the first output of v, in cmd/internal/obj/$ARCH numbering.
func (v *Value) Reg0() int16 {
reg := v.Block.Func.RegAlloc[v.ID].(LocPair)[0]
if reg == nil {
v.Fatalf("nil first register for value: %s\n%s\n", v.LongString(), v.Block.Func)
}
return reg.(*Register).objNum
}
// Reg1 returns the register assigned to the second output of v, in cmd/internal/obj/$ARCH numbering.
func (v *Value) Reg1() int16 {
reg := v.Block.Func.RegAlloc[v.ID].(LocPair)[1]
if reg == nil {
v.Fatalf("nil second register for value: %s\n%s\n", v.LongString(), v.Block.Func)
}
return reg.(*Register).objNum
}
func (v *Value) RegName() string {
reg := v.Block.Func.RegAlloc[v.ID]
if reg == nil {
v.Fatalf("nil register for value: %s\n%s\n", v.LongString(), v.Block.Func)
}
return reg.(*Register).name
}
......@@ -32,7 +32,7 @@ func ssaGenValue387(s *gc.SSAGenState, v *ssa.Value) bool {
case ssa.Op386MOVSSconst2, ssa.Op386MOVSDconst2:
p := gc.Prog(loadPush(v.Type))
p.From.Type = obj.TYPE_MEM
p.From.Reg = gc.SSARegNum(v.Args[0])
p.From.Reg = v.Args[0].Reg()
p.To.Type = obj.TYPE_REG
p.To.Reg = x86.REG_F0
popAndSave(s, v)
......@@ -41,18 +41,18 @@ func ssaGenValue387(s *gc.SSAGenState, v *ssa.Value) bool {
case ssa.Op386MOVSSload, ssa.Op386MOVSDload, ssa.Op386MOVSSloadidx1, ssa.Op386MOVSDloadidx1, ssa.Op386MOVSSloadidx4, ssa.Op386MOVSDloadidx8:
p := gc.Prog(loadPush(v.Type))
p.From.Type = obj.TYPE_MEM
p.From.Reg = gc.SSARegNum(v.Args[0])
p.From.Reg = v.Args[0].Reg()
gc.AddAux(&p.From, v)
switch v.Op {
case ssa.Op386MOVSSloadidx1, ssa.Op386MOVSDloadidx1:
p.From.Scale = 1
p.From.Index = gc.SSARegNum(v.Args[1])
p.From.Index = v.Args[1].Reg()
case ssa.Op386MOVSSloadidx4:
p.From.Scale = 4
p.From.Index = gc.SSARegNum(v.Args[1])
p.From.Index = v.Args[1].Reg()
case ssa.Op386MOVSDloadidx8:
p.From.Scale = 8
p.From.Index = gc.SSARegNum(v.Args[1])
p.From.Index = v.Args[1].Reg()
}
p.To.Type = obj.TYPE_REG
p.To.Reg = x86.REG_F0
......@@ -75,7 +75,7 @@ func ssaGenValue387(s *gc.SSAGenState, v *ssa.Value) bool {
p.From.Type = obj.TYPE_REG
p.From.Reg = x86.REG_F0
p.To.Type = obj.TYPE_MEM
p.To.Reg = gc.SSARegNum(v.Args[0])
p.To.Reg = v.Args[0].Reg()
gc.AddAux(&p.To, v)
return true
......@@ -92,24 +92,24 @@ func ssaGenValue387(s *gc.SSAGenState, v *ssa.Value) bool {
p.From.Type = obj.TYPE_REG
p.From.Reg = x86.REG_F0
p.To.Type = obj.TYPE_MEM
p.To.Reg = gc.SSARegNum(v.Args[0])
p.To.Reg = v.Args[0].Reg()
gc.AddAux(&p.To, v)
switch v.Op {
case ssa.Op386MOVSSstoreidx1, ssa.Op386MOVSDstoreidx1:
p.To.Scale = 1
p.To.Index = gc.SSARegNum(v.Args[1])
p.To.Index = v.Args[1].Reg()
case ssa.Op386MOVSSstoreidx4:
p.To.Scale = 4
p.To.Index = gc.SSARegNum(v.Args[1])
p.To.Index = v.Args[1].Reg()
case ssa.Op386MOVSDstoreidx8:
p.To.Scale = 8
p.To.Index = gc.SSARegNum(v.Args[1])
p.To.Index = v.Args[1].Reg()
}
return true
case ssa.Op386ADDSS, ssa.Op386ADDSD, ssa.Op386SUBSS, ssa.Op386SUBSD,
ssa.Op386MULSS, ssa.Op386MULSD, ssa.Op386DIVSS, ssa.Op386DIVSD:
if gc.SSARegNum(v) != gc.SSARegNum(v.Args[0]) {
if v.Reg() != v.Args[0].Reg() {
v.Fatalf("input[0] and output not in same register %s", v.LongString())
}
......@@ -142,7 +142,7 @@ func ssaGenValue387(s *gc.SSAGenState, v *ssa.Value) bool {
p.From.Type = obj.TYPE_REG
p.From.Reg = x86.REG_F0
p.To.Type = obj.TYPE_REG
p.To.Reg = s.SSEto387[gc.SSARegNum(v)] + 1
p.To.Reg = s.SSEto387[v.Reg()] + 1
// Restore precision if needed.
switch v.Op {
......@@ -161,7 +161,7 @@ func ssaGenValue387(s *gc.SSAGenState, v *ssa.Value) bool {
p.From.Type = obj.TYPE_REG
p.From.Reg = x86.REG_F0
p.To.Type = obj.TYPE_REG
p.To.Reg = s.SSEto387[gc.SSARegNum(v.Args[1])] + 1
p.To.Reg = s.SSEto387[v.Args[1].Reg()] + 1
// Save AX.
p = gc.Prog(x86.AMOVL)
......@@ -200,7 +200,7 @@ func ssaGenValue387(s *gc.SSAGenState, v *ssa.Value) bool {
case ssa.Op386CVTSL2SS, ssa.Op386CVTSL2SD:
p := gc.Prog(x86.AMOVL)
p.From.Type = obj.TYPE_REG
p.From.Reg = gc.SSARegNum(v.Args[0])
p.From.Reg = v.Args[0].Reg()
scratch387(s, &p.To)
p = gc.Prog(x86.AFMOVL)
scratch387(s, &p.From)
......@@ -231,7 +231,7 @@ func ssaGenValue387(s *gc.SSAGenState, v *ssa.Value) bool {
p = gc.Prog(x86.AMOVL)
scratch387(s, &p.From)
p.To.Type = obj.TYPE_REG
p.To.Reg = gc.SSARegNum(v)
p.To.Reg = v.Reg()
// Restore control word.
p = gc.Prog(x86.AFLDCW)
......@@ -329,7 +329,7 @@ func ssaGenValue387(s *gc.SSAGenState, v *ssa.Value) bool {
func push(s *gc.SSAGenState, v *ssa.Value) {
p := gc.Prog(x86.AFMOVD)
p.From.Type = obj.TYPE_REG
p.From.Reg = s.SSEto387[gc.SSARegNum(v)]
p.From.Reg = s.SSEto387[v.Reg()]
p.To.Type = obj.TYPE_REG
p.To.Reg = x86.REG_F0
}
......@@ -337,14 +337,14 @@ func push(s *gc.SSAGenState, v *ssa.Value) {
// popAndSave pops a value off of the floating-point stack and stores
// it in the reigster assigned to v.
func popAndSave(s *gc.SSAGenState, v *ssa.Value) {
r := gc.SSARegNum(v)
r := v.Reg()
if _, ok := s.SSEto387[r]; ok {
// Pop value, write to correct register.
p := gc.Prog(x86.AFMOVDP)
p.From.Type = obj.TYPE_REG
p.From.Reg = x86.REG_F0
p.To.Type = obj.TYPE_REG
p.To.Reg = s.SSEto387[gc.SSARegNum(v)] + 1
p.To.Reg = s.SSEto387[v.Reg()] + 1
} else {
// Don't actually pop value. This 387 register is now the
// new home for the not-yet-assigned-a-home SSE register.
......
......@@ -29,7 +29,6 @@ func Main() {
gc.Thearch.Defframe = defframe
gc.Thearch.Proginfo = proginfo
gc.Thearch.SSARegToReg = ssaRegToReg
gc.Thearch.SSAMarkMoves = ssaMarkMoves
gc.Thearch.SSAGenValue = ssaGenValue
gc.Thearch.SSAGenBlock = ssaGenBlock
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment