mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-11 11:34:02 +00:00
RegAlloc: Account for a variable entry block frequency
Until r197284, the entry frequency was constant -- i.e., set to 2^14. Although current ToT still has a constant entry frequency, since r197284 that has been an implementation detail (which is soon going to change). - r204690 made the wrong assumption for the CSRCost metric. Adjust callee-saved register cost based on entry frequency. - r185393 made the wrong assumption (although it was valid at the time). Update SpillPlacement.cpp::Threshold to be relative to the entry frequency. Since ToT still has 2^14 entry frequency, this should have no observable functionality change. <rdar://problem/14292693> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205789 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
c0c10f20a2
commit
861e4db905
@ -39,6 +39,7 @@
|
|||||||
#include "llvm/CodeGen/VirtRegMap.h"
|
#include "llvm/CodeGen/VirtRegMap.h"
|
||||||
#include "llvm/IR/LLVMContext.h"
|
#include "llvm/IR/LLVMContext.h"
|
||||||
#include "llvm/PassAnalysisSupport.h"
|
#include "llvm/PassAnalysisSupport.h"
|
||||||
|
#include "llvm/Support/BranchProbability.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
@ -275,6 +276,9 @@ class RAGreedy : public MachineFunctionPass,
|
|||||||
/// NoCand which indicates the stack interval.
|
/// NoCand which indicates the stack interval.
|
||||||
SmallVector<unsigned, 32> BundleCand;
|
SmallVector<unsigned, 32> BundleCand;
|
||||||
|
|
||||||
|
/// Callee-save register cost, calculated once per machine function.
|
||||||
|
BlockFrequency CSRCost;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RAGreedy();
|
RAGreedy();
|
||||||
|
|
||||||
@ -343,6 +347,7 @@ private:
|
|||||||
unsigned tryAssignCSRFirstTime(LiveInterval &VirtReg, AllocationOrder &Order,
|
unsigned tryAssignCSRFirstTime(LiveInterval &VirtReg, AllocationOrder &Order,
|
||||||
unsigned PhysReg, unsigned &CostPerUseLimit,
|
unsigned PhysReg, unsigned &CostPerUseLimit,
|
||||||
SmallVectorImpl<unsigned> &NewVRegs);
|
SmallVectorImpl<unsigned> &NewVRegs);
|
||||||
|
void initializeCSRCost();
|
||||||
unsigned tryBlockSplit(LiveInterval&, AllocationOrder&,
|
unsigned tryBlockSplit(LiveInterval&, AllocationOrder&,
|
||||||
SmallVectorImpl<unsigned>&);
|
SmallVectorImpl<unsigned>&);
|
||||||
unsigned tryInstructionSplit(LiveInterval&, AllocationOrder&,
|
unsigned tryInstructionSplit(LiveInterval&, AllocationOrder&,
|
||||||
@ -2157,10 +2162,6 @@ unsigned RAGreedy::tryAssignCSRFirstTime(LiveInterval &VirtReg,
|
|||||||
unsigned PhysReg,
|
unsigned PhysReg,
|
||||||
unsigned &CostPerUseLimit,
|
unsigned &CostPerUseLimit,
|
||||||
SmallVectorImpl<unsigned> &NewVRegs) {
|
SmallVectorImpl<unsigned> &NewVRegs) {
|
||||||
// We use the larger one out of the command-line option and the value report
|
|
||||||
// by TRI.
|
|
||||||
BlockFrequency CSRCost(std::max((unsigned)CSRFirstTimeCost,
|
|
||||||
TRI->getCSRFirstUseCost()));
|
|
||||||
if (getStage(VirtReg) == RS_Spill && VirtReg.isSpillable()) {
|
if (getStage(VirtReg) == RS_Spill && VirtReg.isSpillable()) {
|
||||||
// We choose spill over using the CSR for the first time if the spill cost
|
// We choose spill over using the CSR for the first time if the spill cost
|
||||||
// is lower than CSRCost.
|
// is lower than CSRCost.
|
||||||
@ -2178,9 +2179,9 @@ unsigned RAGreedy::tryAssignCSRFirstTime(LiveInterval &VirtReg,
|
|||||||
// the cost of splitting is lower than CSRCost.
|
// the cost of splitting is lower than CSRCost.
|
||||||
SA->analyze(&VirtReg);
|
SA->analyze(&VirtReg);
|
||||||
unsigned NumCands = 0;
|
unsigned NumCands = 0;
|
||||||
unsigned BestCand =
|
BlockFrequency BestCost = CSRCost; // Don't modify CSRCost.
|
||||||
calculateRegionSplitCost(VirtReg, Order, CSRCost, NumCands,
|
unsigned BestCand = calculateRegionSplitCost(VirtReg, Order, BestCost,
|
||||||
true/*IgnoreCSR*/);
|
NumCands, true /*IgnoreCSR*/);
|
||||||
if (BestCand == NoCand)
|
if (BestCand == NoCand)
|
||||||
// Use the CSR if we can't find a region split below CSRCost.
|
// Use the CSR if we can't find a region split below CSRCost.
|
||||||
return PhysReg;
|
return PhysReg;
|
||||||
@ -2192,6 +2193,31 @@ unsigned RAGreedy::tryAssignCSRFirstTime(LiveInterval &VirtReg,
|
|||||||
return PhysReg;
|
return PhysReg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RAGreedy::initializeCSRCost() {
|
||||||
|
// We use the larger one out of the command-line option and the value report
|
||||||
|
// by TRI.
|
||||||
|
CSRCost = BlockFrequency(
|
||||||
|
std::max((unsigned)CSRFirstTimeCost, TRI->getCSRFirstUseCost()));
|
||||||
|
if (!CSRCost.getFrequency())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Raw cost is relative to Entry == 2^14; scale it appropriately.
|
||||||
|
uint64_t ActualEntry = MBFI->getEntryFreq();
|
||||||
|
if (!ActualEntry) {
|
||||||
|
CSRCost = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint64_t FixedEntry = 1 << 14;
|
||||||
|
if (ActualEntry < FixedEntry)
|
||||||
|
CSRCost *= BranchProbability(ActualEntry, FixedEntry);
|
||||||
|
else if (ActualEntry <= UINT32_MAX)
|
||||||
|
// Invert the fraction and divide.
|
||||||
|
CSRCost /= BranchProbability(FixedEntry, ActualEntry);
|
||||||
|
else
|
||||||
|
// Can't use BranchProbability in general, since it takes 32-bit numbers.
|
||||||
|
CSRCost = CSRCost.getFrequency() * (ActualEntry / FixedEntry);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned RAGreedy::selectOrSplitImpl(LiveInterval &VirtReg,
|
unsigned RAGreedy::selectOrSplitImpl(LiveInterval &VirtReg,
|
||||||
SmallVectorImpl<unsigned> &NewVRegs,
|
SmallVectorImpl<unsigned> &NewVRegs,
|
||||||
SmallVirtRegSet &FixedRegisters,
|
SmallVirtRegSet &FixedRegisters,
|
||||||
@ -2209,8 +2235,7 @@ unsigned RAGreedy::selectOrSplitImpl(LiveInterval &VirtReg,
|
|||||||
// When NewVRegs is not empty, we may have made decisions such as evicting
|
// When NewVRegs is not empty, we may have made decisions such as evicting
|
||||||
// a virtual register, go with the earlier decisions and use the physical
|
// a virtual register, go with the earlier decisions and use the physical
|
||||||
// register.
|
// register.
|
||||||
if ((CSRFirstTimeCost || TRI->getCSRFirstUseCost()) &&
|
if (CSRCost.getFrequency() && CSRFirstUse && NewVRegs.empty()) {
|
||||||
CSRFirstUse && NewVRegs.empty()) {
|
|
||||||
unsigned CSRReg = tryAssignCSRFirstTime(VirtReg, Order, PhysReg,
|
unsigned CSRReg = tryAssignCSRFirstTime(VirtReg, Order, PhysReg,
|
||||||
CostPerUseLimit, NewVRegs);
|
CostPerUseLimit, NewVRegs);
|
||||||
if (CSRReg || !NewVRegs.empty())
|
if (CSRReg || !NewVRegs.empty())
|
||||||
@ -2292,6 +2317,8 @@ bool RAGreedy::runOnMachineFunction(MachineFunction &mf) {
|
|||||||
SpillPlacer = &getAnalysis<SpillPlacement>();
|
SpillPlacer = &getAnalysis<SpillPlacement>();
|
||||||
DebugVars = &getAnalysis<LiveDebugVariables>();
|
DebugVars = &getAnalysis<LiveDebugVariables>();
|
||||||
|
|
||||||
|
initializeCSRCost();
|
||||||
|
|
||||||
calculateSpillWeightsAndHints(*LIS, mf, *Loops, *MBFI);
|
calculateSpillWeightsAndHints(*LIS, mf, *Loops, *MBFI);
|
||||||
|
|
||||||
DEBUG(LIS->dump());
|
DEBUG(LIS->dump());
|
||||||
|
@ -59,9 +59,26 @@ void SpillPlacement::getAnalysisUsage(AnalysisUsage &AU) const {
|
|||||||
MachineFunctionPass::getAnalysisUsage(AU);
|
MachineFunctionPass::getAnalysisUsage(AU);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static BlockFrequency Threshold;
|
||||||
|
}
|
||||||
|
|
||||||
/// Decision threshold. A node gets the output value 0 if the weighted sum of
|
/// Decision threshold. A node gets the output value 0 if the weighted sum of
|
||||||
/// its inputs falls in the open interval (-Threshold;Threshold).
|
/// its inputs falls in the open interval (-Threshold;Threshold).
|
||||||
static const BlockFrequency Threshold = 2;
|
static BlockFrequency getThreshold() { return Threshold; }
|
||||||
|
|
||||||
|
/// \brief Set the threshold for a given entry frequency.
|
||||||
|
///
|
||||||
|
/// Set the threshold relative to \c Entry. Since the threshold is used as a
|
||||||
|
/// bound on the open interval (-Threshold;Threshold), 1 is the minimum
|
||||||
|
/// threshold.
|
||||||
|
static void setThreshold(const BlockFrequency &Entry) {
|
||||||
|
// Apparently 2 is a good threshold when Entry==2^14, but we need to scale
|
||||||
|
// it. Divide by 2^13, rounding as appropriate.
|
||||||
|
uint64_t Freq = Entry.getFrequency();
|
||||||
|
uint64_t Scaled = (Freq >> 13) + bool(Freq & (1 << 12));
|
||||||
|
Threshold = std::max(UINT64_C(1), Scaled);
|
||||||
|
}
|
||||||
|
|
||||||
/// Node - Each edge bundle corresponds to a Hopfield node.
|
/// Node - Each edge bundle corresponds to a Hopfield node.
|
||||||
///
|
///
|
||||||
@ -110,7 +127,7 @@ struct SpillPlacement::Node {
|
|||||||
// the CFG.
|
// the CFG.
|
||||||
void clear() {
|
void clear() {
|
||||||
BiasN = BiasP = Value = 0;
|
BiasN = BiasP = Value = 0;
|
||||||
SumLinkWeights = Threshold;
|
SumLinkWeights = getThreshold();
|
||||||
Links.clear();
|
Links.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,9 +185,9 @@ struct SpillPlacement::Node {
|
|||||||
// 2. It helps tame rounding errors when the links nominally sum to 0.
|
// 2. It helps tame rounding errors when the links nominally sum to 0.
|
||||||
//
|
//
|
||||||
bool Before = preferReg();
|
bool Before = preferReg();
|
||||||
if (SumN >= SumP + Threshold)
|
if (SumN >= SumP + getThreshold())
|
||||||
Value = -1;
|
Value = -1;
|
||||||
else if (SumP >= SumN + Threshold)
|
else if (SumP >= SumN + getThreshold())
|
||||||
Value = 1;
|
Value = 1;
|
||||||
else
|
else
|
||||||
Value = 0;
|
Value = 0;
|
||||||
@ -189,6 +206,7 @@ bool SpillPlacement::runOnMachineFunction(MachineFunction &mf) {
|
|||||||
// Compute total ingoing and outgoing block frequencies for all bundles.
|
// Compute total ingoing and outgoing block frequencies for all bundles.
|
||||||
BlockFrequencies.resize(mf.getNumBlockIDs());
|
BlockFrequencies.resize(mf.getNumBlockIDs());
|
||||||
MBFI = &getAnalysis<MachineBlockFrequencyInfo>();
|
MBFI = &getAnalysis<MachineBlockFrequencyInfo>();
|
||||||
|
setThreshold(MBFI->getEntryFreq());
|
||||||
for (MachineFunction::iterator I = mf.begin(), E = mf.end(); I != E; ++I) {
|
for (MachineFunction::iterator I = mf.begin(), E = mf.end(); I != E; ++I) {
|
||||||
unsigned Num = I->getNumber();
|
unsigned Num = I->getNumber();
|
||||||
BlockFrequencies[Num] = MBFI->getBlockFreq(I);
|
BlockFrequencies[Num] = MBFI->getBlockFreq(I);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user