diff options
author | Evan Cheng <evan.cheng@apple.com> | 2009-06-14 20:22:55 +0000 |
---|---|---|
committer | Evan Cheng <evan.cheng@apple.com> | 2009-06-14 20:22:55 +0000 |
commit | 90f95f88c6ce09c6744777dc9d140c3c77203b92 (patch) | |
tree | 3996a490bf685eea1de9b1579d28f69500dbf8a6 /lib | |
parent | caf6b2bbaf40580596e974b5eee0a7e59b58bd98 (diff) | |
download | external_llvm-90f95f88c6ce09c6744777dc9d140c3c77203b92.zip external_llvm-90f95f88c6ce09c6744777dc9d140c3c77203b92.tar.gz external_llvm-90f95f88c6ce09c6744777dc9d140c3c77203b92.tar.bz2 |
Move register allocation preference (or hint) from LiveInterval to MachineRegisterInfo. This allows more passes to set them.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@73346 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/CodeGen/LiveInterval.cpp | 26 | ||||
-rw-r--r-- | lib/CodeGen/LiveIntervalAnalysis.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/MachineRegisterInfo.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/RegAllocLinearScan.cpp | 30 | ||||
-rw-r--r-- | lib/CodeGen/RegAllocPBQP.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/SimpleRegisterCoalescing.cpp | 71 | ||||
-rw-r--r-- | lib/CodeGen/VirtRegMap.cpp | 37 | ||||
-rw-r--r-- | lib/CodeGen/VirtRegMap.h | 8 |
8 files changed, 142 insertions, 37 deletions
diff --git a/lib/CodeGen/LiveInterval.cpp b/lib/CodeGen/LiveInterval.cpp index 67120b8..97926dd 100644 --- a/lib/CodeGen/LiveInterval.cpp +++ b/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<VNInfo*, 16> &NewVNInfo) { + SmallVector<VNInfo*, 16> &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<MachineRegisterInfo::RegAllocHintType, unsigned> Hint = + MRI->getRegAllocationHint(reg); + if (Hint.first == MachineRegisterInfo::RA_None) { + std::pair<MachineRegisterInfo::RegAllocHintType, unsigned> 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<MachineRegisterInfo::RegAllocHintType, unsigned> 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/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index cf0a648..c26d47f 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/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/lib/CodeGen/MachineRegisterInfo.cpp b/lib/CodeGen/MachineRegisterInfo.cpp index 4f5ab1f..9649c4c 100644 --- a/lib/CodeGen/MachineRegisterInfo.cpp +++ b/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/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp index 804fae5..3c445e7 100644 --- a/lib/CodeGen/RegAllocLinearScan.cpp +++ b/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<std::pair<unsigned,float> > 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/lib/CodeGen/RegAllocPBQP.cpp b/lib/CodeGen/RegAllocPBQP.cpp index 61450a7..d07006d 100644 --- a/lib/CodeGen/RegAllocPBQP.cpp +++ b/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/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp index 2bc234f..95e5aca 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ b/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<MachineRegisterInfo::RegAllocHintType, unsigned> 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<MachineRegisterInfo::RegAllocHintType, unsigned> RHSPref = + mri_->getRegAllocationHint(RHS.reg); + std::pair<MachineRegisterInfo::RegAllocHintType, unsigned> 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/lib/CodeGen/VirtRegMap.cpp b/lib/CodeGen/VirtRegMap.cpp index 29637b9..87d75dd 100644 --- a/lib/CodeGen/VirtRegMap.cpp +++ b/lib/CodeGen/VirtRegMap.cpp @@ -51,6 +51,7 @@ static RegisterPass<VirtRegMap> 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<MachineRegisterInfo::RegAllocHintType, unsigned> 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/lib/CodeGen/VirtRegMap.h b/lib/CodeGen/VirtRegMap.h index 507557d..fe767b7 100644 --- a/lib/CodeGen/VirtRegMap.h +++ b/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<unsigned, ModRef> > 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. |