|  | //===-- RegAllocBasic.cpp - Basic Register Allocator ----------------------===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | /// | 
|  | /// \file | 
|  | /// This file defines the RABasic function pass, which provides a minimal | 
|  | /// implementation of the basic register allocator. | 
|  | /// | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "RegAllocBasic.h" | 
|  | #include "AllocationOrder.h" | 
|  | #include "llvm/Analysis/AliasAnalysis.h" | 
|  | #include "llvm/Analysis/ProfileSummaryInfo.h" | 
|  | #include "llvm/CodeGen/CalcSpillWeights.h" | 
|  | #include "llvm/CodeGen/LiveDebugVariables.h" | 
|  | #include "llvm/CodeGen/LiveIntervals.h" | 
|  | #include "llvm/CodeGen/LiveRegMatrix.h" | 
|  | #include "llvm/CodeGen/LiveStacks.h" | 
|  | #include "llvm/CodeGen/MachineBlockFrequencyInfo.h" | 
|  | #include "llvm/CodeGen/MachineDominators.h" | 
|  | #include "llvm/CodeGen/MachineLoopInfo.h" | 
|  | #include "llvm/CodeGen/Passes.h" | 
|  | #include "llvm/CodeGen/RegAllocRegistry.h" | 
|  | #include "llvm/CodeGen/VirtRegMap.h" | 
|  | #include "llvm/Pass.h" | 
|  | #include "llvm/Support/Debug.h" | 
|  | #include "llvm/Support/raw_ostream.h" | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | #define DEBUG_TYPE "regalloc" | 
|  |  | 
|  | static RegisterRegAlloc basicRegAlloc("basic", "basic register allocator", | 
|  | createBasicRegisterAllocator); | 
|  |  | 
|  | char RABasic::ID = 0; | 
|  |  | 
|  | char &llvm::RABasicID = RABasic::ID; | 
|  |  | 
|  | INITIALIZE_PASS_BEGIN(RABasic, "regallocbasic", "Basic Register Allocator", | 
|  | false, false) | 
|  | INITIALIZE_PASS_DEPENDENCY(LiveDebugVariablesWrapperLegacy) | 
|  | INITIALIZE_PASS_DEPENDENCY(SlotIndexesWrapperPass) | 
|  | INITIALIZE_PASS_DEPENDENCY(LiveIntervalsWrapperPass) | 
|  | INITIALIZE_PASS_DEPENDENCY(RegisterCoalescerLegacy) | 
|  | INITIALIZE_PASS_DEPENDENCY(MachineSchedulerLegacy) | 
|  | INITIALIZE_PASS_DEPENDENCY(LiveStacksWrapperLegacy) | 
|  | INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) | 
|  | INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass) | 
|  | INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass) | 
|  | INITIALIZE_PASS_DEPENDENCY(VirtRegMapWrapperLegacy) | 
|  | INITIALIZE_PASS_DEPENDENCY(LiveRegMatrixWrapperLegacy) | 
|  | INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass) | 
|  | INITIALIZE_PASS_END(RABasic, "regallocbasic", "Basic Register Allocator", false, | 
|  | false) | 
|  |  | 
|  | bool RABasic::LRE_CanEraseVirtReg(Register VirtReg) { | 
|  | LiveInterval &LI = LIS->getInterval(VirtReg); | 
|  | if (VRM->hasPhys(VirtReg)) { | 
|  | Matrix->unassign(LI); | 
|  | aboutToRemoveInterval(LI); | 
|  | return true; | 
|  | } | 
|  | // Unassigned virtreg is probably in the priority queue. | 
|  | // RegAllocBase will erase it after dequeueing. | 
|  | // Nonetheless, clear the live-range so that the debug | 
|  | // dump will show the right state for that VirtReg. | 
|  | LI.clear(); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | void RABasic::LRE_WillShrinkVirtReg(Register VirtReg) { | 
|  | if (!VRM->hasPhys(VirtReg)) | 
|  | return; | 
|  |  | 
|  | // Register is assigned, put it back on the queue for reassignment. | 
|  | LiveInterval &LI = LIS->getInterval(VirtReg); | 
|  | Matrix->unassign(LI); | 
|  | enqueue(&LI); | 
|  | } | 
|  |  | 
|  | RABasic::RABasic(RegAllocFilterFunc F) | 
|  | : MachineFunctionPass(ID), RegAllocBase(F) {} | 
|  |  | 
|  | void RABasic::getAnalysisUsage(AnalysisUsage &AU) const { | 
|  | AU.setPreservesCFG(); | 
|  | AU.addRequired<AAResultsWrapperPass>(); | 
|  | AU.addPreserved<AAResultsWrapperPass>(); | 
|  | AU.addRequired<LiveIntervalsWrapperPass>(); | 
|  | AU.addPreserved<LiveIntervalsWrapperPass>(); | 
|  | AU.addPreserved<SlotIndexesWrapperPass>(); | 
|  | AU.addRequired<LiveDebugVariablesWrapperLegacy>(); | 
|  | AU.addPreserved<LiveDebugVariablesWrapperLegacy>(); | 
|  | AU.addRequired<LiveStacksWrapperLegacy>(); | 
|  | AU.addPreserved<LiveStacksWrapperLegacy>(); | 
|  | AU.addRequired<ProfileSummaryInfoWrapperPass>(); | 
|  | AU.addRequired<MachineBlockFrequencyInfoWrapperPass>(); | 
|  | AU.addPreserved<MachineBlockFrequencyInfoWrapperPass>(); | 
|  | AU.addRequired<MachineDominatorTreeWrapperPass>(); | 
|  | AU.addRequiredID(MachineDominatorsID); | 
|  | AU.addPreservedID(MachineDominatorsID); | 
|  | AU.addRequired<MachineLoopInfoWrapperPass>(); | 
|  | AU.addPreserved<MachineLoopInfoWrapperPass>(); | 
|  | AU.addRequired<VirtRegMapWrapperLegacy>(); | 
|  | AU.addPreserved<VirtRegMapWrapperLegacy>(); | 
|  | AU.addRequired<LiveRegMatrixWrapperLegacy>(); | 
|  | AU.addPreserved<LiveRegMatrixWrapperLegacy>(); | 
|  | MachineFunctionPass::getAnalysisUsage(AU); | 
|  | } | 
|  |  | 
|  | void RABasic::releaseMemory() { | 
|  | SpillerInstance.reset(); | 
|  | } | 
|  |  | 
|  |  | 
|  | // Spill or split all live virtual registers currently unified under PhysReg | 
|  | // that interfere with VirtReg. The newly spilled or split live intervals are | 
|  | // returned by appending them to SplitVRegs. | 
|  | bool RABasic::spillInterferences(const LiveInterval &VirtReg, | 
|  | MCRegister PhysReg, | 
|  | SmallVectorImpl<Register> &SplitVRegs) { | 
|  | // Record each interference and determine if all are spillable before mutating | 
|  | // either the union or live intervals. | 
|  | SmallVector<const LiveInterval *, 8> Intfs; | 
|  |  | 
|  | // Collect interferences assigned to any alias of the physical register. | 
|  | for (MCRegUnit Unit : TRI->regunits(PhysReg)) { | 
|  | LiveIntervalUnion::Query &Q = Matrix->query(VirtReg, Unit); | 
|  | for (const auto *Intf : reverse(Q.interferingVRegs())) { | 
|  | if (!Intf->isSpillable() || Intf->weight() > VirtReg.weight()) | 
|  | return false; | 
|  | Intfs.push_back(Intf); | 
|  | } | 
|  | } | 
|  | LLVM_DEBUG(dbgs() << "spilling " << printReg(PhysReg, TRI) | 
|  | << " interferences with " << VirtReg << "\n"); | 
|  | assert(!Intfs.empty() && "expected interference"); | 
|  |  | 
|  | // Spill each interfering vreg allocated to PhysReg or an alias. | 
|  | for (const LiveInterval *Spill : Intfs) { | 
|  | // Skip duplicates. | 
|  | if (!VRM->hasPhys(Spill->reg())) | 
|  | continue; | 
|  |  | 
|  | // Deallocate the interfering vreg by removing it from the union. | 
|  | // A LiveInterval instance may not be in a union during modification! | 
|  | Matrix->unassign(*Spill); | 
|  |  | 
|  | // Spill the extracted interval. | 
|  | LiveRangeEdit LRE(Spill, SplitVRegs, *MF, *LIS, VRM, this, &DeadRemats); | 
|  | spiller().spill(LRE); | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | // Driver for the register assignment and splitting heuristics. | 
|  | // Manages iteration over the LiveIntervalUnions. | 
|  | // | 
|  | // This is a minimal implementation of register assignment and splitting that | 
|  | // spills whenever we run out of registers. | 
|  | // | 
|  | // selectOrSplit can only be called once per live virtual register. We then do a | 
|  | // single interference test for each register the correct class until we find an | 
|  | // available register. So, the number of interference tests in the worst case is | 
|  | // |vregs| * |machineregs|. And since the number of interference tests is | 
|  | // minimal, there is no value in caching them outside the scope of | 
|  | // selectOrSplit(). | 
|  | MCRegister RABasic::selectOrSplit(const LiveInterval &VirtReg, | 
|  | SmallVectorImpl<Register> &SplitVRegs) { | 
|  | // Populate a list of physical register spill candidates. | 
|  | SmallVector<MCRegister, 8> PhysRegSpillCands; | 
|  |  | 
|  | // Check for an available register in this class. | 
|  | auto Order = | 
|  | AllocationOrder::create(VirtReg.reg(), *VRM, RegClassInfo, Matrix); | 
|  | for (MCRegister PhysReg : Order) { | 
|  | assert(PhysReg.isValid()); | 
|  | // Check for interference in PhysReg | 
|  | switch (Matrix->checkInterference(VirtReg, PhysReg)) { | 
|  | case LiveRegMatrix::IK_Free: | 
|  | // PhysReg is available, allocate it. | 
|  | return PhysReg; | 
|  |  | 
|  | case LiveRegMatrix::IK_VirtReg: | 
|  | // Only virtual registers in the way, we may be able to spill them. | 
|  | PhysRegSpillCands.push_back(PhysReg); | 
|  | continue; | 
|  |  | 
|  | default: | 
|  | // RegMask or RegUnit interference. | 
|  | continue; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Try to spill another interfering reg with less spill weight. | 
|  | for (MCRegister &PhysReg : PhysRegSpillCands) { | 
|  | if (!spillInterferences(VirtReg, PhysReg, SplitVRegs)) | 
|  | continue; | 
|  |  | 
|  | assert(!Matrix->checkInterference(VirtReg, PhysReg) && | 
|  | "Interference after spill."); | 
|  | // Tell the caller to allocate to this newly freed physical register. | 
|  | return PhysReg; | 
|  | } | 
|  |  | 
|  | // No other spill candidates were found, so spill the current VirtReg. | 
|  | LLVM_DEBUG(dbgs() << "spilling: " << VirtReg << '\n'); | 
|  | if (!VirtReg.isSpillable()) | 
|  | return ~0u; | 
|  | LiveRangeEdit LRE(&VirtReg, SplitVRegs, *MF, *LIS, VRM, this, &DeadRemats); | 
|  | spiller().spill(LRE); | 
|  |  | 
|  | // The live virtual register requesting allocation was spilled, so tell | 
|  | // the caller not to allocate anything during this round. | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | bool RABasic::runOnMachineFunction(MachineFunction &mf) { | 
|  | LLVM_DEBUG(dbgs() << "********** BASIC REGISTER ALLOCATION **********\n" | 
|  | << "********** Function: " << mf.getName() << '\n'); | 
|  |  | 
|  | MF = &mf; | 
|  | auto &MBFI = getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI(); | 
|  | auto &LiveStks = getAnalysis<LiveStacksWrapperLegacy>().getLS(); | 
|  | auto &MDT = getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree(); | 
|  |  | 
|  | RegAllocBase::init(getAnalysis<VirtRegMapWrapperLegacy>().getVRM(), | 
|  | getAnalysis<LiveIntervalsWrapperPass>().getLIS(), | 
|  | getAnalysis<LiveRegMatrixWrapperLegacy>().getLRM()); | 
|  | VirtRegAuxInfo VRAI(*MF, *LIS, *VRM, | 
|  | getAnalysis<MachineLoopInfoWrapperPass>().getLI(), MBFI, | 
|  | &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI()); | 
|  | VRAI.calculateSpillWeightsAndHints(); | 
|  |  | 
|  | SpillerInstance.reset( | 
|  | createInlineSpiller({*LIS, LiveStks, MDT, MBFI}, *MF, *VRM, VRAI)); | 
|  |  | 
|  | allocatePhysRegs(); | 
|  | postOptimization(); | 
|  |  | 
|  | // Diagnostic output before rewriting | 
|  | LLVM_DEBUG(dbgs() << "Post alloc VirtRegMap:\n" << *VRM << "\n"); | 
|  |  | 
|  | releaseMemory(); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | FunctionPass* llvm::createBasicRegisterAllocator() { | 
|  | return new RABasic(); | 
|  | } | 
|  |  | 
|  | FunctionPass *llvm::createBasicRegisterAllocator(RegAllocFilterFunc F) { | 
|  | return new RABasic(F); | 
|  | } |