#ifndef LLVM_CODEGEN_VIRTREGMAP_H
#define LLVM_CODEGEN_VIRTREGMAP_H
+#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/Target/TargetRegisterInfo.h"
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IndexedMap.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/Support/Streams.h"
-#include <map>
namespace llvm {
class MachineInstr;
class MachineFunction;
+ class MachineRegisterInfo;
class TargetInstrInfo;
+ class raw_ostream;
+ class SlotIndexes;
- class VirtRegMap {
+ class VirtRegMap : public MachineFunctionPass {
public:
enum {
NO_PHYS_REG = 0,
MAX_STACK_SLOT = (1L << 18)-1
};
- enum ModRef { isRef = 1, isMod = 2, isModRef = 3 };
- typedef std::multimap<MachineInstr*,
- std::pair<unsigned, ModRef> > MI2VirtMapTy;
-
private:
- const TargetInstrInfo &TII;
+ MachineRegisterInfo *MRI;
+ const TargetInstrInfo *TII;
+ const TargetRegisterInfo *TRI;
+ MachineFunction *MF;
- MachineFunction &MF;
/// Virt2PhysMap - This is a virtual to physical register
/// mapping. Each virtual register is required to have an entry in
/// it; even spilled virtual registers (the register mapped to a
/// at.
IndexedMap<int, VirtReg2IndexFunctor> Virt2StackSlotMap;
- /// Virt2StackSlotMap - 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;
-
/// Virt2SplitMap - This is virtual register to splitted virtual register
/// mapping.
IndexedMap<unsigned, VirtReg2IndexFunctor> Virt2SplitMap;
- /// Virt2SplitKillMap - This is splitted virtual register to its last use
- /// (kill) index mapping.
- IndexedMap<unsigned> Virt2SplitKillMap;
-
- /// ReMatMap - This is virtual register to re-materialized instruction
- /// mapping. Each virtual register whose definition is going to be
- /// re-materialized has an entry in it.
- IndexedMap<MachineInstr*, VirtReg2IndexFunctor> ReMatMap;
-
- /// MI2VirtMap - This is MachineInstr to virtual register
- /// mapping. In the case of memory spill code being folded into
- /// instructions, we need to know which virtual register was
- /// read/written by this instruction.
- MI2VirtMapTy MI2VirtMap;
-
- /// SpillPt2VirtMap - This records the virtual registers which should
- /// be spilled right after the MachineInstr due to live interval
- /// splitting.
- std::map<MachineInstr*, std::vector<std::pair<unsigned,bool> > >
- SpillPt2VirtMap;
-
- /// RestorePt2VirtMap - This records the virtual registers which should
- /// be restored right before the MachineInstr due to live interval
- /// 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;
+ /// createSpillSlot - Allocate a spill slot for RC from MFI.
+ unsigned createSpillSlot(const TargetRegisterClass *RC);
VirtRegMap(const VirtRegMap&); // DO NOT IMPLEMENT
void operator=(const VirtRegMap&); // DO NOT IMPLEMENT
public:
- explicit VirtRegMap(MachineFunction &mf);
+ static char ID;
+ VirtRegMap() : MachineFunctionPass(ID), Virt2PhysMap(NO_PHYS_REG),
+ Virt2StackSlotMap(NO_STACK_SLOT), Virt2SplitMap(0) { }
+ virtual bool runOnMachineFunction(MachineFunction &MF);
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
+
+ MachineFunction &getMachineFunction() const {
+ assert(MF && "getMachineFunction called before runOnMachineFunction");
+ return *MF;
+ }
+
+ MachineRegisterInfo &getRegInfo() const { return *MRI; }
+ const TargetRegisterInfo &getTargetRegInfo() const { return *TRI; }
void grow();
grow();
}
+ /// @brief returns the register allocation preference.
+ unsigned getRegAllocPref(unsigned virtReg);
+
+ /// @brief returns true if VirtReg is assigned to its preferred physreg.
+ bool hasPreferredPhys(unsigned VirtReg) {
+ return getPhys(VirtReg) == getRegAllocPref(VirtReg);
+ }
+
/// @brief records virtReg is a split live interval from SReg.
void setIsSplitFromReg(unsigned virtReg, unsigned SReg) {
Virt2SplitMap[virtReg] = SReg;
}
/// @brief returns the live interval virtReg is split from.
- unsigned getPreSplitReg(unsigned virtReg) {
+ unsigned getPreSplitReg(unsigned virtReg) const {
return Virt2SplitMap[virtReg];
}
- /// @brief returns true is the specified virtual register is not
+ /// getOriginal - Return the original virtual register that VirtReg descends
+ /// from through splitting.
+ /// A register that was not created by splitting is its own original.
+ /// This operation is idempotent.
+ unsigned getOriginal(unsigned VirtReg) const {
+ unsigned Orig = getPreSplitReg(VirtReg);
+ return Orig ? Orig : VirtReg;
+ }
+
+ /// @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 &&
- getReMatId(virtReg) == NO_STACK_SLOT)
+ if (getStackSlot(virtReg) == NO_STACK_SLOT)
return true;
// Split register can be assigned a physical register as well as a
// stack slot or remat id.
return Virt2StackSlotMap[virtReg];
}
- /// @brief returns the rematerialization id mapped to the specified virtual
- /// register
- int getReMatId(unsigned virtReg) const {
- assert(TargetRegisterInfo::isVirtualRegister(virtReg));
- return Virt2ReMatIdMap[virtReg];
- }
-
/// @brief create a mapping for the specifed virtual register to
/// the next available stack slot
int assignVirt2StackSlot(unsigned virtReg);
/// the specified stack slot
void assignVirt2StackSlot(unsigned virtReg, int frameIndex);
- /// @brief assign an unique re-materialization id to the specified
- /// virtual register.
- int assignVirtReMatId(unsigned virtReg);
- /// @brief assign an unique re-materialization id to the specified
- /// virtual register.
- void assignVirtReMatId(unsigned virtReg, int id);
-
- /// @brief returns true if the specified virtual register is being
- /// re-materialized.
- bool isReMaterialized(unsigned virtReg) const {
- return ReMatMap[virtReg] != NULL;
- }
-
- /// @brief returns the original machine instruction being re-issued
- /// to re-materialize the specified virtual register.
- MachineInstr *getReMaterializedMI(unsigned virtReg) const {
- return ReMatMap[virtReg];
- }
-
- /// @brief records the specified virtual register will be
- /// re-materialized and the original instruction which will be re-issed
- /// for this purpose. If parameter all is true, then all uses of the
- /// registers are rematerialized and it's safe to delete the definition.
- void setVirtIsReMaterialized(unsigned virtReg, MachineInstr *def) {
- ReMatMap[virtReg] = def;
- }
-
- /// @brief record the last use (kill) of a split virtual register.
- void addKillPoint(unsigned virtReg, unsigned index) {
- Virt2SplitKillMap[virtReg] = index;
- }
-
- unsigned getKillPoint(unsigned virtReg) const {
- return Virt2SplitKillMap[virtReg];
- }
-
- /// @brief remove the last use (kill) of a split virtual register.
- void removeKillPoint(unsigned virtReg) {
- Virt2SplitKillMap[virtReg] = 0;
- }
-
- /// @brief returns true if the specified MachineInstr is a spill point.
- bool isSpillPt(MachineInstr *Pt) const {
- return SpillPt2VirtMap.find(Pt) != SpillPt2VirtMap.end();
- }
-
- /// @brief returns the virtual registers that should be spilled due to
- /// splitting right after the specified MachineInstr.
- std::vector<std::pair<unsigned,bool> > &getSpillPtSpills(MachineInstr *Pt) {
- return SpillPt2VirtMap[Pt];
- }
-
- /// @brief records the specified MachineInstr as a spill point for virtReg.
- void addSpillPoint(unsigned virtReg, bool isKill, MachineInstr *Pt) {
- if (SpillPt2VirtMap.find(Pt) != SpillPt2VirtMap.end())
- SpillPt2VirtMap[Pt].push_back(std::make_pair(virtReg, isKill));
- else {
- std::vector<std::pair<unsigned,bool> > Virts;
- Virts.push_back(std::make_pair(virtReg, isKill));
- SpillPt2VirtMap.insert(std::make_pair(Pt, Virts));
- }
- }
-
- void transferSpillPts(MachineInstr *Old, MachineInstr *New) {
- std::map<MachineInstr*,std::vector<std::pair<unsigned,bool> > >::iterator
- I = SpillPt2VirtMap.find(Old);
- if (I == SpillPt2VirtMap.end())
- return;
- while (!I->second.empty()) {
- unsigned virtReg = I->second.back().first;
- bool isKill = I->second.back().second;
- I->second.pop_back();
- addSpillPoint(virtReg, isKill, New);
- }
- SpillPt2VirtMap.erase(I);
- }
-
- /// @brief returns true if the specified MachineInstr is a restore point.
- bool isRestorePt(MachineInstr *Pt) const {
- return RestorePt2VirtMap.find(Pt) != RestorePt2VirtMap.end();
- }
-
- /// @brief returns the virtual registers that should be restoreed due to
- /// splitting right after the specified MachineInstr.
- std::vector<unsigned> &getRestorePtRestores(MachineInstr *Pt) {
- return RestorePt2VirtMap[Pt];
- }
-
- /// @brief records the specified MachineInstr as a restore point for virtReg.
- void addRestorePoint(unsigned virtReg, MachineInstr *Pt) {
- if (RestorePt2VirtMap.find(Pt) != RestorePt2VirtMap.end())
- RestorePt2VirtMap[Pt].push_back(virtReg);
- else {
- std::vector<unsigned> Virts;
- Virts.push_back(virtReg);
- RestorePt2VirtMap.insert(std::make_pair(Pt, Virts));
- }
- }
-
- /// @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);
- if (I == RestorePt2VirtMap.end())
- return;
- while (!I->second.empty()) {
- unsigned virtReg = I->second.back();
- I->second.pop_back();
- addRestorePoint(virtReg, New);
- }
- 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;
- }
-
- /// @brief Return highest spill slot index.
- int getHighSpillSlot() const {
- return HighSpillSlot;
- }
+ /// rewrite - Rewrite all instructions in MF to use only physical registers
+ /// by mapping all virtual register operands to their assigned physical
+ /// registers.
+ ///
+ /// @param Indexes Optionally remove deleted instructions from indexes.
+ void rewrite(SlotIndexes *Indexes);
- /// @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 Updates information about the specified virtual register's value
- /// folded into newMI machine instruction.
- void virtFolded(unsigned VirtReg, MachineInstr *OldMI, MachineInstr *NewMI,
- ModRef MRInfo);
-
- /// @brief Updates information about the specified virtual register's value
- /// folded into the specified machine instruction.
- void virtFolded(unsigned VirtReg, MachineInstr *MI, ModRef MRInfo);
-
- /// @brief returns the virtual registers' values folded in memory
- /// operands of this instruction
- std::pair<MI2VirtMapTy::const_iterator, MI2VirtMapTy::const_iterator>
- getFoldedVirts(MachineInstr* MI) const {
- return MI2VirtMap.equal_range(MI);
- }
-
- /// RemoveMachineInstrFromMaps - MI is being erased, remove it from the
- /// the folded instruction map and spill point map.
- void RemoveMachineInstrFromMaps(MachineInstr *MI);
-
- void print(std::ostream &OS) const;
- void print(std::ostream *OS) const { if (OS) print(*OS); }
+ void print(raw_ostream &OS, const Module* M = 0) const;
void dump() const;
};
- inline std::ostream *operator<<(std::ostream *OS, const VirtRegMap &VRM) {
- VRM.print(OS);
- return OS;
- }
- inline std::ostream &operator<<(std::ostream &OS, const VirtRegMap &VRM) {
+ inline raw_ostream &operator<<(raw_ostream &OS, const VirtRegMap &VRM) {
VRM.print(OS);
return OS;
}
-
- /// Spiller interface: Implementations of this interface assign spilled
- /// virtual registers to stack slots, rewriting the code.
- struct Spiller {
- virtual ~Spiller();
- virtual bool runOnMachineFunction(MachineFunction &MF,
- VirtRegMap &VRM) = 0;
- };
-
- /// createSpiller - Create an return a spiller object, as specified on the
- /// command line.
- Spiller* createSpiller();
-
} // End llvm namespace
#endif