"unsafe"
)
-const regDebug = false // TODO: compiler flag
-const logSpills = false
+const (
+ logSpills = iota
+ regDebug
+ stackDebug
+)
// distance is a measure of how far into the future values are used.
// distance is measured in units of instructions.
}
// Mark r as unused.
- if regDebug {
+ if s.f.pass.debug > regDebug {
fmt.Printf("freeReg %s (dump %s/%s)\n", registers[r].Name(), v, s.regs[r].c)
}
s.regs[r] = regState{}
// assignReg assigns register r to hold c, a copy of v.
// r must be unused.
func (s *regAllocState) assignReg(r register, v *Value, c *Value) {
- if regDebug {
+ if s.f.pass.debug > regDebug {
fmt.Printf("assignReg %s %s/%s\n", registers[r].Name(), v, c)
}
if s.regs[r].v != nil {
switch {
// Load v from its spill location.
case vi.spill != nil:
- if logSpills {
+ if s.f.pass.debug > logSpills {
fmt.Println("regalloc: load spill")
}
c = s.curBlock.NewValue1(line, OpLoadReg, v.Type, vi.spill)
liveSet.add(a.ID)
}
}
- if regDebug {
+ if s.f.pass.debug > regDebug {
fmt.Printf("uses for %s:%s\n", s.f.Name, b)
for i := range s.values {
vi := &s.values[i]
p := b.Preds[idx]
s.setState(s.endRegs[p.ID])
- if regDebug {
+ if s.f.pass.debug > regDebug {
fmt.Printf("starting merge block %s with end state of %s:\n", b, p)
for _, x := range s.endRegs[p.ID] {
fmt.Printf(" %s: orig:%s cache:%s\n", registers[x.r].Name(), x.v, x.c)
}
s.startRegs[b.ID] = regList
- if regDebug {
+ if s.f.pass.debug > regDebug {
fmt.Printf("after phis\n")
for _, x := range s.startRegs[b.ID] {
fmt.Printf(" %s: v%d\n", registers[x.r].Name(), x.vid)
// Process all the non-phi values.
for _, v := range oldSched {
- if regDebug {
+ if s.f.pass.debug > regDebug {
fmt.Printf(" processing %s\n", v.LongString())
}
if v.Op == OpPhi {
// Load control value into reg.
if v := b.Control; v != nil && s.values[v.ID].needReg {
- if regDebug {
+ if s.f.pass.debug > regDebug {
fmt.Printf(" processing control %s\n", v.LongString())
}
// TODO: regspec for block control values, instead of using
for i := range s.values {
vi := s.values[i]
if vi.spillUsed {
- if logSpills {
+ if s.f.pass.debug > logSpills {
fmt.Println("regalloc: spilled value")
}
continue
e.s = s
e.cache = map[ID][]*Value{}
e.contents = map[Location]contentRecord{}
- if regDebug {
+ if s.f.pass.debug > regDebug {
fmt.Printf("shuffle %s\n", s.f.Name)
fmt.Println(s.f.String())
}
// setup initializes the edge state for shuffling.
func (e *edgeState) setup(idx int, srcReg []endReg, dstReg []startReg, stacklive []ID) {
- if regDebug {
+ if e.s.f.pass.debug > regDebug {
fmt.Printf("edge %s->%s\n", e.p, e.b)
}
}
e.destinations = dsts
- if regDebug {
+ if e.s.f.pass.debug > regDebug {
for _, vid := range e.cachedVals {
a := e.cache[vid]
for _, c := range a {
vid := e.contents[loc].vid
c := e.contents[loc].c
r := e.findRegFor(c.Type)
- if regDebug {
+ if e.s.f.pass.debug > regDebug {
fmt.Printf("breaking cycle with v%d in %s:%s\n", vid, loc.Name(), c)
}
if _, isReg := loc.(*Register); isReg {
v := e.s.orig[vid]
var c *Value
var src Location
- if regDebug {
+ if e.s.f.pass.debug > regDebug {
fmt.Printf("moving v%d to %s\n", vid, loc.Name())
fmt.Printf("sources of v%d:", vid)
}
for _, w := range e.cache[vid] {
h := e.s.f.getHome(w.ID)
- if regDebug {
+ if e.s.f.pass.debug > regDebug {
fmt.Printf(" %s:%s", h.Name(), w)
}
_, isreg := h.(*Register)
src = h
}
}
- if regDebug {
+ if e.s.f.pass.debug > regDebug {
if src != nil {
fmt.Printf(" [use %s]\n", src.Name())
} else {
}
}
}
- if regDebug {
+ if e.s.f.pass.debug > regDebug {
fmt.Printf("%s\n", c.LongString())
fmt.Printf("v%d now available in %s:%s\n", vid, loc.Name(), c)
}
a := e.cache[vid]
for i, c := range a {
if e.s.f.getHome(c.ID) == loc {
- if regDebug {
+ if e.s.f.pass.debug > regDebug {
fmt.Printf("v%d no longer available in %s:%s\n", vid, loc.Name(), c)
}
a[i], a = a[len(a)-1], a[:len(a)-1]
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)
- if regDebug {
+ if e.s.f.pass.debug > regDebug {
fmt.Printf(" SPILL %s->%s %s\n", r.Name(), t.Name(), x.LongString())
}
// r will now be overwritten by the caller. At some point
break
}
}
- if regDebug {
+ if f.pass.debug > regDebug {
fmt.Println("live values at end of each block")
for _, b := range f.Blocks {
fmt.Printf(" %s:", b)
import "fmt"
-const stackDebug = false // TODO: compiler flag
-
type stackAllocState struct {
f *Func
values []stackValState
// all Values that did not get a register.
// Returns a map from block ID to the stack values live at the end of that block.
func stackalloc(f *Func, spillLive [][]ID) [][]ID {
- if stackDebug {
+ if f.pass.debug > stackDebug {
fmt.Println("before stackalloc")
fmt.Println(f.String())
}
for _, v := range b.Values {
s.values[v.ID].typ = v.Type
s.values[v.ID].needSlot = !v.Type.IsMemory() && !v.Type.IsVoid() && !v.Type.IsFlags() && f.getHome(v.ID) == nil && !v.rematerializeable()
- if stackDebug && s.values[v.ID].needSlot {
+ if f.pass.debug > stackDebug && s.values[v.ID].needSlot {
fmt.Printf("%s needs a stack slot\n", v)
}
if v.Op == OpStoreReg {
continue
}
loc := LocalSlot{v.Aux.(GCNode), v.Type, v.AuxInt}
- if stackDebug {
+ if f.pass.debug > stackDebug {
fmt.Printf("stackalloc %s to %s\n", v, loc.Name())
}
f.setHome(v, loc)
goto noname
}
}
- if stackDebug {
+ if f.pass.debug > stackDebug {
fmt.Printf("stackalloc %s to %s\n", v, name.Name())
}
f.setHome(v, name)
}
// Use the stack variable at that index for v.
loc := locs[i]
- if stackDebug {
+ if f.pass.debug > stackDebug {
fmt.Printf("stackalloc %s to %s\n", v, loc.Name())
}
f.setHome(v, loc)
break
}
}
- if stackDebug {
+ if s.f.pass.debug > stackDebug {
for _, b := range s.f.Blocks {
fmt.Printf("stacklive %s %v\n", b, s.live[b.ID])
}
}
}
}
- if stackDebug {
+ if f.pass.debug > stackDebug {
for vid, i := range s.interfere {
if len(i) > 0 {
fmt.Printf("v%d interferes with", vid)