When the register allocator runs out of registers, spill a physical register around the def's and use's of the interval being allocated to make it possible for the interval to target a register and spill it right away and restore a register for uses. This likely generates terrible code but is before than aborting.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48218 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp
index d710d48..7931804 100644
--- a/lib/CodeGen/LiveIntervalAnalysis.cpp
+++ b/lib/CodeGen/LiveIntervalAnalysis.cpp
@@ -1620,3 +1620,81 @@
 
   return RetNewLIs;
 }
+
+/// hasAllocatableSuperReg - Return true if the specified physical register has
+/// any super register that's allocatable.
+bool LiveIntervals::hasAllocatableSuperReg(unsigned Reg) const {
+  for (const unsigned* AS = tri_->getSuperRegisters(Reg); *AS; ++AS)
+    if (allocatableRegs_[*AS] && hasInterval(*AS))
+      return true;
+  return false;
+}
+
+/// getRepresentativeReg - Find the largest super register of the specified
+/// physical register.
+unsigned LiveIntervals::getRepresentativeReg(unsigned Reg) const {
+  // Find the largest super-register that is allocatable. 
+  unsigned BestReg = Reg;
+  for (const unsigned* AS = tri_->getSuperRegisters(Reg); *AS; ++AS) {
+    unsigned SuperReg = *AS;
+    if (!hasAllocatableSuperReg(SuperReg) && hasInterval(SuperReg)) {
+      BestReg = SuperReg;
+      break;
+    }
+  }
+  return BestReg;
+}
+
+/// getNumConflictsWithPhysReg - Return the number of uses and defs of the
+/// specified interval that conflicts with the specified physical register.
+unsigned LiveIntervals::getNumConflictsWithPhysReg(const LiveInterval &li,
+                                                   unsigned PhysReg) const {
+  unsigned NumConflicts = 0;
+  const LiveInterval &pli = getInterval(getRepresentativeReg(PhysReg));
+  for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(li.reg),
+         E = mri_->reg_end(); I != E; ++I) {
+    MachineOperand &O = I.getOperand();
+    MachineInstr *MI = O.getParent();
+    unsigned Index = getInstructionIndex(MI);
+    if (pli.liveAt(Index))
+      ++NumConflicts;
+  }
+  return NumConflicts;
+}
+
+/// spillPhysRegAroundRegDefsUses - Spill the specified physical register
+/// around all defs and uses of the specified interval.
+void LiveIntervals::spillPhysRegAroundRegDefsUses(const LiveInterval &li,
+                                            unsigned PhysReg, VirtRegMap &vrm) {
+  unsigned SpillReg = getRepresentativeReg(PhysReg);
+
+  for (const unsigned *AS = tri_->getAliasSet(PhysReg); *AS; ++AS)
+    // If there are registers which alias PhysReg, but which are not a
+    // sub-register of the chosen representative super register. Assert
+    // since we can't handle it yet.
+    assert(*AS == SpillReg || !allocatableRegs_[*AS] ||
+           tri_->isSuperRegister(*AS, SpillReg));
+
+  LiveInterval &pli = getInterval(SpillReg);
+  SmallPtrSet<MachineInstr*, 8> SeenMIs;
+  for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(li.reg),
+         E = mri_->reg_end(); I != E; ++I) {
+    MachineOperand &O = I.getOperand();
+    MachineInstr *MI = O.getParent();
+    if (SeenMIs.count(MI))
+      continue;
+    SeenMIs.insert(MI);
+    unsigned Index = getInstructionIndex(MI);
+    if (pli.liveAt(Index)) {
+      vrm.addEmergencySpill(SpillReg, MI);
+      pli.removeRange(getLoadIndex(Index), getStoreIndex(Index)+1);
+      for (const unsigned* AS = tri_->getSubRegisters(SpillReg); *AS; ++AS) {
+        if (!hasInterval(*AS))
+          continue;
+        LiveInterval &spli = getInterval(*AS);
+        if (spli.liveAt(Index))
+          spli.removeRange(getLoadIndex(Index), getStoreIndex(Index)+1);
+      }
+    }
+  }
+}
diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp
index d43cc19..12e7d6a 100644
--- a/lib/CodeGen/RegAllocLinearScan.cpp
+++ b/lib/CodeGen/RegAllocLinearScan.cpp
@@ -561,6 +561,7 @@
   // is very bad (it contains all callee clobbered registers for any functions
   // with a call), so we want to avoid doing that if possible.
   unsigned physReg = getFreePhysReg(cur);
+  unsigned BestPhysReg = physReg;
   if (physReg) {
     // We got a register.  However, if it's in the fixed_ list, we might
     // conflict with it.  Check to see if we conflict with it or any of its
@@ -685,8 +686,27 @@
     }
 
     // All registers must have inf weight. Just grab one!
-    if (!minReg)
-      minReg = *RC->allocation_order_begin(*mf_);
+    if (!minReg) {
+      if (BestPhysReg)
+        minReg = BestPhysReg;
+      else {
+        // Get the physical register with the fewest conflicts.
+        unsigned MinConflicts = ~0U;
+        for (TargetRegisterClass::iterator i = RC->allocation_order_begin(*mf_),
+               e = RC->allocation_order_end(*mf_); i != e; ++i) {
+          unsigned reg = *i;
+          unsigned NumConflicts = li_->getNumConflictsWithPhysReg(*cur, reg);
+          if (NumConflicts <= MinConflicts) {
+            MinConflicts = NumConflicts;
+            minReg = reg;
+          }
+        }
+      }
+
+      if (cur->weight == HUGE_VALF || cur->getSize() == 1)
+        // Spill a physical register around defs and uses.
+        li_->spillPhysRegAroundRegDefsUses(*cur, minReg, *vrm_);
+    }
   }
   
   DOUT << "\t\tregister with min weight: "
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp
index 032ef5e..c042acb 100644
--- a/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp
@@ -61,7 +61,7 @@
         II.ImplicitDefs[ResNo - II.getNumDefs()] == Reg) {
       PhysReg = Reg;
       const TargetRegisterClass *RC =
-        TRI->getPhysicalRegisterRegClass(Def->getValueType(ResNo), Reg);
+        TRI->getPhysicalRegisterRegClass(Reg, Def->getValueType(ResNo));
       Cost = RC->getCopyCost();
     }
   }
@@ -433,7 +433,7 @@
   }
 
   const TargetRegisterClass *SrcRC = 0, *DstRC = 0;
-  SrcRC = TRI->getPhysicalRegisterRegClass(Node->getValueType(ResNo), SrcReg);
+  SrcRC = TRI->getPhysicalRegisterRegClass(SrcReg, Node->getValueType(ResNo));
   
   // Figure out the register class to create for the destreg.
   if (VRBase) {
@@ -862,14 +862,13 @@
       if (TargetRegisterInfo::isVirtualRegister(SrcReg))
         SrcTRC = RegInfo.getRegClass(SrcReg);
       else
-        SrcTRC = TRI->getPhysicalRegisterRegClass(SrcVal.getValueType(),SrcReg);
+        SrcTRC = TRI->getPhysicalRegisterRegClass(SrcReg,SrcVal.getValueType());
 
       if (TargetRegisterInfo::isVirtualRegister(DestReg))
         DstTRC = RegInfo.getRegClass(DestReg);
       else
-        DstTRC = TRI->getPhysicalRegisterRegClass(
-                                            Node->getOperand(1).getValueType(),
-                                                  DestReg);
+        DstTRC = TRI->getPhysicalRegisterRegClass(DestReg,
+                                            Node->getOperand(1).getValueType());
       TII->copyRegToReg(*BB, BB->end(), DestReg, SrcReg, DstTRC, SrcTRC);
       break;
     }
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
index df57f74..0d3926f 100644
--- a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
+++ b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
@@ -768,7 +768,7 @@
           // Issue expensive cross register class copies.
           MVT::ValueType VT = getPhysicalRegisterVT(LRDef->Node, Reg, TII);
           const TargetRegisterClass *RC =
-            TRI->getPhysicalRegisterRegClass(VT, Reg);
+            TRI->getPhysicalRegisterRegClass(Reg, VT);
           const TargetRegisterClass *DestRC = TRI->getCrossCopyRegClass(RC);
           if (!DestRC) {
             assert(false && "Don't know how to copy this physical register!");
diff --git a/lib/CodeGen/VirtRegMap.cpp b/lib/CodeGen/VirtRegMap.cpp
index c39ac61..cce36e5 100644
--- a/lib/CodeGen/VirtRegMap.cpp
+++ b/lib/CodeGen/VirtRegMap.cpp
@@ -125,6 +125,21 @@
   Virt2ReMatIdMap[virtReg] = id;
 }
 
+int VirtRegMap::getEmergencySpillSlot(const TargetRegisterClass *RC) {
+  std::map<const TargetRegisterClass*, int>::iterator I =
+    EmergencySpillSlots.find(RC);
+  if (I != EmergencySpillSlots.end())
+    return I->second;
+  int SS = MF.getFrameInfo()->CreateStackObject(RC->getSize(),
+                                                RC->getAlignment());
+  if (LowSpillSlot == NO_STACK_SLOT)
+    LowSpillSlot = SS;
+  if (HighSpillSlot == NO_STACK_SLOT || SS > HighSpillSlot)
+    HighSpillSlot = SS;
+  I->second = SS;
+  return SS;
+}
+
 void VirtRegMap::addSpillSlotUse(int FI, MachineInstr *MI) {
   if (!MF.getFrameInfo()->isFixedObjectIndex(FI)) {
     assert(FI >= 0 && "Spill slot index should not be negative!");
@@ -164,6 +179,7 @@
   MI2VirtMap.erase(MI);
   SpillPt2VirtMap.erase(MI);
   RestorePt2VirtMap.erase(MI);
+  EmergencySpillMap.erase(MI);
 }
 
 void VirtRegMap::print(std::ostream &OS) const {
@@ -1043,6 +1059,30 @@
     MachineInstr &MI = *MII;
     const TargetInstrDesc &TID = MI.getDesc();
 
+    if (VRM.hasEmergencySpills(&MI)) {
+      // Spill physical register(s) in the rare case the allocator has run out
+      // of registers to allocate.
+      SmallSet<int, 4> UsedSS;
+      std::vector<unsigned> &EmSpills = VRM.getEmergencySpills(&MI);
+      for (unsigned i = 0, e = EmSpills.size(); i != e; ++i) {
+        unsigned PhysReg = EmSpills[i];
+        const TargetRegisterClass *RC =
+          TRI->getPhysicalRegisterRegClass(PhysReg);
+        assert(RC && "Unable to determine register class!");
+        int SS = VRM.getEmergencySpillSlot(RC);
+        if (UsedSS.count(SS))
+          assert(0 && "Need to spill more than one physical registers!");
+        UsedSS.insert(SS);
+        TII->storeRegToStackSlot(MBB, MII, PhysReg, true, SS, RC);
+        MachineInstr *StoreMI = prior(MII);
+        VRM.addSpillSlotUse(SS, StoreMI);
+        TII->loadRegFromStackSlot(MBB, next(MII), PhysReg, SS, RC);
+        MachineInstr *LoadMI = next(MII);
+        VRM.addSpillSlotUse(SS, LoadMI);
+        ++NumSpills;
+      }
+    }
+
     // Insert restores here if asked to.
     if (VRM.isRestorePt(&MI)) {
       std::vector<unsigned> &RestoreRegs = VRM.getRestorePtRestores(&MI);
diff --git a/lib/CodeGen/VirtRegMap.h b/lib/CodeGen/VirtRegMap.h
index d1c14f6..7ebf31e 100644
--- a/lib/CodeGen/VirtRegMap.h
+++ b/lib/CodeGen/VirtRegMap.h
@@ -93,6 +93,17 @@
     /// splitting.
     std::map<MachineInstr*, std::vector<unsigned> > RestorePt2VirtMap;
 
+    /// EmergencySpillMap - This records the physical registers that should
+    /// be spilled / restored around the MachineInstr since the register
+    /// allocator has run out of registers.
+    std::map<MachineInstr*, std::vector<unsigned> > EmergencySpillMap;
+
+    /// EmergencySpillSlots - This records emergency spill slots used to
+    /// spill physical registers when the register allocator runs out of
+    /// registers. Ideally only one stack slot is used per function per
+    /// register class.
+    std::map<const TargetRegisterClass*, int> EmergencySpillSlots;
+
     /// ReMatId - Instead of assigning a stack slot to a to be rematerialized
     /// virtual register, an unique id is being assigned. This keeps track of
     /// the highest id used so far. Note, this starts at (1<<18) to avoid
@@ -293,6 +304,8 @@
       }
     }
 
+    /// @brief - transfer restore point information from one instruction to
+    /// another.
     void transferRestorePts(MachineInstr *Old, MachineInstr *New) {
       std::map<MachineInstr*,std::vector<unsigned> >::iterator I =
         RestorePt2VirtMap.find(Old);
@@ -306,6 +319,33 @@
       RestorePt2VirtMap.erase(I);
     }
 
+    /// @brief records that the specified physical register must be spilled
+    /// around the specified machine instr.
+    void addEmergencySpill(unsigned PhysReg, MachineInstr *MI) {
+      if (EmergencySpillMap.find(MI) != EmergencySpillMap.end())
+        EmergencySpillMap[MI].push_back(PhysReg);
+      else {
+        std::vector<unsigned> PhysRegs;
+        PhysRegs.push_back(PhysReg);
+        EmergencySpillMap.insert(std::make_pair(MI, PhysRegs));
+      }
+    }
+
+    /// @brief returns true if one or more physical registers must be spilled
+    /// around the specified instruction.
+    bool hasEmergencySpills(MachineInstr *MI) const {
+      return EmergencySpillMap.find(MI) != EmergencySpillMap.end();
+    }
+
+    /// @brief returns the physical registers to be spilled and restored around
+    /// the instruction.
+    std::vector<unsigned> &getEmergencySpills(MachineInstr *MI) {
+      return EmergencySpillMap[MI];
+    }
+
+    /// @brief return or get a emergency spill slot for the register class.
+    int getEmergencySpillSlot(const TargetRegisterClass *RC);
+
     /// @brief Return lowest spill slot index.
     int getLowSpillSlot() const {
       return LowSpillSlot;