aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/ssa/regalloc.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/ssa/regalloc.go')
-rw-r--r--src/cmd/compile/internal/ssa/regalloc.go69
1 files changed, 50 insertions, 19 deletions
diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go
index 64c6aed3e7..0339b073ae 100644
--- a/src/cmd/compile/internal/ssa/regalloc.go
+++ b/src/cmd/compile/internal/ssa/regalloc.go
@@ -625,9 +625,6 @@ func (s *regAllocState) init(f *Func) {
s.f.fe.Fatalf(src.NoXPos, "arch %s not implemented", s.f.Config.arch)
}
}
- if s.f.Config.use387 {
- s.allocatable &^= 1 << 15 // X7 disallowed (one 387 register is used as scratch space during SSE->387 generation in ../x86/387.go)
- }
// Linear scan register allocation can be influenced by the order in which blocks appear.
// Decouple the register allocation order from the generated block order.
@@ -1015,8 +1012,8 @@ func (s *regAllocState) regalloc(f *Func) {
// Copy phi ops into new schedule.
b.Values = append(b.Values, phis...)
- // Third pass - pick registers for phis whose inputs
- // were not in a register.
+ // Third pass - pick registers for phis whose input
+ // was not in a register in the primary predecessor.
for i, v := range phis {
if !s.values[v.ID].needReg {
continue
@@ -1024,10 +1021,25 @@ func (s *regAllocState) regalloc(f *Func) {
if phiRegs[i] != noRegister {
continue
}
- if s.f.Config.use387 && v.Type.IsFloat() {
- continue // 387 can't handle floats in registers between blocks
- }
m := s.compatRegs(v.Type) &^ phiUsed &^ s.used
+ // If one of the other inputs of v is in a register, and the register is available,
+ // select this register, which can save some unnecessary copies.
+ for i, pe := range b.Preds {
+ if int32(i) == idx {
+ continue
+ }
+ ri := noRegister
+ for _, er := range s.endRegs[pe.b.ID] {
+ if er.v == s.orig[v.Args[i].ID] {
+ ri = er.r
+ break
+ }
+ }
+ if ri != noRegister && m>>ri&1 != 0 {
+ m = regMask(1) << ri
+ break
+ }
+ }
if m != 0 {
r := pickReg(m)
phiRegs[i] = r
@@ -1125,7 +1137,19 @@ func (s *regAllocState) regalloc(f *Func) {
}
rp, ok := s.f.getHome(v.ID).(*Register)
if !ok {
- continue
+ // If v is not assigned a register, pick a register assigned to one of v's inputs.
+ // Hopefully v will get assigned that register later.
+ // If the inputs have allocated register information, add it to desired,
+ // which may reduce spill or copy operations when the register is available.
+ for _, a := range v.Args {
+ rp, ok = s.f.getHome(a.ID).(*Register)
+ if ok {
+ break
+ }
+ }
+ if !ok {
+ continue
+ }
}
desired.add(v.Args[pidx].ID, register(rp.num))
}
@@ -1528,11 +1552,6 @@ func (s *regAllocState) regalloc(f *Func) {
s.freeUseRecords = u
}
- // Spill any values that can't live across basic block boundaries.
- if s.f.Config.use387 {
- s.freeRegs(s.f.Config.fpRegMask)
- }
-
// If we are approaching a merge point and we are the primary
// predecessor of it, find live values that we use soon after
// the merge point and promote them to registers now.
@@ -1562,10 +1581,20 @@ func (s *regAllocState) regalloc(f *Func) {
continue
}
v := s.orig[vid]
- if s.f.Config.use387 && v.Type.IsFloat() {
- continue // 387 can't handle floats in registers between blocks
- }
m := s.compatRegs(v.Type) &^ s.used
+ // Used desired register if available.
+ outerloop:
+ for _, e := range desired.entries {
+ if e.ID != v.ID {
+ continue
+ }
+ for _, r := range e.regs {
+ if r != noRegister && m>>r&1 != 0 {
+ m = regMask(1) << r
+ break outerloop
+ }
+ }
+ }
if m&^desired.avoid != 0 {
m &^= desired.avoid
}
@@ -1627,7 +1656,9 @@ func (s *regAllocState) regalloc(f *Func) {
// we'll rematerialize during the merge.
continue
}
- //fmt.Printf("live-at-end spill for %s at %s\n", s.orig[e.ID], b)
+ if s.f.pass.debug > regDebug {
+ fmt.Printf("live-at-end spill for %s at %s\n", s.orig[e.ID], b)
+ }
spill := s.makeSpill(s.orig[e.ID], b)
s.spillLive[b.ID] = append(s.spillLive[b.ID], spill.ID)
}
@@ -2498,7 +2529,7 @@ func (s *regAllocState) computeLive() {
for _, b := range f.Blocks {
fmt.Printf(" %s:", b)
for _, x := range s.live[b.ID] {
- fmt.Printf(" v%d", x.ID)
+ fmt.Printf(" v%d(%d)", x.ID, x.dist)
for _, e := range s.desired[b.ID].entries {
if e.ID != x.ID {
continue