diff options
Diffstat (limited to 'src/cmd/compile/internal/ssa/regalloc.go')
-rw-r--r-- | src/cmd/compile/internal/ssa/regalloc.go | 69 |
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 |