summaryrefslogtreecommitdiff
path: root/lib/CodeGen/RegAllocGreedy.cpp
diff options
context:
space:
mode:
authorManman Ren <manman.ren@gmail.com>2014-03-25 00:16:25 +0000
committerManman Ren <manman.ren@gmail.com>2014-03-25 00:16:25 +0000
commit692d1830f3fc0fc583f1bb84f9ab3574bc546e3b (patch)
tree5a54aff31b6757dcc5107cf46cb405a76ecb91b5 /lib/CodeGen/RegAllocGreedy.cpp
parent4a88cd08da9318d5d29cad4f9807ec395b341f68 (diff)
downloadllvm-692d1830f3fc0fc583f1bb84f9ab3574bc546e3b.tar.gz
llvm-692d1830f3fc0fc583f1bb84f9ab3574bc546e3b.tar.bz2
llvm-692d1830f3fc0fc583f1bb84f9ab3574bc546e3b.tar.xz
Register Allocator: check other options before using a CSR for the first time.
When register allocator's stage is RS_Spill, we choose spill over using the CSR for the first time, if the spill cost is lower than CSRCost. When register allocator's stage is < RS_Split, we choose pre-splitting over using the CSR for the first time, if the cost of splitting is lower than CSRCost. CSRCost is set with command-line option "regalloc-csr-first-time-cost". The default value is 0 to generate the same codes as before this commit. With a value of 15 (1 << 14 is the entry frequency), I measured performance gain of 3% on 253.perlbmk and 1.7% on 197.parser, with instrumented PGO, on an arm device. rdar://16162005 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204690 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/RegAllocGreedy.cpp')
-rw-r--r--lib/CodeGen/RegAllocGreedy.cpp63
1 files changed, 57 insertions, 6 deletions
diff --git a/lib/CodeGen/RegAllocGreedy.cpp b/lib/CodeGen/RegAllocGreedy.cpp
index 5293e3160f..3a4ad620d0 100644
--- a/lib/CodeGen/RegAllocGreedy.cpp
+++ b/lib/CodeGen/RegAllocGreedy.cpp
@@ -71,6 +71,12 @@ static cl::opt<unsigned> LastChanceRecoloringMaxInterference(
" interference at a time"),
cl::init(8));
+// FIXME: Find a good default for this flag and remove the flag.
+static cl::opt<unsigned>
+CSRFirstTimeCost("regalloc-csr-first-time-cost",
+ cl::desc("Cost for first time use of callee-saved register."),
+ cl::init(0), cl::Hidden);
+
static RegisterRegAlloc greedyRegAlloc("greedy", "greedy register allocator",
createGreedyRegisterAllocator);
@@ -310,7 +316,7 @@ private:
unsigned calculateRegionSplitCost(LiveInterval &VirtReg,
AllocationOrder &Order,
BlockFrequency &BestCost,
- unsigned &NumCands);
+ unsigned &NumCands, bool IgnoreCSR);
/// Perform region splitting.
unsigned doRegionSplit(LiveInterval &VirtReg, unsigned BestCand,
bool HasCompact,
@@ -1257,7 +1263,8 @@ unsigned RAGreedy::tryRegionSplit(LiveInterval &VirtReg, AllocationOrder &Order,
}
unsigned BestCand =
- calculateRegionSplitCost(VirtReg, Order, BestCost, NumCands);
+ calculateRegionSplitCost(VirtReg, Order, BestCost, NumCands,
+ false/*IgnoreCSR*/);
// No solutions found, fall back to single block splitting.
if (!HasCompact && BestCand == NoCand)
@@ -1269,10 +1276,15 @@ unsigned RAGreedy::tryRegionSplit(LiveInterval &VirtReg, AllocationOrder &Order,
unsigned RAGreedy::calculateRegionSplitCost(LiveInterval &VirtReg,
AllocationOrder &Order,
BlockFrequency &BestCost,
- unsigned &NumCands) {
+ unsigned &NumCands,
+ bool IgnoreCSR) {
unsigned BestCand = NoCand;
Order.rewind();
while (unsigned PhysReg = Order.next()) {
+ if (unsigned CSR = RegClassInfo.getLastCalleeSavedAlias(PhysReg))
+ if (IgnoreCSR && !MRI->isPhysRegUsed(CSR))
+ continue;
+
// Discard bad candidates before we run out of interference cache cursors.
// This will only affect register classes with a lot of registers (>32).
if (NumCands == IntfCache.getMaxCursors()) {
@@ -2099,10 +2111,49 @@ unsigned RAGreedy::selectOrSplitImpl(LiveInterval &VirtReg,
SmallVectorImpl<unsigned> &NewVRegs,
SmallVirtRegSet &FixedRegisters,
unsigned Depth) {
+ unsigned CostPerUseLimit = ~0u;
// First try assigning a free register.
AllocationOrder Order(VirtReg.reg, *VRM, RegClassInfo);
- if (unsigned PhysReg = tryAssign(VirtReg, Order, NewVRegs))
- return PhysReg;
+ if (unsigned PhysReg = tryAssign(VirtReg, Order, NewVRegs)) {
+ // We check other options if we are using a CSR for the first time.
+ bool CSRFirstUse = false;
+ if (unsigned CSR = RegClassInfo.getLastCalleeSavedAlias(PhysReg))
+ if (!MRI->isPhysRegUsed(CSR))
+ CSRFirstUse = true;
+
+ BlockFrequency CSRCost(CSRFirstTimeCost);
+ if (getStage(VirtReg) == RS_Spill && CSRFirstUse && NewVRegs.empty() &&
+ CSRFirstTimeCost > 0 && VirtReg.isSpillable()) {
+ // We choose spill over using the CSR for the first time if the spill cost
+ // is lower than CSRCost.
+ SA->analyze(&VirtReg);
+ if (calcSpillCost() >= CSRCost)
+ return PhysReg;
+
+ // We are going to spill, set CostPerUseLimit to 1 to make sure that
+ // we will not use a callee-saved register in tryEvict.
+ CostPerUseLimit = 1;
+ }
+ else if (getStage(VirtReg) < RS_Split && CSRFirstUse &&
+ NewVRegs.empty() && CSRFirstTimeCost > 0) {
+ // We choose pre-splitting over using the CSR for the first time if
+ // the cost of splitting is lower than CSRCost.
+ SA->analyze(&VirtReg);
+ unsigned NumCands = 0;
+ unsigned BestCand =
+ calculateRegionSplitCost(VirtReg, Order, CSRCost, NumCands,
+ true/*IgnoreCSR*/);
+ if (BestCand == NoCand)
+ // Use the CSR if we can't find a region split below CSRCost.
+ return PhysReg;
+
+ // Perform the actual pre-splitting.
+ doRegionSplit(VirtReg, BestCand, false/*HasCompact*/, NewVRegs);
+ if (!NewVRegs.empty())
+ return 0;
+ } else
+ return PhysReg;
+ }
LiveRangeStage Stage = getStage(VirtReg);
DEBUG(dbgs() << StageName[Stage]
@@ -2112,7 +2163,7 @@ unsigned RAGreedy::selectOrSplitImpl(LiveInterval &VirtReg,
// queue. The RS_Split ranges already failed to do this, and they should not
// get a second chance until they have been split.
if (Stage != RS_Split)
- if (unsigned PhysReg = tryEvict(VirtReg, Order, NewVRegs))
+ if (unsigned PhysReg = tryEvict(VirtReg, Order, NewVRegs, CostPerUseLimit))
return PhysReg;
assert(NewVRegs.empty() && "Cannot append to existing NewVRegs");