aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/compile/internal/ssa/regalloc.go36
1 files changed, 33 insertions, 3 deletions
diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go
index 691530ec0b..7b97c8e097 100644
--- a/src/cmd/compile/internal/ssa/regalloc.go
+++ b/src/cmd/compile/internal/ssa/regalloc.go
@@ -1012,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
@@ -1022,6 +1022,24 @@ func (s *regAllocState) regalloc(f *Func) {
continue
}
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
@@ -1119,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))
}