10b57cec5SDimitry Andric //===-- RegAllocBasic.cpp - Basic Register Allocator ----------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file defines the RABasic function pass, which provides a minimal 100b57cec5SDimitry Andric // implementation of the basic register allocator. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "AllocationOrder.h" 150b57cec5SDimitry Andric #include "RegAllocBase.h" 160b57cec5SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h" 170b57cec5SDimitry Andric #include "llvm/CodeGen/CalcSpillWeights.h" 18*0fca6ea1SDimitry Andric #include "llvm/CodeGen/LiveDebugVariables.h" 190b57cec5SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h" 200b57cec5SDimitry Andric #include "llvm/CodeGen/LiveRangeEdit.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/LiveRegMatrix.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/LiveStacks.h" 230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBlockFrequencyInfo.h" 240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h" 260b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h" 270b57cec5SDimitry Andric #include "llvm/CodeGen/RegAllocRegistry.h" 285ffd83dbSDimitry Andric #include "llvm/CodeGen/Spiller.h" 290b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 300b57cec5SDimitry Andric #include "llvm/CodeGen/VirtRegMap.h" 315ffd83dbSDimitry Andric #include "llvm/Pass.h" 320b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 330b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 340b57cec5SDimitry Andric #include <queue> 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric using namespace llvm; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric #define DEBUG_TYPE "regalloc" 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric static RegisterRegAlloc basicRegAlloc("basic", "basic register allocator", 410b57cec5SDimitry Andric createBasicRegisterAllocator); 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric namespace { 440b57cec5SDimitry Andric struct CompSpillWeight { 4581ad6265SDimitry Andric bool operator()(const LiveInterval *A, const LiveInterval *B) const { 46e8d8bef9SDimitry Andric return A->weight() < B->weight(); 470b57cec5SDimitry Andric } 480b57cec5SDimitry Andric }; 490b57cec5SDimitry Andric } 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric namespace { 520b57cec5SDimitry Andric /// RABasic provides a minimal implementation of the basic register allocation 530b57cec5SDimitry Andric /// algorithm. It prioritizes live virtual registers by spill weight and spills 540b57cec5SDimitry Andric /// whenever a register is unavailable. This is not practical in production but 550b57cec5SDimitry Andric /// provides a useful baseline both for measuring other allocators and comparing 560b57cec5SDimitry Andric /// the speed of the basic algorithm against other styles of allocators. 570b57cec5SDimitry Andric class RABasic : public MachineFunctionPass, 580b57cec5SDimitry Andric public RegAllocBase, 590b57cec5SDimitry Andric private LiveRangeEdit::Delegate { 600b57cec5SDimitry Andric // context 6106c3fb27SDimitry Andric MachineFunction *MF = nullptr; 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric // state 640b57cec5SDimitry Andric std::unique_ptr<Spiller> SpillerInstance; 6581ad6265SDimitry Andric std::priority_queue<const LiveInterval *, std::vector<const LiveInterval *>, 6681ad6265SDimitry Andric CompSpillWeight> 6781ad6265SDimitry Andric Queue; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric // Scratch space. Allocated here to avoid repeated malloc calls in 700b57cec5SDimitry Andric // selectOrSplit(). 710b57cec5SDimitry Andric BitVector UsableRegs; 720b57cec5SDimitry Andric 73e8d8bef9SDimitry Andric bool LRE_CanEraseVirtReg(Register) override; 74e8d8bef9SDimitry Andric void LRE_WillShrinkVirtReg(Register) override; 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric public: 77*0fca6ea1SDimitry Andric RABasic(const RegAllocFilterFunc F = nullptr); 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric /// Return the pass name. 800b57cec5SDimitry Andric StringRef getPassName() const override { return "Basic Register Allocator"; } 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric /// RABasic analysis usage. 830b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override; 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric void releaseMemory() override; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric Spiller &spiller() override { return *SpillerInstance; } 880b57cec5SDimitry Andric 8981ad6265SDimitry Andric void enqueueImpl(const LiveInterval *LI) override { Queue.push(LI); } 900b57cec5SDimitry Andric 9181ad6265SDimitry Andric const LiveInterval *dequeue() override { 920b57cec5SDimitry Andric if (Queue.empty()) 930b57cec5SDimitry Andric return nullptr; 9481ad6265SDimitry Andric const LiveInterval *LI = Queue.top(); 950b57cec5SDimitry Andric Queue.pop(); 960b57cec5SDimitry Andric return LI; 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric 9981ad6265SDimitry Andric MCRegister selectOrSplit(const LiveInterval &VirtReg, 1005ffd83dbSDimitry Andric SmallVectorImpl<Register> &SplitVRegs) override; 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric /// Perform register allocation. 1030b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &mf) override; 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 1060b57cec5SDimitry Andric return MachineFunctionProperties().set( 1070b57cec5SDimitry Andric MachineFunctionProperties::Property::NoPHIs); 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric 110e8d8bef9SDimitry Andric MachineFunctionProperties getClearedProperties() const override { 111e8d8bef9SDimitry Andric return MachineFunctionProperties().set( 112e8d8bef9SDimitry Andric MachineFunctionProperties::Property::IsSSA); 113e8d8bef9SDimitry Andric } 114e8d8bef9SDimitry Andric 1150b57cec5SDimitry Andric // Helper for spilling all live virtual registers currently unified under preg 1160b57cec5SDimitry Andric // that interfere with the most recently queried lvr. Return true if spilling 1170b57cec5SDimitry Andric // was successful, and append any new spilled/split intervals to splitLVRs. 11881ad6265SDimitry Andric bool spillInterferences(const LiveInterval &VirtReg, MCRegister PhysReg, 1195ffd83dbSDimitry Andric SmallVectorImpl<Register> &SplitVRegs); 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric static char ID; 1220b57cec5SDimitry Andric }; 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric char RABasic::ID = 0; 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric } // end anonymous namespace 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric char &llvm::RABasicID = RABasic::ID; 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(RABasic, "regallocbasic", "Basic Register Allocator", 1310b57cec5SDimitry Andric false, false) 1320b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LiveDebugVariables) 133*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(SlotIndexesWrapperPass) 134*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LiveIntervalsWrapperPass) 1350b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(RegisterCoalescer) 1360b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineScheduler) 1370b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LiveStacks) 138fcaf7f86SDimitry Andric INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) 139*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass) 140*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass) 1410b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(VirtRegMap) 1420b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LiveRegMatrix) 1430b57cec5SDimitry Andric INITIALIZE_PASS_END(RABasic, "regallocbasic", "Basic Register Allocator", false, 1440b57cec5SDimitry Andric false) 1450b57cec5SDimitry Andric 146e8d8bef9SDimitry Andric bool RABasic::LRE_CanEraseVirtReg(Register VirtReg) { 1470b57cec5SDimitry Andric LiveInterval &LI = LIS->getInterval(VirtReg); 1480b57cec5SDimitry Andric if (VRM->hasPhys(VirtReg)) { 1490b57cec5SDimitry Andric Matrix->unassign(LI); 1500b57cec5SDimitry Andric aboutToRemoveInterval(LI); 1510b57cec5SDimitry Andric return true; 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric // Unassigned virtreg is probably in the priority queue. 1540b57cec5SDimitry Andric // RegAllocBase will erase it after dequeueing. 1550b57cec5SDimitry Andric // Nonetheless, clear the live-range so that the debug 1560b57cec5SDimitry Andric // dump will show the right state for that VirtReg. 1570b57cec5SDimitry Andric LI.clear(); 1580b57cec5SDimitry Andric return false; 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric 161e8d8bef9SDimitry Andric void RABasic::LRE_WillShrinkVirtReg(Register VirtReg) { 1620b57cec5SDimitry Andric if (!VRM->hasPhys(VirtReg)) 1630b57cec5SDimitry Andric return; 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric // Register is assigned, put it back on the queue for reassignment. 1660b57cec5SDimitry Andric LiveInterval &LI = LIS->getInterval(VirtReg); 1670b57cec5SDimitry Andric Matrix->unassign(LI); 1680b57cec5SDimitry Andric enqueue(&LI); 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric 171*0fca6ea1SDimitry Andric RABasic::RABasic(RegAllocFilterFunc F) 172*0fca6ea1SDimitry Andric : MachineFunctionPass(ID), RegAllocBase(F) {} 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric void RABasic::getAnalysisUsage(AnalysisUsage &AU) const { 1750b57cec5SDimitry Andric AU.setPreservesCFG(); 1760b57cec5SDimitry Andric AU.addRequired<AAResultsWrapperPass>(); 1770b57cec5SDimitry Andric AU.addPreserved<AAResultsWrapperPass>(); 178*0fca6ea1SDimitry Andric AU.addRequired<LiveIntervalsWrapperPass>(); 179*0fca6ea1SDimitry Andric AU.addPreserved<LiveIntervalsWrapperPass>(); 180*0fca6ea1SDimitry Andric AU.addPreserved<SlotIndexesWrapperPass>(); 1810b57cec5SDimitry Andric AU.addRequired<LiveDebugVariables>(); 1820b57cec5SDimitry Andric AU.addPreserved<LiveDebugVariables>(); 1830b57cec5SDimitry Andric AU.addRequired<LiveStacks>(); 1840b57cec5SDimitry Andric AU.addPreserved<LiveStacks>(); 185*0fca6ea1SDimitry Andric AU.addRequired<MachineBlockFrequencyInfoWrapperPass>(); 186*0fca6ea1SDimitry Andric AU.addPreserved<MachineBlockFrequencyInfoWrapperPass>(); 1870b57cec5SDimitry Andric AU.addRequiredID(MachineDominatorsID); 1880b57cec5SDimitry Andric AU.addPreservedID(MachineDominatorsID); 189*0fca6ea1SDimitry Andric AU.addRequired<MachineLoopInfoWrapperPass>(); 190*0fca6ea1SDimitry Andric AU.addPreserved<MachineLoopInfoWrapperPass>(); 1910b57cec5SDimitry Andric AU.addRequired<VirtRegMap>(); 1920b57cec5SDimitry Andric AU.addPreserved<VirtRegMap>(); 1930b57cec5SDimitry Andric AU.addRequired<LiveRegMatrix>(); 1940b57cec5SDimitry Andric AU.addPreserved<LiveRegMatrix>(); 1950b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 1960b57cec5SDimitry Andric } 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric void RABasic::releaseMemory() { 1990b57cec5SDimitry Andric SpillerInstance.reset(); 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric // Spill or split all live virtual registers currently unified under PhysReg 2040b57cec5SDimitry Andric // that interfere with VirtReg. The newly spilled or split live intervals are 2050b57cec5SDimitry Andric // returned by appending them to SplitVRegs. 20681ad6265SDimitry Andric bool RABasic::spillInterferences(const LiveInterval &VirtReg, 20781ad6265SDimitry Andric MCRegister PhysReg, 2085ffd83dbSDimitry Andric SmallVectorImpl<Register> &SplitVRegs) { 2090b57cec5SDimitry Andric // Record each interference and determine if all are spillable before mutating 2100b57cec5SDimitry Andric // either the union or live intervals. 21181ad6265SDimitry Andric SmallVector<const LiveInterval *, 8> Intfs; 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric // Collect interferences assigned to any alias of the physical register. 21406c3fb27SDimitry Andric for (MCRegUnit Unit : TRI->regunits(PhysReg)) { 21506c3fb27SDimitry Andric LiveIntervalUnion::Query &Q = Matrix->query(VirtReg, Unit); 21681ad6265SDimitry Andric for (const auto *Intf : reverse(Q.interferingVRegs())) { 217e8d8bef9SDimitry Andric if (!Intf->isSpillable() || Intf->weight() > VirtReg.weight()) 2180b57cec5SDimitry Andric return false; 2190b57cec5SDimitry Andric Intfs.push_back(Intf); 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "spilling " << printReg(PhysReg, TRI) 2230b57cec5SDimitry Andric << " interferences with " << VirtReg << "\n"); 2240b57cec5SDimitry Andric assert(!Intfs.empty() && "expected interference"); 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric // Spill each interfering vreg allocated to PhysReg or an alias. 227*0fca6ea1SDimitry Andric for (const LiveInterval *Spill : Intfs) { 2280b57cec5SDimitry Andric // Skip duplicates. 229*0fca6ea1SDimitry Andric if (!VRM->hasPhys(Spill->reg())) 2300b57cec5SDimitry Andric continue; 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric // Deallocate the interfering vreg by removing it from the union. 2330b57cec5SDimitry Andric // A LiveInterval instance may not be in a union during modification! 234*0fca6ea1SDimitry Andric Matrix->unassign(*Spill); 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric // Spill the extracted interval. 237*0fca6ea1SDimitry Andric LiveRangeEdit LRE(Spill, SplitVRegs, *MF, *LIS, VRM, this, &DeadRemats); 2380b57cec5SDimitry Andric spiller().spill(LRE); 2390b57cec5SDimitry Andric } 2400b57cec5SDimitry Andric return true; 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric // Driver for the register assignment and splitting heuristics. 2440b57cec5SDimitry Andric // Manages iteration over the LiveIntervalUnions. 2450b57cec5SDimitry Andric // 2460b57cec5SDimitry Andric // This is a minimal implementation of register assignment and splitting that 2470b57cec5SDimitry Andric // spills whenever we run out of registers. 2480b57cec5SDimitry Andric // 2490b57cec5SDimitry Andric // selectOrSplit can only be called once per live virtual register. We then do a 2500b57cec5SDimitry Andric // single interference test for each register the correct class until we find an 2510b57cec5SDimitry Andric // available register. So, the number of interference tests in the worst case is 2520b57cec5SDimitry Andric // |vregs| * |machineregs|. And since the number of interference tests is 2530b57cec5SDimitry Andric // minimal, there is no value in caching them outside the scope of 2540b57cec5SDimitry Andric // selectOrSplit(). 25581ad6265SDimitry Andric MCRegister RABasic::selectOrSplit(const LiveInterval &VirtReg, 2565ffd83dbSDimitry Andric SmallVectorImpl<Register> &SplitVRegs) { 2570b57cec5SDimitry Andric // Populate a list of physical register spill candidates. 258e8d8bef9SDimitry Andric SmallVector<MCRegister, 8> PhysRegSpillCands; 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric // Check for an available register in this class. 261e8d8bef9SDimitry Andric auto Order = 262e8d8bef9SDimitry Andric AllocationOrder::create(VirtReg.reg(), *VRM, RegClassInfo, Matrix); 263e8d8bef9SDimitry Andric for (MCRegister PhysReg : Order) { 264e8d8bef9SDimitry Andric assert(PhysReg.isValid()); 2650b57cec5SDimitry Andric // Check for interference in PhysReg 2660b57cec5SDimitry Andric switch (Matrix->checkInterference(VirtReg, PhysReg)) { 2670b57cec5SDimitry Andric case LiveRegMatrix::IK_Free: 2680b57cec5SDimitry Andric // PhysReg is available, allocate it. 2690b57cec5SDimitry Andric return PhysReg; 2700b57cec5SDimitry Andric 2710b57cec5SDimitry Andric case LiveRegMatrix::IK_VirtReg: 2720b57cec5SDimitry Andric // Only virtual registers in the way, we may be able to spill them. 2730b57cec5SDimitry Andric PhysRegSpillCands.push_back(PhysReg); 2740b57cec5SDimitry Andric continue; 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric default: 2770b57cec5SDimitry Andric // RegMask or RegUnit interference. 2780b57cec5SDimitry Andric continue; 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric } 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric // Try to spill another interfering reg with less spill weight. 283fe6060f1SDimitry Andric for (MCRegister &PhysReg : PhysRegSpillCands) { 284fe6060f1SDimitry Andric if (!spillInterferences(VirtReg, PhysReg, SplitVRegs)) 2850b57cec5SDimitry Andric continue; 2860b57cec5SDimitry Andric 287fe6060f1SDimitry Andric assert(!Matrix->checkInterference(VirtReg, PhysReg) && 2880b57cec5SDimitry Andric "Interference after spill."); 2890b57cec5SDimitry Andric // Tell the caller to allocate to this newly freed physical register. 290fe6060f1SDimitry Andric return PhysReg; 2910b57cec5SDimitry Andric } 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric // No other spill candidates were found, so spill the current VirtReg. 2940b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "spilling: " << VirtReg << '\n'); 2950b57cec5SDimitry Andric if (!VirtReg.isSpillable()) 2960b57cec5SDimitry Andric return ~0u; 2970b57cec5SDimitry Andric LiveRangeEdit LRE(&VirtReg, SplitVRegs, *MF, *LIS, VRM, this, &DeadRemats); 2980b57cec5SDimitry Andric spiller().spill(LRE); 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric // The live virtual register requesting allocation was spilled, so tell 3010b57cec5SDimitry Andric // the caller not to allocate anything during this round. 3020b57cec5SDimitry Andric return 0; 3030b57cec5SDimitry Andric } 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric bool RABasic::runOnMachineFunction(MachineFunction &mf) { 3060b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "********** BASIC REGISTER ALLOCATION **********\n" 3070b57cec5SDimitry Andric << "********** Function: " << mf.getName() << '\n'); 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric MF = &mf; 3100b57cec5SDimitry Andric RegAllocBase::init(getAnalysis<VirtRegMap>(), 311*0fca6ea1SDimitry Andric getAnalysis<LiveIntervalsWrapperPass>().getLIS(), 3120b57cec5SDimitry Andric getAnalysis<LiveRegMatrix>()); 313*0fca6ea1SDimitry Andric VirtRegAuxInfo VRAI( 314*0fca6ea1SDimitry Andric *MF, *LIS, *VRM, getAnalysis<MachineLoopInfoWrapperPass>().getLI(), 315*0fca6ea1SDimitry Andric getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI()); 316e8d8bef9SDimitry Andric VRAI.calculateSpillWeightsAndHints(); 3170b57cec5SDimitry Andric 318fe6060f1SDimitry Andric SpillerInstance.reset(createInlineSpiller(*this, *MF, *VRM, VRAI)); 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric allocatePhysRegs(); 3210b57cec5SDimitry Andric postOptimization(); 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric // Diagnostic output before rewriting 3240b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Post alloc VirtRegMap:\n" << *VRM << "\n"); 3250b57cec5SDimitry Andric 3260b57cec5SDimitry Andric releaseMemory(); 3270b57cec5SDimitry Andric return true; 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric 330fe6060f1SDimitry Andric FunctionPass* llvm::createBasicRegisterAllocator() { 3310b57cec5SDimitry Andric return new RABasic(); 3320b57cec5SDimitry Andric } 333fe6060f1SDimitry Andric 334*0fca6ea1SDimitry Andric FunctionPass *llvm::createBasicRegisterAllocator(RegAllocFilterFunc F) { 335fe6060f1SDimitry Andric return new RABasic(F); 336fe6060f1SDimitry Andric } 337