Commit 840f25be authored by Austin Clements's avatar Austin Clements

cmd/compile: dense numbering for GP registers

For register maps, we need a dense numbering of registers that may
contain pointers of interest to the garbage collector. Add this to
Register and compute it from the GP register set.

For #24543.

Change-Id: If6f0521effca5eca4d17895468b1fc52d67e0f32
Reviewed-on: https://go-review.googlesource.com/109351
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarKeith Randall <khr@golang.org>
parent 4f765b18
...@@ -27,6 +27,7 @@ type Config struct { ...@@ -27,6 +27,7 @@ type Config struct {
gpRegMask regMask // general purpose integer register mask gpRegMask regMask // general purpose integer register mask
fpRegMask regMask // floating point register mask fpRegMask regMask // floating point register mask
specialRegMask regMask // special register mask specialRegMask regMask // special register mask
GCRegMap []*Register // garbage collector register map, by GC register index
FPReg int8 // register number of frame pointer, -1 if not used FPReg int8 // register number of frame pointer, -1 if not used
LinkReg int8 // register number of link register if it is a general purpose register, -1 if not used LinkReg int8 // register number of link register if it is a general purpose register, -1 if not used
hasGReg bool // has hardware g register hasGReg bool // has hardware g register
...@@ -375,6 +376,21 @@ func NewConfig(arch string, types Types, ctxt *obj.Link, optimize bool) *Config ...@@ -375,6 +376,21 @@ func NewConfig(arch string, types Types, ctxt *obj.Link, optimize bool) *Config
c.sparsePhiCutoff = uint64(v) // convert -1 to maxint, for never use sparse c.sparsePhiCutoff = uint64(v) // convert -1 to maxint, for never use sparse
} }
// Create the GC register map index.
// TODO: This is only used for debug printing. Maybe export config.registers?
gcRegMapSize := int16(0)
for _, r := range c.registers {
if r.gcNum+1 > gcRegMapSize {
gcRegMapSize = r.gcNum + 1
}
}
c.GCRegMap = make([]*Register, gcRegMapSize)
for i, r := range c.registers {
if r.gcNum != -1 {
c.GCRegMap[r.gcNum] = &c.registers[i]
}
}
return c return c
} }
......
...@@ -301,6 +301,7 @@ func genOp() { ...@@ -301,6 +301,7 @@ func genOp() {
continue continue
} }
fmt.Fprintf(w, "var registers%s = [...]Register {\n", a.name) fmt.Fprintf(w, "var registers%s = [...]Register {\n", a.name)
var gcRegN int
for i, r := range a.regnames { for i, r := range a.regnames {
pkg := a.pkg[len("cmd/internal/obj/"):] pkg := a.pkg[len("cmd/internal/obj/"):]
var objname string // name in cmd/internal/obj/$ARCH var objname string // name in cmd/internal/obj/$ARCH
...@@ -315,7 +316,18 @@ func genOp() { ...@@ -315,7 +316,18 @@ func genOp() {
default: default:
objname = pkg + ".REG_" + r objname = pkg + ".REG_" + r
} }
fmt.Fprintf(w, " {%d, %s, \"%s\"},\n", i, objname, r) // Assign a GC register map index to registers
// that may contain pointers.
gcRegIdx := -1
if a.gpregmask&(1<<uint(i)) != 0 {
gcRegIdx = gcRegN
gcRegN++
}
fmt.Fprintf(w, " {%d, %s, %d, \"%s\"},\n", i, objname, gcRegIdx, r)
}
if gcRegN > 32 {
// Won't fit in a uint32 mask.
log.Fatalf("too many GC registers (%d > 32) on %s", gcRegN, a.name)
} }
fmt.Fprintln(w, "}") fmt.Fprintln(w, "}")
fmt.Fprintf(w, "var gpRegMask%s = regMask(%d)\n", a.name, a.gpregmask) fmt.Fprintf(w, "var gpRegMask%s = regMask(%d)\n", a.name, a.gpregmask)
......
...@@ -19,6 +19,7 @@ type Location interface { ...@@ -19,6 +19,7 @@ type Location interface {
type Register struct { type Register struct {
num int32 // dense numbering num int32 // dense numbering
objNum int16 // register number from cmd/internal/obj/$ARCH objNum int16 // register number from cmd/internal/obj/$ARCH
gcNum int16 // GC register map number (dense numbering of registers that can contain pointers)
name string name string
} }
...@@ -32,6 +33,12 @@ func (r *Register) ObjNum() int16 { ...@@ -32,6 +33,12 @@ func (r *Register) ObjNum() int16 {
return r.objNum return r.objNum
} }
// GCNum returns the runtime GC register index of r, or -1 if this
// register can't contain pointers.
func (r *Register) GCNum() int16 {
return r.gcNum
}
// A LocalSlot is a location in the stack frame, which identifies and stores // A LocalSlot is a location in the stack frame, which identifies and stores
// part or all of a PPARAM, PPARAMOUT, or PAUTO ONAME node. // part or all of a PPARAM, PPARAMOUT, or PAUTO ONAME node.
// It can represent a whole variable, part of a larger stack slot, or part of a // It can represent a whole variable, part of a larger stack slot, or part of a
......
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