From 085caf10beed56dade58b0c99331a5c249bb878a Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Sun, 14 Jun 2009 20:22:55 +0000 Subject: [PATCH] Move register allocation preference (or hint) from LiveInterval to MachineRegisterInfo. This allows more passes to set them. llvm-svn: 73346 --- llvm/include/llvm/CodeGen/LiveInterval.h | 10 +-- .../llvm/CodeGen/MachineRegisterInfo.h | 39 +++++++++- llvm/include/llvm/Target/TargetRegisterInfo.h | 14 ++++ llvm/lib/CodeGen/LiveInterval.cpp | 26 +++++-- llvm/lib/CodeGen/LiveIntervalAnalysis.cpp | 2 +- llvm/lib/CodeGen/MachineRegisterInfo.cpp | 2 + llvm/lib/CodeGen/RegAllocLinearScan.cpp | 30 ++++---- llvm/lib/CodeGen/RegAllocPBQP.cpp | 3 +- llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp | 71 +++++++++++++++---- llvm/lib/CodeGen/VirtRegMap.cpp | 37 +++++++++- llvm/lib/CodeGen/VirtRegMap.h | 8 ++- 11 files changed, 200 insertions(+), 42 deletions(-) diff --git a/llvm/include/llvm/CodeGen/LiveInterval.h b/llvm/include/llvm/CodeGen/LiveInterval.h index f1ae587ac195..f0d3b01e1402 100644 --- a/llvm/include/llvm/CodeGen/LiveInterval.h +++ b/llvm/include/llvm/CodeGen/LiveInterval.h @@ -29,6 +29,7 @@ namespace llvm { class MachineInstr; + class MachineRegisterInfo; class TargetRegisterInfo; struct LiveInterval; @@ -108,7 +109,6 @@ namespace llvm { unsigned reg; // the register or stack slot of this interval // if the top bits is set, it represents a stack slot. float weight; // weight of this interval - unsigned short preference; // preferred register for this interval Ranges ranges; // the ranges in which this register is live VNInfoList valnos; // value#'s @@ -134,7 +134,7 @@ namespace llvm { }; LiveInterval(unsigned Reg, float Weight, bool IsSS = false) - : reg(Reg), weight(Weight), preference(0) { + : reg(Reg), weight(Weight) { if (IsSS) reg = reg | (1U << (sizeof(unsigned)*CHAR_BIT-1)); } @@ -339,7 +339,8 @@ namespace llvm { /// Copy - Copy the specified live interval. This copies all the fields /// except for the register of the interval. - void Copy(const LiveInterval &RHS, BumpPtrAllocator &VNInfoAllocator); + void Copy(const LiveInterval &RHS, MachineRegisterInfo *MRI, + BumpPtrAllocator &VNInfoAllocator); bool empty() const { return ranges.empty(); } @@ -416,7 +417,8 @@ namespace llvm { /// the intervals are not joinable, this aborts. void join(LiveInterval &Other, const int *ValNoAssignments, const int *RHSValNoAssignments, - SmallVector &NewVNInfo); + SmallVector &NewVNInfo, + MachineRegisterInfo *MRI); /// isInOneLiveRange - Return true if the range specified is entirely in the /// a single LiveRange of the live interval. diff --git a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h index 02f9b7c686e2..c343d42a92ec 100644 --- a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h @@ -25,6 +25,16 @@ namespace llvm { /// registers, including vreg register classes, use/def chains for registers, /// etc. class MachineRegisterInfo { +public: + /// Register allocation hints. + enum RegAllocHintType { + RA_None, /// No preference + RA_Preference, /// Prefer a particular register + RA_PairEven, /// Even register of a register pair + RA_PairOdd /// Odd register of a register pair + }; + +private: /// VRegInfo - Information we keep for each virtual register. The entries in /// this vector are actually converted to vreg numbers by adding the /// TargetRegisterInfo::FirstVirtualRegister delta to their index. @@ -37,6 +47,14 @@ class MachineRegisterInfo { /// virtual registers. For each target register class, it keeps a list of /// virtual registers belonging to the class. std::vector > RegClass2VRegMap; + + /// RegAllocHints - This vector records register allocation hints for virtual + /// registers. For each virtual register, it keeps a register and type enum + /// pair making up the allocation hint. For example, if the hint type is + /// RA_Specified, it means the virtual register prefers the specified physical + /// register of the hint or the physical register allocated to the virtual + /// register of the hint. + std::vector > RegAllocHints; /// PhysRegUseDefLists - This is an array of the head of the use/def list for /// physical registers. @@ -170,7 +188,26 @@ public: std::vector &getRegClassVirtRegs(const TargetRegisterClass *RC) { return RegClass2VRegMap[RC->getID()]; } - + + /// setRegAllocationHint - Specify a register allocation hint for the + /// specified virtual register. + void setRegAllocationHint(unsigned Reg, + RegAllocHintType Type, unsigned PrefReg) { + Reg -= TargetRegisterInfo::FirstVirtualRegister; + assert(Reg < VRegInfo.size() && "Invalid vreg!"); + RegAllocHints[Reg].first = Type; + RegAllocHints[Reg].second = PrefReg; + } + + /// getRegAllocationHint - Return the register allocation hint for the + /// specified virtual register. + std::pair + getRegAllocationHint(unsigned Reg) const { + Reg -= TargetRegisterInfo::FirstVirtualRegister; + assert(Reg < VRegInfo.size() && "Invalid vreg!"); + return RegAllocHints[Reg]; + } + //===--------------------------------------------------------------------===// // Physical Register Use Info //===--------------------------------------------------------------------===// diff --git a/llvm/include/llvm/Target/TargetRegisterInfo.h b/llvm/include/llvm/Target/TargetRegisterInfo.h index 0218bfdb2ae3..949185ac261a 100644 --- a/llvm/include/llvm/Target/TargetRegisterInfo.h +++ b/llvm/include/llvm/Target/TargetRegisterInfo.h @@ -484,6 +484,20 @@ public: return 0; } + /// getRegisterPairEven - Return the even register of the register pair that + /// contains the specified register. + virtual unsigned getRegisterPairEven(const MachineFunction &MF, + unsigned Reg) const { + return 0; + } + + /// getRegisterPairOdd - Return the odd register of the register pair that + /// contains the specified register. + virtual unsigned getRegisterPairOdd(const MachineFunction &MF, + unsigned Reg) const { + return 0; + } + //===--------------------------------------------------------------------===// // Register Class Information // diff --git a/llvm/lib/CodeGen/LiveInterval.cpp b/llvm/lib/CodeGen/LiveInterval.cpp index 67120b879886..97926dd6fd58 100644 --- a/llvm/lib/CodeGen/LiveInterval.cpp +++ b/llvm/lib/CodeGen/LiveInterval.cpp @@ -19,6 +19,7 @@ //===----------------------------------------------------------------------===// #include "llvm/CodeGen/LiveInterval.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/STLExtras.h" @@ -421,13 +422,13 @@ VNInfo *LiveInterval::findDefinedVNInfo(unsigned DefIdxOrReg) const { return VNI; } - /// join - Join two live intervals (this, and other) together. This applies /// mappings to the value numbers in the LHS/RHS intervals as specified. If /// the intervals are not joinable, this aborts. void LiveInterval::join(LiveInterval &Other, const int *LHSValNoAssignments, const int *RHSValNoAssignments, - SmallVector &NewVNInfo) { + SmallVector &NewVNInfo, + MachineRegisterInfo *MRI) { // Determine if any of our live range values are mapped. This is uncommon, so // we want to avoid the interval scan if not. bool MustMapCurValNos = false; @@ -502,8 +503,19 @@ void LiveInterval::join(LiveInterval &Other, const int *LHSValNoAssignments, } weight += Other.weight; - if (Other.preference && !preference) - preference = Other.preference; + + // Update regalloc hint if currently there isn't one. + if (TargetRegisterInfo::isVirtualRegister(reg) && + TargetRegisterInfo::isVirtualRegister(Other.reg)) { + std::pair Hint = + MRI->getRegAllocationHint(reg); + if (Hint.first == MachineRegisterInfo::RA_None) { + std::pair OtherHint = + MRI->getRegAllocationHint(Other.reg); + if (OtherHint.first != MachineRegisterInfo::RA_None) + MRI->setRegAllocationHint(reg, OtherHint.first, OtherHint.second); + } + } } /// MergeRangesInAsValue - Merge all of the intervals in RHS into this live @@ -756,10 +768,14 @@ VNInfo* LiveInterval::MergeValueNumberInto(VNInfo *V1, VNInfo *V2) { } void LiveInterval::Copy(const LiveInterval &RHS, + MachineRegisterInfo *MRI, BumpPtrAllocator &VNInfoAllocator) { ranges.clear(); valnos.clear(); - preference = RHS.preference; + std::pair Hint = + MRI->getRegAllocationHint(RHS.reg); + MRI->setRegAllocationHint(reg, Hint.first, Hint.second); + weight = RHS.weight; for (unsigned i = 0, e = RHS.getNumValNums(); i != e; ++i) { const VNInfo *VNI = RHS.getValNumInfo(i); diff --git a/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp b/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp index cf0a648b629d..c26d47ff7c2d 100644 --- a/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -896,7 +896,7 @@ LiveInterval* LiveIntervals::createInterval(unsigned reg) { /// managing the allocated memory. LiveInterval* LiveIntervals::dupInterval(LiveInterval *li) { LiveInterval *NewLI = createInterval(li->reg); - NewLI->Copy(*li, getVNInfoAllocator()); + NewLI->Copy(*li, mri_, getVNInfoAllocator()); return NewLI; } diff --git a/llvm/lib/CodeGen/MachineRegisterInfo.cpp b/llvm/lib/CodeGen/MachineRegisterInfo.cpp index 4f5ab1f5860e..9649c4c44ce7 100644 --- a/llvm/lib/CodeGen/MachineRegisterInfo.cpp +++ b/llvm/lib/CodeGen/MachineRegisterInfo.cpp @@ -16,6 +16,7 @@ using namespace llvm; MachineRegisterInfo::MachineRegisterInfo(const TargetRegisterInfo &TRI) { VRegInfo.reserve(256); + RegAllocHints.reserve(256); RegClass2VRegMap.resize(TRI.getNumRegClasses()+1); // RC ID starts at 1. UsedPhysRegs.resize(TRI.getNumRegs()); @@ -64,6 +65,7 @@ MachineRegisterInfo::createVirtualRegister(const TargetRegisterClass *RegClass){ // Add a reg, but keep track of whether the vector reallocated or not. void *ArrayBase = VRegInfo.empty() ? 0 : &VRegInfo[0]; VRegInfo.push_back(std::make_pair(RegClass, (MachineOperand*)0)); + RegAllocHints.push_back(std::make_pair(RA_None, 0)); if (!((&VRegInfo[0] == ArrayBase || VRegInfo.size() == 1))) // The vector reallocated, handle this now. diff --git a/llvm/lib/CodeGen/RegAllocLinearScan.cpp b/llvm/lib/CodeGen/RegAllocLinearScan.cpp index 804fae55e545..3c445e7942d9 100644 --- a/llvm/lib/CodeGen/RegAllocLinearScan.cpp +++ b/llvm/lib/CodeGen/RegAllocLinearScan.cpp @@ -352,7 +352,8 @@ void RALinScan::ComputeRelatedRegClasses() { /// different register classes or because the coalescer was overly /// conservative. unsigned RALinScan::attemptTrivialCoalescing(LiveInterval &cur, unsigned Reg) { - if ((cur.preference && cur.preference == Reg) || !cur.containsOneValue()) + unsigned Preference = vrm_->getRegAllocPref(cur.reg); + if ((Preference && Preference == Reg) || !cur.containsOneValue()) return Reg; VNInfo *vni = cur.begin()->valno; @@ -584,7 +585,7 @@ void RALinScan::linearScan() // register allocator had to spill other registers in its register class. if (ls_->getNumIntervals() == 0) return; - if (!vrm_->FindUnusedRegisters(tri_, li_)) + if (!vrm_->FindUnusedRegisters(li_)) return; } @@ -897,7 +898,7 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) // This is an implicitly defined live interval, just assign any register. const TargetRegisterClass *RC = mri_->getRegClass(cur->reg); if (cur->empty()) { - unsigned physReg = cur->preference; + unsigned physReg = vrm_->getRegAllocPref(cur->reg); if (!physReg) physReg = *RC->allocation_order_begin(*mf_); DOUT << tri_->getName(physReg) << '\n'; @@ -917,7 +918,7 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) // register class, then we should try to assign it the same register. // This can happen when the move is from a larger register class to a smaller // one, e.g. X86::mov32to32_. These move instructions are not coalescable. - if (!cur->preference && cur->hasAtLeastOneValue()) { + if (!vrm_->getRegAllocPref(cur->reg) && cur->hasAtLeastOneValue()) { VNInfo *vni = cur->begin()->valno; if (vni->def && vni->def != ~1U && vni->def != ~0U) { MachineInstr *CopyMI = li_->getInstructionFromIndex(vni->def); @@ -935,7 +936,8 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) if (DstSubReg) Reg = tri_->getMatchingSuperReg(Reg, DstSubReg, RC); if (Reg && allocatableRegs_[Reg] && RC->contains(Reg)) - cur->preference = Reg; + mri_->setRegAllocationHint(cur->reg, + MachineRegisterInfo::RA_Preference, Reg); } } } @@ -1044,7 +1046,8 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) if (LiveInterval *NextReloadLI = hasNextReloadInterval(cur)) { // "Downgrade" physReg to try to keep physReg from being allocated until // the next reload from the same SS is allocated. - NextReloadLI->preference = physReg; + mri_->setRegAllocationHint(NextReloadLI->reg, + MachineRegisterInfo::RA_Preference, physReg); DowngradeRegister(cur, physReg); } return; @@ -1071,7 +1074,7 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) // Find a register to spill. float minWeight = HUGE_VALF; - unsigned minReg = 0; /*cur->preference*/; // Try the pref register first. + unsigned minReg = 0; bool Found = false; std::vector > RegsWeights; @@ -1290,7 +1293,7 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) // It interval has a preference, it must be defined by a copy. Clear the // preference now since the source interval allocation may have been // undone as well. - i->preference = 0; + mri_->setRegAllocationHint(i->reg, MachineRegisterInfo::RA_None, 0); else { UpgradeRegister(ii->second); } @@ -1428,11 +1431,12 @@ unsigned RALinScan::getFreePhysReg(LiveInterval *cur) { // If copy coalescer has assigned a "preferred" register, check if it's // available first. - if (cur->preference) { - DOUT << "(preferred: " << tri_->getName(cur->preference) << ") "; - if (isRegAvail(cur->preference) && - RC->contains(cur->preference)) - return cur->preference; + unsigned Preference = vrm_->getRegAllocPref(cur->reg); + if (Preference) { + DOUT << "(preferred: " << tri_->getName(Preference) << ") "; + if (isRegAvail(Preference) && + RC->contains(Preference)) + return Preference; } if (!DowngradedRegs.empty()) { diff --git a/llvm/lib/CodeGen/RegAllocPBQP.cpp b/llvm/lib/CodeGen/RegAllocPBQP.cpp index 61450a7cca7c..d07006d7e188 100644 --- a/llvm/lib/CodeGen/RegAllocPBQP.cpp +++ b/llvm/lib/CodeGen/RegAllocPBQP.cpp @@ -733,8 +733,7 @@ void PBQPRegAlloc::finalizeAlloc() const { itr != end; ++itr) { LiveInterval *li = *itr; - unsigned physReg = li->preference; - + unsigned physReg = vrm->getRegAllocPref(li->reg); if (physReg == 0) { const TargetRegisterClass *liRC = mri->getRegClass(li->reg); physReg = *liRC->allocation_order_begin(*mf); diff --git a/llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp b/llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp index 2bc234f7d09e..95e5acaab415 100644 --- a/llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ b/llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -1265,6 +1265,35 @@ SimpleRegisterCoalescing::CanJoinInsertSubRegToPhysReg(unsigned DstReg, return true; } +/// getRegAllocPreference - Return register allocation preference register. +/// +static unsigned getRegAllocPreference(unsigned Reg, MachineFunction &MF, + MachineRegisterInfo *MRI, + const TargetRegisterInfo *TRI) { + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + return 0; + + std::pair Hint = + MRI->getRegAllocationHint(Reg); + switch (Hint.first) { + default: assert(0); + case MachineRegisterInfo::RA_None: + return 0; + case MachineRegisterInfo::RA_Preference: + return Hint.second; + case MachineRegisterInfo::RA_PairEven: + if (TargetRegisterInfo::isPhysicalRegister(Hint.second)) + return TRI->getRegisterPairOdd(MF, Hint.second); + return Hint.second; + case MachineRegisterInfo::RA_PairOdd: + if (TargetRegisterInfo::isPhysicalRegister(Hint.second)) + return TRI->getRegisterPairEven(MF, Hint.second); + return Hint.second; + } + // Shouldn't reach here. + return 0; +} + /// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, /// which are the src/dst of the copy instruction CopyMI. This returns true /// if the copy was successfully coalesced away. If it is not currently @@ -1566,7 +1595,8 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { if (PhysJoinTweak) { if (SrcIsPhys) { if (!isWinToJoinVRWithSrcPhysReg(CopyMI, CopyMBB, DstInt, SrcInt)) { - DstInt.preference = SrcReg; + mri_->setRegAllocationHint(DstInt.reg, + MachineRegisterInfo::RA_Preference, SrcReg); ++numAborts; DOUT << "\tMay tie down a physical register, abort!\n"; Again = true; // May be possible to coalesce later. @@ -1574,7 +1604,8 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { } } else { if (!isWinToJoinVRWithDstPhysReg(CopyMI, CopyMBB, DstInt, SrcInt)) { - SrcInt.preference = DstReg; + mri_->setRegAllocationHint(SrcInt.reg, + MachineRegisterInfo::RA_Preference, DstReg); ++numAborts; DOUT << "\tMay tie down a physical register, abort!\n"; Again = true; // May be possible to coalesce later. @@ -1598,7 +1629,8 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { if (Length > Threshold && (((float)std::distance(mri_->use_begin(JoinVReg), mri_->use_end()) / Length) < Ratio)) { - JoinVInt.preference = JoinPReg; + mri_->setRegAllocationHint(JoinVInt.reg, + MachineRegisterInfo::RA_Preference, JoinPReg); ++numAborts; DOUT << "\tMay tie down a physical register, abort!\n"; Again = true; // May be possible to coalesce later. @@ -1691,7 +1723,7 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { !SrcIsPhys && !DstIsPhys) { if ((isExtSubReg && !Swapped) || ((isInsSubReg || isSubRegToReg) && Swapped)) { - ResSrcInt->Copy(*ResDstInt, li_->getVNInfoAllocator()); + ResSrcInt->Copy(*ResDstInt, mri_, li_->getVNInfoAllocator()); std::swap(SrcReg, DstReg); std::swap(ResSrcInt, ResDstInt); } @@ -1778,11 +1810,13 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { // If resulting interval has a preference that no longer fits because of subreg // coalescing, just clear the preference. - if (ResDstInt->preference && (isExtSubReg || isInsSubReg || isSubRegToReg) && + unsigned Preference = getRegAllocPreference(ResDstInt->reg, *mf_, mri_, tri_); + if (Preference && (isExtSubReg || isInsSubReg || isSubRegToReg) && TargetRegisterInfo::isVirtualRegister(ResDstInt->reg)) { const TargetRegisterClass *RC = mri_->getRegClass(ResDstInt->reg); - if (!RC->contains(ResDstInt->preference)) - ResDstInt->preference = 0; + if (!RC->contains(Preference)) + mri_->setRegAllocationHint(ResDstInt->reg, + MachineRegisterInfo::RA_None, 0); } DOUT << "\n\t\tJoined. Result = "; ResDstInt->print(DOUT, tri_); @@ -2029,8 +2063,18 @@ bool SimpleRegisterCoalescing::SimpleJoin(LiveInterval &LHS, LiveInterval &RHS){ LHS.addKills(LHSValNo, VNI->kills); LHS.MergeRangesInAsValue(RHS, LHSValNo); LHS.weight += RHS.weight; - if (RHS.preference && !LHS.preference) - LHS.preference = RHS.preference; + + // Update regalloc hint if both are virtual registers. + if (TargetRegisterInfo::isVirtualRegister(LHS.reg) && + TargetRegisterInfo::isVirtualRegister(RHS.reg)) { + std::pair RHSPref = + mri_->getRegAllocationHint(RHS.reg); + std::pair LHSPref = + mri_->getRegAllocationHint(LHS.reg); + if (RHSPref.first != MachineRegisterInfo::RA_None && + LHSPref.first == MachineRegisterInfo::RA_None) + mri_->setRegAllocationHint(LHS.reg, RHSPref.first, RHSPref.second); + } // Update the liveintervals of sub-registers. if (TargetRegisterInfo::isPhysicalRegister(LHS.reg)) @@ -2315,10 +2359,12 @@ SimpleRegisterCoalescing::JoinIntervals(LiveInterval &LHS, LiveInterval &RHS, if ((RHS.ranges.size() > LHS.ranges.size() && TargetRegisterInfo::isVirtualRegister(LHS.reg)) || TargetRegisterInfo::isPhysicalRegister(RHS.reg)) { - RHS.join(LHS, &RHSValNoAssignments[0], &LHSValNoAssignments[0], NewVNInfo); + RHS.join(LHS, &RHSValNoAssignments[0], &LHSValNoAssignments[0], NewVNInfo, + mri_); Swapped = true; } else { - LHS.join(RHS, &LHSValNoAssignments[0], &RHSValNoAssignments[0], NewVNInfo); + LHS.join(RHS, &LHSValNoAssignments[0], &RHSValNoAssignments[0], NewVNInfo, + mri_); Swapped = false; } return true; @@ -2800,7 +2846,8 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) { } // Slightly prefer live interval that has been assigned a preferred reg. - if (LI.preference) + if (mri_->getRegAllocationHint(LI.reg).first != + MachineRegisterInfo::RA_None) LI.weight *= 1.01F; // Divide the weight of the interval by its size. This encourages diff --git a/llvm/lib/CodeGen/VirtRegMap.cpp b/llvm/lib/CodeGen/VirtRegMap.cpp index 29637b954f0b..87d75dd006d1 100644 --- a/llvm/lib/CodeGen/VirtRegMap.cpp +++ b/llvm/lib/CodeGen/VirtRegMap.cpp @@ -51,6 +51,7 @@ static RegisterPass X("virtregmap", "Virtual Register Map"); bool VirtRegMap::runOnMachineFunction(MachineFunction &mf) { + MRI = &mf.getRegInfo(); TII = mf.getTarget().getInstrInfo(); TRI = mf.getTarget().getRegisterInfo(); MF = &mf; @@ -98,6 +99,39 @@ void VirtRegMap::grow() { ImplicitDefed.resize(LastVirtReg-TargetRegisterInfo::FirstVirtualRegister+1); } +unsigned VirtRegMap::getRegAllocPref(unsigned virtReg) { + std::pair Hint = + MRI->getRegAllocationHint(virtReg); + switch (Hint.first) { + default: assert(0); + case MachineRegisterInfo::RA_None: + return 0; + case MachineRegisterInfo::RA_Preference: + if (TargetRegisterInfo::isPhysicalRegister(Hint.second)) + return Hint.second; + if (hasPhys(Hint.second)) + return getPhys(Hint.second); + case MachineRegisterInfo::RA_PairEven: { + unsigned physReg = Hint.second; + if (TargetRegisterInfo::isPhysicalRegister(physReg)) + return TRI->getRegisterPairEven(*MF, physReg); + else if (hasPhys(physReg)) + return TRI->getRegisterPairEven(*MF, getPhys(physReg)); + return 0; + } + case MachineRegisterInfo::RA_PairOdd: { + unsigned physReg = Hint.second; + if (TargetRegisterInfo::isPhysicalRegister(physReg)) + return TRI->getRegisterPairOdd(*MF, physReg); + else if (hasPhys(physReg)) + return TRI->getRegisterPairOdd(*MF, getPhys(physReg)); + return 0; + } + } + // Shouldn't reach here. + return 0; +} + int VirtRegMap::assignVirt2StackSlot(unsigned virtReg) { assert(TargetRegisterInfo::isVirtualRegister(virtReg)); assert(Virt2StackSlotMap[virtReg] == NO_STACK_SLOT && @@ -213,8 +247,7 @@ void VirtRegMap::RemoveMachineInstrFromMaps(MachineInstr *MI) { /// FindUnusedRegisters - Gather a list of allocatable registers that /// have not been allocated to any virtual register. -bool VirtRegMap::FindUnusedRegisters(const TargetRegisterInfo *TRI, - LiveIntervals* LIs) { +bool VirtRegMap::FindUnusedRegisters(LiveIntervals* LIs) { unsigned NumRegs = TRI->getNumRegs(); UnusedRegs.reset(); UnusedRegs.resize(NumRegs); diff --git a/llvm/lib/CodeGen/VirtRegMap.h b/llvm/lib/CodeGen/VirtRegMap.h index 507557d24c08..fe767b7671e1 100644 --- a/llvm/lib/CodeGen/VirtRegMap.h +++ b/llvm/lib/CodeGen/VirtRegMap.h @@ -31,6 +31,7 @@ namespace llvm { class LiveIntervals; class MachineInstr; class MachineFunction; + class MachineRegisterInfo; class TargetInstrInfo; class TargetRegisterInfo; @@ -47,6 +48,7 @@ namespace llvm { std::pair > MI2VirtMapTy; private: + MachineRegisterInfo *MRI; const TargetInstrInfo *TII; const TargetRegisterInfo *TRI; MachineFunction *MF; @@ -190,6 +192,9 @@ namespace llvm { grow(); } + /// @brief returns the register allocation preference. + unsigned getRegAllocPref(unsigned virtReg); + /// @brief records virtReg is a split live interval from SReg. void setIsSplitFromReg(unsigned virtReg, unsigned SReg) { Virt2SplitMap[virtReg] = SReg; @@ -445,8 +450,7 @@ namespace llvm { /// FindUnusedRegisters - Gather a list of allocatable registers that /// have not been allocated to any virtual register. - bool FindUnusedRegisters(const TargetRegisterInfo *TRI, - LiveIntervals* LIs); + bool FindUnusedRegisters(LiveIntervals* LIs); /// HasUnusedRegisters - Return true if there are any allocatable registers /// that have not been allocated to any virtual register.