@@ -869,7 +869,6 @@ func (s *regAllocState) regalloc(f *Func) {
869
869
m := s .values [a .ID ].regs &^ phiUsed & s .allocatable
870
870
if m != 0 {
871
871
r := pickReg (m )
872
- s .freeReg (r )
873
872
phiUsed |= regMask (1 ) << r
874
873
phiRegs = append (phiRegs , r )
875
874
} else {
@@ -878,7 +877,7 @@ func (s *regAllocState) regalloc(f *Func) {
878
877
}
879
878
880
879
// Second pass - deallocate any phi inputs which are now dead.
881
- for _ , v := range phis {
880
+ for i , v := range phis {
882
881
if ! s .values [v .ID ].needReg {
883
882
continue
884
883
}
@@ -887,6 +886,31 @@ func (s *regAllocState) regalloc(f *Func) {
887
886
// Input is dead beyond the phi, deallocate
888
887
// anywhere else it might live.
889
888
s .freeRegs (s .values [a .ID ].regs )
889
+ } else {
890
+ // Input is still live.
891
+ // Try to move it around before kicking out, if there is a free register.
892
+ // We generate a Copy in the predecessor block and record it. It will be
893
+ // deleted if never used.
894
+ r := phiRegs [i ]
895
+ if r == noRegister {
896
+ continue
897
+ }
898
+ // Pick a free register. At this point some registers used in the predecessor
899
+ // block may have been deallocated. Those are the ones used for Phis. Exclude
900
+ // them (and they are not going to be helpful anyway).
901
+ m := s .compatRegs (a .Type ) &^ s .used &^ phiUsed
902
+ if m != 0 && ! s .values [a .ID ].rematerializeable && countRegs (s .values [a .ID ].regs ) == 1 {
903
+ r2 := pickReg (m )
904
+ c := p .NewValue1 (a .Line , OpCopy , a .Type , s .regs [r ].c )
905
+ s .copies [c ] = false
906
+ if s .f .pass .debug > regDebug {
907
+ fmt .Printf ("copy %s to %s : %s\n " , a , c , s .registers [r2 ].Name ())
908
+ }
909
+ s .setOrig (c , a )
910
+ s .assignReg (r2 , a , c )
911
+ s .endRegs [p .ID ] = append (s .endRegs [p .ID ], endReg {r2 , a , c })
912
+ }
913
+ s .freeReg (r )
890
914
}
891
915
}
892
916
0 commit comments