summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/lib/CodeGen/RegAllocGreedy.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2017-01-24 08:32:59 +0000
committerpatrick <patrick@openbsd.org>2017-01-24 08:32:59 +0000
commit53d771aafdbe5b919f264f53cba3788e2c4cffd2 (patch)
tree7eca39498be0ff1e3a6daf583cd9ca5886bb2636 /gnu/llvm/lib/CodeGen/RegAllocGreedy.cpp
parentIn preparation of compiling our kernels with -ffreestanding, explicitly map (diff)
downloadwireguard-openbsd-53d771aafdbe5b919f264f53cba3788e2c4cffd2.tar.xz
wireguard-openbsd-53d771aafdbe5b919f264f53cba3788e2c4cffd2.zip
Import LLVM 4.0.0 rc1 including clang and lld to help the current
development effort on OpenBSD/arm64.
Diffstat (limited to 'gnu/llvm/lib/CodeGen/RegAllocGreedy.cpp')
-rw-r--r--gnu/llvm/lib/CodeGen/RegAllocGreedy.cpp107
1 files changed, 76 insertions, 31 deletions
diff --git a/gnu/llvm/lib/CodeGen/RegAllocGreedy.cpp b/gnu/llvm/lib/CodeGen/RegAllocGreedy.cpp
index c4d4b1eadf3..c47cfb1b986 100644
--- a/gnu/llvm/lib/CodeGen/RegAllocGreedy.cpp
+++ b/gnu/llvm/lib/CodeGen/RegAllocGreedy.cpp
@@ -61,8 +61,7 @@ static cl::opt<SplitEditor::ComplementSpillMode> SplitSpillMode(
cl::desc("Spill mode for splitting live ranges"),
cl::values(clEnumValN(SplitEditor::SM_Partition, "default", "Default"),
clEnumValN(SplitEditor::SM_Size, "size", "Optimize for size"),
- clEnumValN(SplitEditor::SM_Speed, "speed", "Optimize for speed"),
- clEnumValEnd),
+ clEnumValN(SplitEditor::SM_Speed, "speed", "Optimize for speed")),
cl::init(SplitEditor::SM_Speed));
static cl::opt<unsigned>
@@ -318,9 +317,7 @@ public:
RAGreedy();
/// Return the pass name.
- const char* getPassName() const override {
- return "Greedy Register Allocator";
- }
+ StringRef getPassName() const override { return "Greedy Register Allocator"; }
/// RAGreedy analysis usage.
void getAnalysisUsage(AnalysisUsage &AU) const override;
@@ -334,6 +331,11 @@ public:
/// Perform register allocation.
bool runOnMachineFunction(MachineFunction &mf) override;
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::NoPHIs);
+ }
+
static char ID;
private:
@@ -421,6 +423,24 @@ private:
} // end anonymous namespace
char RAGreedy::ID = 0;
+char &llvm::RAGreedyID = RAGreedy::ID;
+
+INITIALIZE_PASS_BEGIN(RAGreedy, "greedy",
+ "Greedy Register Allocator", false, false)
+INITIALIZE_PASS_DEPENDENCY(LiveDebugVariables)
+INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
+INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
+INITIALIZE_PASS_DEPENDENCY(RegisterCoalescer)
+INITIALIZE_PASS_DEPENDENCY(MachineScheduler)
+INITIALIZE_PASS_DEPENDENCY(LiveStacks)
+INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
+INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
+INITIALIZE_PASS_DEPENDENCY(VirtRegMap)
+INITIALIZE_PASS_DEPENDENCY(LiveRegMatrix)
+INITIALIZE_PASS_DEPENDENCY(EdgeBundles)
+INITIALIZE_PASS_DEPENDENCY(SpillPlacement)
+INITIALIZE_PASS_END(RAGreedy, "greedy",
+ "Greedy Register Allocator", false, false)
#ifndef NDEBUG
const char *const RAGreedy::StageName[] = {
@@ -444,19 +464,6 @@ FunctionPass* llvm::createGreedyRegisterAllocator() {
}
RAGreedy::RAGreedy(): MachineFunctionPass(ID) {
- initializeLiveDebugVariablesPass(*PassRegistry::getPassRegistry());
- initializeSlotIndexesPass(*PassRegistry::getPassRegistry());
- initializeLiveIntervalsPass(*PassRegistry::getPassRegistry());
- initializeSlotIndexesPass(*PassRegistry::getPassRegistry());
- initializeRegisterCoalescerPass(*PassRegistry::getPassRegistry());
- initializeMachineSchedulerPass(*PassRegistry::getPassRegistry());
- initializeLiveStacksPass(*PassRegistry::getPassRegistry());
- initializeMachineDominatorTreePass(*PassRegistry::getPassRegistry());
- initializeMachineLoopInfoPass(*PassRegistry::getPassRegistry());
- initializeVirtRegMapPass(*PassRegistry::getPassRegistry());
- initializeLiveRegMatrixPass(*PassRegistry::getPassRegistry());
- initializeEdgeBundlesPass(*PassRegistry::getPassRegistry());
- initializeSpillPlacementPass(*PassRegistry::getPassRegistry());
}
void RAGreedy::getAnalysisUsage(AnalysisUsage &AU) const {
@@ -639,6 +646,9 @@ unsigned RAGreedy::tryAssign(LiveInterval &VirtReg,
evictInterference(VirtReg, Hint, NewVRegs);
return Hint;
}
+ // Record the missed hint, we may be able to recover
+ // at the end if the surrounding allocation changed.
+ SetOfBrokenHints.insert(&VirtReg);
}
// Try to evict interference from a cheaper alternative.
@@ -859,7 +869,8 @@ unsigned RAGreedy::tryEvict(LiveInterval &VirtReg,
AllocationOrder &Order,
SmallVectorImpl<unsigned> &NewVRegs,
unsigned CostPerUseLimit) {
- NamedRegionTimer T("Evict", TimerGroupName, TimePassesIsEnabled);
+ NamedRegionTimer T("evict", "Evict", TimerGroupName, TimerGroupDescription,
+ TimePassesIsEnabled);
// Keep track of the cheapest interference seen so far.
EvictionCost BestCost;
@@ -1957,7 +1968,8 @@ unsigned RAGreedy::trySplit(LiveInterval &VirtReg, AllocationOrder &Order,
// Local intervals are handled separately.
if (LIS->intervalIsInOneMBB(VirtReg)) {
- NamedRegionTimer T("Local Splitting", TimerGroupName, TimePassesIsEnabled);
+ NamedRegionTimer T("local_split", "Local Splitting", TimerGroupName,
+ TimerGroupDescription, TimePassesIsEnabled);
SA->analyze(&VirtReg);
unsigned PhysReg = tryLocalSplit(VirtReg, Order, NewVRegs);
if (PhysReg || !NewVRegs.empty())
@@ -1965,7 +1977,8 @@ unsigned RAGreedy::trySplit(LiveInterval &VirtReg, AllocationOrder &Order,
return tryInstructionSplit(VirtReg, Order, NewVRegs);
}
- NamedRegionTimer T("Global Splitting", TimerGroupName, TimePassesIsEnabled);
+ NamedRegionTimer T("global_split", "Global Splitting", TimerGroupName,
+ TimerGroupDescription, TimePassesIsEnabled);
SA->analyze(&VirtReg);
@@ -2103,6 +2116,7 @@ unsigned RAGreedy::tryLastChanceRecoloring(LiveInterval &VirtReg,
// Mark VirtReg as fixed, i.e., it will not be recolored pass this point in
// this recoloring "session".
FixedRegisters.insert(VirtReg.reg);
+ SmallVector<unsigned, 4> CurrentNewVRegs;
Order.rewind();
while (unsigned PhysReg = Order.next()) {
@@ -2110,6 +2124,7 @@ unsigned RAGreedy::tryLastChanceRecoloring(LiveInterval &VirtReg,
<< PrintReg(PhysReg, TRI) << '\n');
RecoloringCandidates.clear();
VirtRegToPhysReg.clear();
+ CurrentNewVRegs.clear();
// It is only possible to recolor virtual register interference.
if (Matrix->checkInterference(VirtReg, PhysReg) >
@@ -2154,8 +2169,11 @@ unsigned RAGreedy::tryLastChanceRecoloring(LiveInterval &VirtReg,
// If we cannot recolor all the interferences, we will have to start again
// at this point for the next physical register.
SmallVirtRegSet SaveFixedRegisters(FixedRegisters);
- if (tryRecoloringCandidates(RecoloringQueue, NewVRegs, FixedRegisters,
- Depth)) {
+ if (tryRecoloringCandidates(RecoloringQueue, CurrentNewVRegs,
+ FixedRegisters, Depth)) {
+ // Push the queued vregs into the main queue.
+ for (unsigned NewVReg : CurrentNewVRegs)
+ NewVRegs.push_back(NewVReg);
// Do not mess up with the global assignment process.
// I.e., VirtReg must be unassigned.
Matrix->unassign(VirtReg);
@@ -2169,6 +2187,18 @@ unsigned RAGreedy::tryLastChanceRecoloring(LiveInterval &VirtReg,
FixedRegisters = SaveFixedRegisters;
Matrix->unassign(VirtReg);
+ // For a newly created vreg which is also in RecoloringCandidates,
+ // don't add it to NewVRegs because its physical register will be restored
+ // below. Other vregs in CurrentNewVRegs are created by calling
+ // selectOrSplit and should be added into NewVRegs.
+ for (SmallVectorImpl<unsigned>::iterator Next = CurrentNewVRegs.begin(),
+ End = CurrentNewVRegs.end();
+ Next != End; ++Next) {
+ if (RecoloringCandidates.count(&LIS->getInterval(*Next)))
+ continue;
+ NewVRegs.push_back(*Next);
+ }
+
for (SmallLISet::iterator It = RecoloringCandidates.begin(),
EndIt = RecoloringCandidates.end();
It != EndIt; ++It) {
@@ -2201,10 +2231,21 @@ bool RAGreedy::tryRecoloringCandidates(PQueue &RecoloringQueue,
DEBUG(dbgs() << "Try to recolor: " << *LI << '\n');
unsigned PhysReg;
PhysReg = selectOrSplitImpl(*LI, NewVRegs, FixedRegisters, Depth + 1);
- if (PhysReg == ~0u || !PhysReg)
+ // When splitting happens, the live-range may actually be empty.
+ // In that case, this is okay to continue the recoloring even
+ // if we did not find an alternative color for it. Indeed,
+ // there will not be anything to color for LI in the end.
+ if (PhysReg == ~0u || (!PhysReg && !LI->empty()))
return false;
+
+ if (!PhysReg) {
+ assert(LI->empty() && "Only empty live-range do not require a register");
+ DEBUG(dbgs() << "Recoloring of " << *LI << " succeeded. Empty LI.\n");
+ continue;
+ }
DEBUG(dbgs() << "Recoloring of " << *LI
<< " succeeded with: " << PrintReg(PhysReg, TRI) << '\n');
+
Matrix->assign(*LI, PhysReg);
FixedRegisters.insert(LI->reg);
}
@@ -2519,7 +2560,7 @@ unsigned RAGreedy::selectOrSplitImpl(LiveInterval &VirtReg,
return PhysReg;
}
- assert(NewVRegs.empty() && "Cannot append to existing NewVRegs");
+ assert((NewVRegs.empty() || Depth) && "Cannot append to existing NewVRegs");
// The first time we see a live range, don't try to split or spill.
// Wait until the second time, when all smaller ranges have been allocated.
@@ -2531,17 +2572,20 @@ unsigned RAGreedy::selectOrSplitImpl(LiveInterval &VirtReg,
return 0;
}
+ if (Stage < RS_Spill) {
+ // Try splitting VirtReg or interferences.
+ unsigned NewVRegSizeBefore = NewVRegs.size();
+ unsigned PhysReg = trySplit(VirtReg, Order, NewVRegs);
+ if (PhysReg || (NewVRegs.size() - NewVRegSizeBefore))
+ return PhysReg;
+ }
+
// If we couldn't allocate a register from spilling, there is probably some
// invalid inline assembly. The base class wil report it.
if (Stage >= RS_Done || !VirtReg.isSpillable())
return tryLastChanceRecoloring(VirtReg, Order, NewVRegs, FixedRegisters,
Depth);
- // Try splitting VirtReg or interferences.
- unsigned PhysReg = trySplit(VirtReg, Order, NewVRegs);
- if (PhysReg || !NewVRegs.empty())
- return PhysReg;
-
// Finally spill VirtReg itself.
if (EnableDeferredSpilling && getStage(VirtReg) < RS_Memory) {
// TODO: This is experimental and in particular, we do not model
@@ -2552,7 +2596,8 @@ unsigned RAGreedy::selectOrSplitImpl(LiveInterval &VirtReg,
DEBUG(dbgs() << "Do as if this register is in memory\n");
NewVRegs.push_back(VirtReg.reg);
} else {
- NamedRegionTimer T("Spiller", TimerGroupName, TimePassesIsEnabled);
+ NamedRegionTimer T("spill", "Spiller", TimerGroupName,
+ TimerGroupDescription, TimePassesIsEnabled);
LiveRangeEdit LRE(&VirtReg, NewVRegs, *MF, *LIS, VRM, this, &DeadRemats);
spiller().spill(LRE);
setStage(NewVRegs.begin(), NewVRegs.end(), RS_Done);