diff options
| author | 2017-01-24 08:32:59 +0000 | |
|---|---|---|
| committer | 2017-01-24 08:32:59 +0000 | |
| commit | 53d771aafdbe5b919f264f53cba3788e2c4cffd2 (patch) | |
| tree | 7eca39498be0ff1e3a6daf583cd9ca5886bb2636 /gnu/llvm/lib/CodeGen/RegAllocGreedy.cpp | |
| parent | In preparation of compiling our kernels with -ffreestanding, explicitly map (diff) | |
| download | wireguard-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.cpp | 107 |
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); |
