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 "LiveDebugVariables.h"
160b57cec5SDimitry Andric #include "RegAllocBase.h"
170b57cec5SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/CalcSpillWeights.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 {
operator ()__anonc7259a950111::CompSpillWeight4581ad6265SDimitry 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
61*fe013be4SDimitry 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:
77fe6060f1SDimitry Andric RABasic(const RegClassFilterFunc F = allocateAllRegClasses);
780b57cec5SDimitry Andric
790b57cec5SDimitry Andric /// Return the pass name.
getPassName() const800b57cec5SDimitry 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
spiller()870b57cec5SDimitry Andric Spiller &spiller() override { return *SpillerInstance; }
880b57cec5SDimitry Andric
enqueueImpl(const LiveInterval * LI)8981ad6265SDimitry Andric void enqueueImpl(const LiveInterval *LI) override { Queue.push(LI); }
900b57cec5SDimitry Andric
dequeue()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
getRequiredProperties() const1050b57cec5SDimitry Andric MachineFunctionProperties getRequiredProperties() const override {
1060b57cec5SDimitry Andric return MachineFunctionProperties().set(
1070b57cec5SDimitry Andric MachineFunctionProperties::Property::NoPHIs);
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric
getClearedProperties() const110e8d8bef9SDimitry 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)
INITIALIZE_PASS_DEPENDENCY(LiveDebugVariables)1320b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LiveDebugVariables)
1330b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
1340b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
1350b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(RegisterCoalescer)
1360b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineScheduler)
1370b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LiveStacks)
138fcaf7f86SDimitry Andric INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
1390b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
1400b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
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
LRE_WillShrinkVirtReg(Register VirtReg)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
RABasic(RegClassFilterFunc F)171fe6060f1SDimitry Andric RABasic::RABasic(RegClassFilterFunc F):
172fe6060f1SDimitry Andric MachineFunctionPass(ID),
173fe6060f1SDimitry Andric RegAllocBase(F) {
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const1760b57cec5SDimitry Andric void RABasic::getAnalysisUsage(AnalysisUsage &AU) const {
1770b57cec5SDimitry Andric AU.setPreservesCFG();
1780b57cec5SDimitry Andric AU.addRequired<AAResultsWrapperPass>();
1790b57cec5SDimitry Andric AU.addPreserved<AAResultsWrapperPass>();
1800b57cec5SDimitry Andric AU.addRequired<LiveIntervals>();
1810b57cec5SDimitry Andric AU.addPreserved<LiveIntervals>();
1820b57cec5SDimitry Andric AU.addPreserved<SlotIndexes>();
1830b57cec5SDimitry Andric AU.addRequired<LiveDebugVariables>();
1840b57cec5SDimitry Andric AU.addPreserved<LiveDebugVariables>();
1850b57cec5SDimitry Andric AU.addRequired<LiveStacks>();
1860b57cec5SDimitry Andric AU.addPreserved<LiveStacks>();
1870b57cec5SDimitry Andric AU.addRequired<MachineBlockFrequencyInfo>();
1880b57cec5SDimitry Andric AU.addPreserved<MachineBlockFrequencyInfo>();
1890b57cec5SDimitry Andric AU.addRequiredID(MachineDominatorsID);
1900b57cec5SDimitry Andric AU.addPreservedID(MachineDominatorsID);
1910b57cec5SDimitry Andric AU.addRequired<MachineLoopInfo>();
1920b57cec5SDimitry Andric AU.addPreserved<MachineLoopInfo>();
1930b57cec5SDimitry Andric AU.addRequired<VirtRegMap>();
1940b57cec5SDimitry Andric AU.addPreserved<VirtRegMap>();
1950b57cec5SDimitry Andric AU.addRequired<LiveRegMatrix>();
1960b57cec5SDimitry Andric AU.addPreserved<LiveRegMatrix>();
1970b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
1980b57cec5SDimitry Andric }
1990b57cec5SDimitry Andric
releaseMemory()2000b57cec5SDimitry Andric void RABasic::releaseMemory() {
2010b57cec5SDimitry Andric SpillerInstance.reset();
2020b57cec5SDimitry Andric }
2030b57cec5SDimitry Andric
2040b57cec5SDimitry Andric
2050b57cec5SDimitry Andric // Spill or split all live virtual registers currently unified under PhysReg
2060b57cec5SDimitry Andric // that interfere with VirtReg. The newly spilled or split live intervals are
2070b57cec5SDimitry Andric // returned by appending them to SplitVRegs.
spillInterferences(const LiveInterval & VirtReg,MCRegister PhysReg,SmallVectorImpl<Register> & SplitVRegs)20881ad6265SDimitry Andric bool RABasic::spillInterferences(const LiveInterval &VirtReg,
20981ad6265SDimitry Andric MCRegister PhysReg,
2105ffd83dbSDimitry Andric SmallVectorImpl<Register> &SplitVRegs) {
2110b57cec5SDimitry Andric // Record each interference and determine if all are spillable before mutating
2120b57cec5SDimitry Andric // either the union or live intervals.
21381ad6265SDimitry Andric SmallVector<const LiveInterval *, 8> Intfs;
2140b57cec5SDimitry Andric
2150b57cec5SDimitry Andric // Collect interferences assigned to any alias of the physical register.
216*fe013be4SDimitry Andric for (MCRegUnit Unit : TRI->regunits(PhysReg)) {
217*fe013be4SDimitry Andric LiveIntervalUnion::Query &Q = Matrix->query(VirtReg, Unit);
21881ad6265SDimitry Andric for (const auto *Intf : reverse(Q.interferingVRegs())) {
219e8d8bef9SDimitry Andric if (!Intf->isSpillable() || Intf->weight() > VirtReg.weight())
2200b57cec5SDimitry Andric return false;
2210b57cec5SDimitry Andric Intfs.push_back(Intf);
2220b57cec5SDimitry Andric }
2230b57cec5SDimitry Andric }
2240b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "spilling " << printReg(PhysReg, TRI)
2250b57cec5SDimitry Andric << " interferences with " << VirtReg << "\n");
2260b57cec5SDimitry Andric assert(!Intfs.empty() && "expected interference");
2270b57cec5SDimitry Andric
2280b57cec5SDimitry Andric // Spill each interfering vreg allocated to PhysReg or an alias.
2290b57cec5SDimitry Andric for (unsigned i = 0, e = Intfs.size(); i != e; ++i) {
23081ad6265SDimitry Andric const LiveInterval &Spill = *Intfs[i];
2310b57cec5SDimitry Andric
2320b57cec5SDimitry Andric // Skip duplicates.
233e8d8bef9SDimitry Andric if (!VRM->hasPhys(Spill.reg()))
2340b57cec5SDimitry Andric continue;
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andric // Deallocate the interfering vreg by removing it from the union.
2370b57cec5SDimitry Andric // A LiveInterval instance may not be in a union during modification!
2380b57cec5SDimitry Andric Matrix->unassign(Spill);
2390b57cec5SDimitry Andric
2400b57cec5SDimitry Andric // Spill the extracted interval.
2410b57cec5SDimitry Andric LiveRangeEdit LRE(&Spill, SplitVRegs, *MF, *LIS, VRM, this, &DeadRemats);
2420b57cec5SDimitry Andric spiller().spill(LRE);
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric return true;
2450b57cec5SDimitry Andric }
2460b57cec5SDimitry Andric
2470b57cec5SDimitry Andric // Driver for the register assignment and splitting heuristics.
2480b57cec5SDimitry Andric // Manages iteration over the LiveIntervalUnions.
2490b57cec5SDimitry Andric //
2500b57cec5SDimitry Andric // This is a minimal implementation of register assignment and splitting that
2510b57cec5SDimitry Andric // spills whenever we run out of registers.
2520b57cec5SDimitry Andric //
2530b57cec5SDimitry Andric // selectOrSplit can only be called once per live virtual register. We then do a
2540b57cec5SDimitry Andric // single interference test for each register the correct class until we find an
2550b57cec5SDimitry Andric // available register. So, the number of interference tests in the worst case is
2560b57cec5SDimitry Andric // |vregs| * |machineregs|. And since the number of interference tests is
2570b57cec5SDimitry Andric // minimal, there is no value in caching them outside the scope of
2580b57cec5SDimitry Andric // selectOrSplit().
selectOrSplit(const LiveInterval & VirtReg,SmallVectorImpl<Register> & SplitVRegs)25981ad6265SDimitry Andric MCRegister RABasic::selectOrSplit(const LiveInterval &VirtReg,
2605ffd83dbSDimitry Andric SmallVectorImpl<Register> &SplitVRegs) {
2610b57cec5SDimitry Andric // Populate a list of physical register spill candidates.
262e8d8bef9SDimitry Andric SmallVector<MCRegister, 8> PhysRegSpillCands;
2630b57cec5SDimitry Andric
2640b57cec5SDimitry Andric // Check for an available register in this class.
265e8d8bef9SDimitry Andric auto Order =
266e8d8bef9SDimitry Andric AllocationOrder::create(VirtReg.reg(), *VRM, RegClassInfo, Matrix);
267e8d8bef9SDimitry Andric for (MCRegister PhysReg : Order) {
268e8d8bef9SDimitry Andric assert(PhysReg.isValid());
2690b57cec5SDimitry Andric // Check for interference in PhysReg
2700b57cec5SDimitry Andric switch (Matrix->checkInterference(VirtReg, PhysReg)) {
2710b57cec5SDimitry Andric case LiveRegMatrix::IK_Free:
2720b57cec5SDimitry Andric // PhysReg is available, allocate it.
2730b57cec5SDimitry Andric return PhysReg;
2740b57cec5SDimitry Andric
2750b57cec5SDimitry Andric case LiveRegMatrix::IK_VirtReg:
2760b57cec5SDimitry Andric // Only virtual registers in the way, we may be able to spill them.
2770b57cec5SDimitry Andric PhysRegSpillCands.push_back(PhysReg);
2780b57cec5SDimitry Andric continue;
2790b57cec5SDimitry Andric
2800b57cec5SDimitry Andric default:
2810b57cec5SDimitry Andric // RegMask or RegUnit interference.
2820b57cec5SDimitry Andric continue;
2830b57cec5SDimitry Andric }
2840b57cec5SDimitry Andric }
2850b57cec5SDimitry Andric
2860b57cec5SDimitry Andric // Try to spill another interfering reg with less spill weight.
287fe6060f1SDimitry Andric for (MCRegister &PhysReg : PhysRegSpillCands) {
288fe6060f1SDimitry Andric if (!spillInterferences(VirtReg, PhysReg, SplitVRegs))
2890b57cec5SDimitry Andric continue;
2900b57cec5SDimitry Andric
291fe6060f1SDimitry Andric assert(!Matrix->checkInterference(VirtReg, PhysReg) &&
2920b57cec5SDimitry Andric "Interference after spill.");
2930b57cec5SDimitry Andric // Tell the caller to allocate to this newly freed physical register.
294fe6060f1SDimitry Andric return PhysReg;
2950b57cec5SDimitry Andric }
2960b57cec5SDimitry Andric
2970b57cec5SDimitry Andric // No other spill candidates were found, so spill the current VirtReg.
2980b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "spilling: " << VirtReg << '\n');
2990b57cec5SDimitry Andric if (!VirtReg.isSpillable())
3000b57cec5SDimitry Andric return ~0u;
3010b57cec5SDimitry Andric LiveRangeEdit LRE(&VirtReg, SplitVRegs, *MF, *LIS, VRM, this, &DeadRemats);
3020b57cec5SDimitry Andric spiller().spill(LRE);
3030b57cec5SDimitry Andric
3040b57cec5SDimitry Andric // The live virtual register requesting allocation was spilled, so tell
3050b57cec5SDimitry Andric // the caller not to allocate anything during this round.
3060b57cec5SDimitry Andric return 0;
3070b57cec5SDimitry Andric }
3080b57cec5SDimitry Andric
runOnMachineFunction(MachineFunction & mf)3090b57cec5SDimitry Andric bool RABasic::runOnMachineFunction(MachineFunction &mf) {
3100b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "********** BASIC REGISTER ALLOCATION **********\n"
3110b57cec5SDimitry Andric << "********** Function: " << mf.getName() << '\n');
3120b57cec5SDimitry Andric
3130b57cec5SDimitry Andric MF = &mf;
3140b57cec5SDimitry Andric RegAllocBase::init(getAnalysis<VirtRegMap>(),
3150b57cec5SDimitry Andric getAnalysis<LiveIntervals>(),
3160b57cec5SDimitry Andric getAnalysis<LiveRegMatrix>());
317e8d8bef9SDimitry Andric VirtRegAuxInfo VRAI(*MF, *LIS, *VRM, getAnalysis<MachineLoopInfo>(),
3180b57cec5SDimitry Andric getAnalysis<MachineBlockFrequencyInfo>());
319e8d8bef9SDimitry Andric VRAI.calculateSpillWeightsAndHints();
3200b57cec5SDimitry Andric
321fe6060f1SDimitry Andric SpillerInstance.reset(createInlineSpiller(*this, *MF, *VRM, VRAI));
3220b57cec5SDimitry Andric
3230b57cec5SDimitry Andric allocatePhysRegs();
3240b57cec5SDimitry Andric postOptimization();
3250b57cec5SDimitry Andric
3260b57cec5SDimitry Andric // Diagnostic output before rewriting
3270b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Post alloc VirtRegMap:\n" << *VRM << "\n");
3280b57cec5SDimitry Andric
3290b57cec5SDimitry Andric releaseMemory();
3300b57cec5SDimitry Andric return true;
3310b57cec5SDimitry Andric }
3320b57cec5SDimitry Andric
createBasicRegisterAllocator()333fe6060f1SDimitry Andric FunctionPass* llvm::createBasicRegisterAllocator() {
3340b57cec5SDimitry Andric return new RABasic();
3350b57cec5SDimitry Andric }
336fe6060f1SDimitry Andric
createBasicRegisterAllocator(RegClassFilterFunc F)337fe6060f1SDimitry Andric FunctionPass* llvm::createBasicRegisterAllocator(RegClassFilterFunc F) {
338fe6060f1SDimitry Andric return new RABasic(F);
339fe6060f1SDimitry Andric }
340