Fix PR3667
[oota-llvm.git] / lib / CodeGen / VirtRegMap.h
index a7f47deaf274faf404dda4a2f7fec5229c731357..8b494a7c617bc3de183a0b0bc31716b9b59b77dd 100644 (file)
 #define LLVM_CODEGEN_VIRTREGMAP_H
 
 #include "llvm/Target/TargetRegisterInfo.h"
-#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/IndexedMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/Streams.h"
 #include <map>
 
@@ -57,7 +59,7 @@ namespace llvm {
     /// at.
     IndexedMap<int, VirtReg2IndexFunctor> Virt2StackSlotMap;
 
-    /// Virt2StackSlotMap - This is virtual register to rematerialization id
+    /// Virt2ReMatIdMap - This is virtual register to rematerialization id
     /// mapping. Each spilled virtual register that should be remat'd has an
     /// entry in it which corresponds to the remat id.
     IndexedMap<int, VirtReg2IndexFunctor> Virt2ReMatIdMap;
@@ -92,12 +94,33 @@ namespace llvm {
     /// 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
     /// conflicts with stack slot numbers.
     int ReMatId;
 
+    /// LowSpillSlot, HighSpillSlot - Lowest and highest spill slot indexes.
+    int LowSpillSlot, HighSpillSlot;
+
+    /// SpillSlotToUsesMap - Records uses for each register spill slot.
+    SmallVector<SmallPtrSet<MachineInstr*, 4>, 8> SpillSlotToUsesMap;
+
+    /// ImplicitDefed - One bit for each virtual register. If set it indicates
+    /// the register is implicitly defined.
+    BitVector ImplicitDefed;
+
     VirtRegMap(const VirtRegMap&);     // DO NOT IMPLEMENT
     void operator=(const VirtRegMap&); // DO NOT IMPLEMENT
 
@@ -155,7 +178,7 @@ namespace llvm {
       return Virt2SplitMap[virtReg];
     }
 
-    /// @brief returns true is the specified virtual register is not
+    /// @brief returns true if the specified virtual register is not
     /// mapped to a stack slot or rematerialized.
     bool isAssignedReg(unsigned virtReg) const {
       if (getStackSlot(virtReg) == NO_STACK_SLOT &&
@@ -250,6 +273,8 @@ namespace llvm {
       }
     }
 
+    /// @brief - transfer spill point information from one instruction to
+    /// another.
     void transferSpillPts(MachineInstr *Old, MachineInstr *New) {
       std::map<MachineInstr*,std::vector<std::pair<unsigned,bool> > >::iterator
         I = SpillPt2VirtMap.find(Old);
@@ -286,6 +311,8 @@ namespace llvm {
       }
     }
 
+    /// @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);
@@ -299,6 +326,77 @@ namespace llvm {
       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 - transfer emergency spill information from one instruction to
+    /// another.
+    void transferEmergencySpills(MachineInstr *Old, MachineInstr *New) {
+      std::map<MachineInstr*,std::vector<unsigned> >::iterator I =
+        EmergencySpillMap.find(Old);
+      if (I == EmergencySpillMap.end())
+        return;
+      while (!I->second.empty()) {
+        unsigned virtReg = I->second.back();
+        I->second.pop_back();
+        addEmergencySpill(virtReg, New);
+      }
+      EmergencySpillMap.erase(I);
+    }
+
+    /// @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;
+    }
+
+    /// @brief Return highest spill slot index.
+    int getHighSpillSlot() const {
+      return HighSpillSlot;
+    }
+
+    /// @brief Records a spill slot use.
+    void addSpillSlotUse(int FrameIndex, MachineInstr *MI);
+
+    /// @brief Returns true if spill slot has been used.
+    bool isSpillSlotUsed(int FrameIndex) const {
+      assert(FrameIndex >= 0 && "Spill slot index should not be negative!");
+      return !SpillSlotToUsesMap[FrameIndex-LowSpillSlot].empty();
+    }
+
+    /// @brief Mark the specified register as being implicitly defined.
+    void setIsImplicitlyDefined(unsigned VirtReg) {
+      ImplicitDefed.set(VirtReg-TargetRegisterInfo::FirstVirtualRegister);
+    }
+
+    /// @brief Returns true if the virtual register is implicitly defined.
+    bool isImplicitlyDefined(unsigned VirtReg) const {
+      return ImplicitDefed[VirtReg-TargetRegisterInfo::FirstVirtualRegister];
+    }
+
     /// @brief Updates information about the specified virtual register's value
     /// folded into newMI machine instruction.
     void virtFolded(unsigned VirtReg, MachineInstr *OldMI, MachineInstr *NewMI,
@@ -317,11 +415,7 @@ namespace llvm {
     
     /// RemoveMachineInstrFromMaps - MI is being erased, remove it from the
     /// the folded instruction map and spill point map.
-    void RemoveMachineInstrFromMaps(MachineInstr *MI) {
-      MI2VirtMap.erase(MI);
-      SpillPt2VirtMap.erase(MI);
-      RestorePt2VirtMap.erase(MI);
-    }
+    void RemoveMachineInstrFromMaps(MachineInstr *MI);
 
     void print(std::ostream &OS) const;
     void print(std::ostream *OS) const { if (OS) print(*OS); }