summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2009-06-14 20:22:55 +0000
committerEvan Cheng <evan.cheng@apple.com>2009-06-14 20:22:55 +0000
commit90f95f88c6ce09c6744777dc9d140c3c77203b92 (patch)
tree3996a490bf685eea1de9b1579d28f69500dbf8a6
parentcaf6b2bbaf40580596e974b5eee0a7e59b58bd98 (diff)
downloadllvm-90f95f88c6ce09c6744777dc9d140c3c77203b92.tar.gz
llvm-90f95f88c6ce09c6744777dc9d140c3c77203b92.tar.bz2
llvm-90f95f88c6ce09c6744777dc9d140c3c77203b92.tar.xz
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
-rw-r--r--include/llvm/CodeGen/LiveInterval.h10
-rw-r--r--include/llvm/CodeGen/MachineRegisterInfo.h39
-rw-r--r--include/llvm/Target/TargetRegisterInfo.h14
-rw-r--r--lib/CodeGen/LiveInterval.cpp26
-rw-r--r--lib/CodeGen/LiveIntervalAnalysis.cpp2
-rw-r--r--lib/CodeGen/MachineRegisterInfo.cpp2
-rw-r--r--lib/CodeGen/RegAllocLinearScan.cpp30
-rw-r--r--lib/CodeGen/RegAllocPBQP.cpp3
-rw-r--r--lib/CodeGen/SimpleRegisterCoalescing.cpp71
-rw-r--r--lib/CodeGen/VirtRegMap.cpp37
-rw-r--r--lib/CodeGen/VirtRegMap.h8
11 files changed, 200 insertions, 42 deletions
diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h
index f1ae587ac1..f0d3b01e14 100644
--- a/include/llvm/CodeGen/LiveInterval.h
+++ b/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<VNInfo*, 16> &NewVNInfo);
+ SmallVector<VNInfo*, 16> &NewVNInfo,
+ MachineRegisterInfo *MRI);
/// isInOneLiveRange - Return true if the range specified is entirely in the
/// a single LiveRange of the live interval.
diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h
index 02f9b7c686..c343d42a92 100644
--- a/include/llvm/CodeGen/MachineRegisterInfo.h
+++ b/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<std::vector<unsigned> > 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<std::pair<RegAllocHintType, unsigned> > RegAllocHints;
/// PhysRegUseDefLists - This is an array of the head of the use/def list for
/// physical registers.
@@ -170,7 +188,26 @@ public:
std::vector<unsigned> &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<RegAllocHintType, unsigned>
+ getRegAllocationHint(unsigned Reg) const {
+ Reg -= TargetRegisterInfo::FirstVirtualRegister;
+ assert(Reg < VRegInfo.size() && "Invalid vreg!");
+ return RegAllocHints[Reg];
+ }
+
//===--------------------------------------------------------------------===//
// Physical Register Use Info
//===--------------------------------------------------------------------===//
diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h
index 0218bfdb2a..949185ac26 100644
--- a/include/llvm/Target/TargetRegisterInfo.h
+++ b/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/lib/CodeGen/LiveInterval.cpp b/lib/CodeGen/LiveInterval.cpp
index 67120b8798..97926dd6fd 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 cf0a648b62..c26d47ff7c 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 4f5ab1f586..9649c4c44c 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 804fae55e5..3c445e7942 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 61450a7cca..d07006d7e1 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 2bc234f7d0..95e5acaab4 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 29637b954f..87d75dd006 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 507557d24c..fe767b7671 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.