diff options
author | Manman Ren <manman.ren@gmail.com> | 2014-03-25 00:16:25 +0000 |
---|---|---|
committer | Manman Ren <manman.ren@gmail.com> | 2014-03-25 00:16:25 +0000 |
commit | 692d1830f3fc0fc583f1bb84f9ab3574bc546e3b (patch) | |
tree | 5a54aff31b6757dcc5107cf46cb405a76ecb91b5 /lib/CodeGen/RegAllocGreedy.cpp | |
parent | 4a88cd08da9318d5d29cad4f9807ec395b341f68 (diff) | |
download | llvm-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.cpp | 63 |
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"); |