mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-15 22:28:18 +00:00
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
This commit is contained in:
@@ -282,11 +282,25 @@ namespace llvm {
|
|||||||
addIntervalsForSpills(const LiveInterval& i,
|
addIntervalsForSpills(const LiveInterval& i,
|
||||||
const MachineLoopInfo *loopInfo, VirtRegMap& vrm);
|
const MachineLoopInfo *loopInfo, VirtRegMap& vrm);
|
||||||
|
|
||||||
|
/// spillPhysRegAroundRegDefsUses - Spill the specified physical register
|
||||||
|
/// around all defs and uses of the specified interval.
|
||||||
|
void spillPhysRegAroundRegDefsUses(const LiveInterval &li,
|
||||||
|
unsigned PhysReg, VirtRegMap &vrm);
|
||||||
|
|
||||||
/// isReMaterializable - Returns true if every definition of MI of every
|
/// isReMaterializable - Returns true if every definition of MI of every
|
||||||
/// val# of the specified interval is re-materializable. Also returns true
|
/// val# of the specified interval is re-materializable. Also returns true
|
||||||
/// by reference if all of the defs are load instructions.
|
/// by reference if all of the defs are load instructions.
|
||||||
bool isReMaterializable(const LiveInterval &li, bool &isLoad);
|
bool isReMaterializable(const LiveInterval &li, bool &isLoad);
|
||||||
|
|
||||||
|
/// getRepresentativeReg - Find the largest super register of the specified
|
||||||
|
/// physical register.
|
||||||
|
unsigned getRepresentativeReg(unsigned Reg) const;
|
||||||
|
|
||||||
|
/// getNumConflictsWithPhysReg - Return the number of uses and defs of the
|
||||||
|
/// specified interval that conflicts with the specified physical register.
|
||||||
|
unsigned getNumConflictsWithPhysReg(const LiveInterval &li,
|
||||||
|
unsigned PhysReg) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// computeIntervals - Compute live intervals.
|
/// computeIntervals - Compute live intervals.
|
||||||
void computeIntervals();
|
void computeIntervals();
|
||||||
@@ -360,6 +374,10 @@ namespace llvm {
|
|||||||
/// within a single basic block.
|
/// within a single basic block.
|
||||||
bool intervalIsInOneMBB(const LiveInterval &li) const;
|
bool intervalIsInOneMBB(const LiveInterval &li) const;
|
||||||
|
|
||||||
|
/// hasAllocatableSuperReg - Return true if the specified physical register
|
||||||
|
/// has any super register that's allocatable.
|
||||||
|
bool hasAllocatableSuperReg(unsigned Reg) const;
|
||||||
|
|
||||||
/// SRInfo - Spill / restore info.
|
/// SRInfo - Spill / restore info.
|
||||||
struct SRInfo {
|
struct SRInfo {
|
||||||
int index;
|
int index;
|
||||||
|
@@ -321,9 +321,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// getPhysicalRegisterRegClass - Returns the Register Class of a physical
|
/// getPhysicalRegisterRegClass - Returns the Register Class of a physical
|
||||||
/// register of the given type.
|
/// register of the given type. If type is MVT::Other, then just return any
|
||||||
const TargetRegisterClass *getPhysicalRegisterRegClass(MVT::ValueType VT,
|
/// register class the register belongs to.
|
||||||
unsigned Reg) const;
|
const TargetRegisterClass *getPhysicalRegisterRegClass(unsigned Reg,
|
||||||
|
MVT::ValueType VT = MVT::Other) const;
|
||||||
|
|
||||||
/// getAllocatableSet - Returns a bitset indexed by register number
|
/// getAllocatableSet - Returns a bitset indexed by register number
|
||||||
/// indicating if a register is allocatable or not. If a register class is
|
/// indicating if a register is allocatable or not. If a register class is
|
||||||
|
@@ -1620,3 +1620,81 @@ addIntervalsForSpills(const LiveInterval &li,
|
|||||||
|
|
||||||
return RetNewLIs;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -561,6 +561,7 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur)
|
|||||||
// is very bad (it contains all callee clobbered registers for any functions
|
// is very bad (it contains all callee clobbered registers for any functions
|
||||||
// with a call), so we want to avoid doing that if possible.
|
// with a call), so we want to avoid doing that if possible.
|
||||||
unsigned physReg = getFreePhysReg(cur);
|
unsigned physReg = getFreePhysReg(cur);
|
||||||
|
unsigned BestPhysReg = physReg;
|
||||||
if (physReg) {
|
if (physReg) {
|
||||||
// We got a register. However, if it's in the fixed_ list, we might
|
// 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
|
// conflict with it. Check to see if we conflict with it or any of its
|
||||||
@@ -685,8 +686,27 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// All registers must have inf weight. Just grab one!
|
// All registers must have inf weight. Just grab one!
|
||||||
if (!minReg)
|
if (!minReg) {
|
||||||
minReg = *RC->allocation_order_begin(*mf_);
|
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: "
|
DOUT << "\t\tregister with min weight: "
|
||||||
|
@@ -61,7 +61,7 @@ static void CheckForPhysRegDependency(SDNode *Def, SDNode *Use, unsigned Op,
|
|||||||
II.ImplicitDefs[ResNo - II.getNumDefs()] == Reg) {
|
II.ImplicitDefs[ResNo - II.getNumDefs()] == Reg) {
|
||||||
PhysReg = Reg;
|
PhysReg = Reg;
|
||||||
const TargetRegisterClass *RC =
|
const TargetRegisterClass *RC =
|
||||||
TRI->getPhysicalRegisterRegClass(Def->getValueType(ResNo), Reg);
|
TRI->getPhysicalRegisterRegClass(Reg, Def->getValueType(ResNo));
|
||||||
Cost = RC->getCopyCost();
|
Cost = RC->getCopyCost();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -433,7 +433,7 @@ void ScheduleDAG::EmitCopyFromReg(SDNode *Node, unsigned ResNo,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const TargetRegisterClass *SrcRC = 0, *DstRC = 0;
|
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.
|
// Figure out the register class to create for the destreg.
|
||||||
if (VRBase) {
|
if (VRBase) {
|
||||||
@@ -862,14 +862,13 @@ void ScheduleDAG::EmitNode(SDNode *Node, unsigned InstanceNo,
|
|||||||
if (TargetRegisterInfo::isVirtualRegister(SrcReg))
|
if (TargetRegisterInfo::isVirtualRegister(SrcReg))
|
||||||
SrcTRC = RegInfo.getRegClass(SrcReg);
|
SrcTRC = RegInfo.getRegClass(SrcReg);
|
||||||
else
|
else
|
||||||
SrcTRC = TRI->getPhysicalRegisterRegClass(SrcVal.getValueType(),SrcReg);
|
SrcTRC = TRI->getPhysicalRegisterRegClass(SrcReg,SrcVal.getValueType());
|
||||||
|
|
||||||
if (TargetRegisterInfo::isVirtualRegister(DestReg))
|
if (TargetRegisterInfo::isVirtualRegister(DestReg))
|
||||||
DstTRC = RegInfo.getRegClass(DestReg);
|
DstTRC = RegInfo.getRegClass(DestReg);
|
||||||
else
|
else
|
||||||
DstTRC = TRI->getPhysicalRegisterRegClass(
|
DstTRC = TRI->getPhysicalRegisterRegClass(DestReg,
|
||||||
Node->getOperand(1).getValueType(),
|
Node->getOperand(1).getValueType());
|
||||||
DestReg);
|
|
||||||
TII->copyRegToReg(*BB, BB->end(), DestReg, SrcReg, DstTRC, SrcTRC);
|
TII->copyRegToReg(*BB, BB->end(), DestReg, SrcReg, DstTRC, SrcTRC);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -768,7 +768,7 @@ void ScheduleDAGRRList::ListScheduleBottomUp() {
|
|||||||
// Issue expensive cross register class copies.
|
// Issue expensive cross register class copies.
|
||||||
MVT::ValueType VT = getPhysicalRegisterVT(LRDef->Node, Reg, TII);
|
MVT::ValueType VT = getPhysicalRegisterVT(LRDef->Node, Reg, TII);
|
||||||
const TargetRegisterClass *RC =
|
const TargetRegisterClass *RC =
|
||||||
TRI->getPhysicalRegisterRegClass(VT, Reg);
|
TRI->getPhysicalRegisterRegClass(Reg, VT);
|
||||||
const TargetRegisterClass *DestRC = TRI->getCrossCopyRegClass(RC);
|
const TargetRegisterClass *DestRC = TRI->getCrossCopyRegClass(RC);
|
||||||
if (!DestRC) {
|
if (!DestRC) {
|
||||||
assert(false && "Don't know how to copy this physical register!");
|
assert(false && "Don't know how to copy this physical register!");
|
||||||
|
@@ -125,6 +125,21 @@ void VirtRegMap::assignVirtReMatId(unsigned virtReg, int id) {
|
|||||||
Virt2ReMatIdMap[virtReg] = id;
|
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) {
|
void VirtRegMap::addSpillSlotUse(int FI, MachineInstr *MI) {
|
||||||
if (!MF.getFrameInfo()->isFixedObjectIndex(FI)) {
|
if (!MF.getFrameInfo()->isFixedObjectIndex(FI)) {
|
||||||
assert(FI >= 0 && "Spill slot index should not be negative!");
|
assert(FI >= 0 && "Spill slot index should not be negative!");
|
||||||
@@ -164,6 +179,7 @@ void VirtRegMap::RemoveMachineInstrFromMaps(MachineInstr *MI) {
|
|||||||
MI2VirtMap.erase(MI);
|
MI2VirtMap.erase(MI);
|
||||||
SpillPt2VirtMap.erase(MI);
|
SpillPt2VirtMap.erase(MI);
|
||||||
RestorePt2VirtMap.erase(MI);
|
RestorePt2VirtMap.erase(MI);
|
||||||
|
EmergencySpillMap.erase(MI);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtRegMap::print(std::ostream &OS) const {
|
void VirtRegMap::print(std::ostream &OS) const {
|
||||||
@@ -1043,6 +1059,30 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
|
|||||||
MachineInstr &MI = *MII;
|
MachineInstr &MI = *MII;
|
||||||
const TargetInstrDesc &TID = MI.getDesc();
|
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.
|
// Insert restores here if asked to.
|
||||||
if (VRM.isRestorePt(&MI)) {
|
if (VRM.isRestorePt(&MI)) {
|
||||||
std::vector<unsigned> &RestoreRegs = VRM.getRestorePtRestores(&MI);
|
std::vector<unsigned> &RestoreRegs = VRM.getRestorePtRestores(&MI);
|
||||||
|
@@ -93,6 +93,17 @@ namespace llvm {
|
|||||||
/// splitting.
|
/// splitting.
|
||||||
std::map<MachineInstr*, std::vector<unsigned> > RestorePt2VirtMap;
|
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
|
/// ReMatId - Instead of assigning a stack slot to a to be rematerialized
|
||||||
/// virtual register, an unique id is being assigned. This keeps track of
|
/// 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
|
/// the highest id used so far. Note, this starts at (1<<18) to avoid
|
||||||
@@ -293,6 +304,8 @@ namespace llvm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief - transfer restore point information from one instruction to
|
||||||
|
/// another.
|
||||||
void transferRestorePts(MachineInstr *Old, MachineInstr *New) {
|
void transferRestorePts(MachineInstr *Old, MachineInstr *New) {
|
||||||
std::map<MachineInstr*,std::vector<unsigned> >::iterator I =
|
std::map<MachineInstr*,std::vector<unsigned> >::iterator I =
|
||||||
RestorePt2VirtMap.find(Old);
|
RestorePt2VirtMap.find(Old);
|
||||||
@@ -306,6 +319,33 @@ namespace llvm {
|
|||||||
RestorePt2VirtMap.erase(I);
|
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.
|
/// @brief Return lowest spill slot index.
|
||||||
int getLowSpillSlot() const {
|
int getLowSpillSlot() const {
|
||||||
return LowSpillSlot;
|
return LowSpillSlot;
|
||||||
|
@@ -34,20 +34,21 @@ TargetRegisterInfo::TargetRegisterInfo(const TargetRegisterDesc *D, unsigned NR,
|
|||||||
TargetRegisterInfo::~TargetRegisterInfo() {}
|
TargetRegisterInfo::~TargetRegisterInfo() {}
|
||||||
|
|
||||||
/// getPhysicalRegisterRegClass - Returns the Register Class of a physical
|
/// getPhysicalRegisterRegClass - Returns the Register Class of a physical
|
||||||
/// register.
|
/// register of the given type. If type is MVT::Other, then just return any
|
||||||
|
/// register class the register belongs to.
|
||||||
const TargetRegisterClass *
|
const TargetRegisterClass *
|
||||||
TargetRegisterInfo::getPhysicalRegisterRegClass(MVT::ValueType VT,
|
TargetRegisterInfo::getPhysicalRegisterRegClass(unsigned reg,
|
||||||
unsigned reg) const {
|
MVT::ValueType VT) const {
|
||||||
assert(isPhysicalRegister(reg) && "reg must be a physical register");
|
assert(isPhysicalRegister(reg) && "reg must be a physical register");
|
||||||
// Pick the register class of the right type that contains this physreg.
|
// Pick the register class of the right type that contains this physreg.
|
||||||
for (regclass_iterator I = regclass_begin(), E = regclass_end(); I != E; ++I)
|
for (regclass_iterator I = regclass_begin(), E = regclass_end(); I != E; ++I)
|
||||||
if ((*I)->hasType(VT) && (*I)->contains(reg))
|
if ((VT == MVT::Other || (*I)->hasType(VT))
|
||||||
|
&& (*I)->contains(reg))
|
||||||
return *I;
|
return *I;
|
||||||
assert(false && "Couldn't find the register class");
|
assert(false && "Couldn't find the register class");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// getAllocatableSetForRC - Toggle the bits that represent allocatable
|
/// getAllocatableSetForRC - Toggle the bits that represent allocatable
|
||||||
/// registers for the specific register class.
|
/// registers for the specific register class.
|
||||||
static void getAllocatableSetForRC(MachineFunction &MF,
|
static void getAllocatableSetForRC(MachineFunction &MF,
|
||||||
|
14
test/CodeGen/X86/2008-03-10-RegAllocInfLoop.ll
Normal file
14
test/CodeGen/X86/2008-03-10-RegAllocInfLoop.ll
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
; RUN: llvm-as < %s | llc -mtriple=i386-pc-linux-gnu -relocation-model=pic -disable-fp-elim
|
||||||
|
; PR2134
|
||||||
|
|
||||||
|
declare fastcc i8* @w_addchar(i8*, i32*, i32*, i8 signext ) nounwind
|
||||||
|
|
||||||
|
define x86_stdcallcc i32 @parse_backslash(i8** inreg %word, i32* inreg %word_length, i32* inreg %max_length) nounwind {
|
||||||
|
entry:
|
||||||
|
%tmp6 = load i8* null, align 1 ; <i8> [#uses=1]
|
||||||
|
br label %bb13
|
||||||
|
bb13: ; preds = %entry
|
||||||
|
%tmp26 = call fastcc i8* @w_addchar( i8* null, i32* %word_length, i32* %max_length, i8 signext %tmp6 ) nounwind ; <i8*> [#uses=1]
|
||||||
|
store i8* %tmp26, i8** %word, align 4
|
||||||
|
ret i32 0
|
||||||
|
}
|
Reference in New Issue
Block a user