diff options
Diffstat (limited to 'llvm/lib/CodeGen/RegAllocFast.cpp')
-rw-r--r-- | llvm/lib/CodeGen/RegAllocFast.cpp | 201 |
1 files changed, 124 insertions, 77 deletions
diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp index 6740e1f..09ce8c4 100644 --- a/llvm/lib/CodeGen/RegAllocFast.cpp +++ b/llvm/lib/CodeGen/RegAllocFast.cpp @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/CodeGen/RegAllocFast.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IndexedMap.h" @@ -174,14 +175,12 @@ private: DenseMap<const MachineInstr *, uint64_t> Instr2PosIndex; }; -class RegAllocFast : public MachineFunctionPass { +class RegAllocFastImpl { public: - static char ID; - - RegAllocFast(const RegClassFilterFunc F = allocateAllRegClasses, - bool ClearVirtRegs_ = true) - : MachineFunctionPass(ID), ShouldAllocateClass(F), - StackSlotForVirtReg(-1), ClearVirtRegs(ClearVirtRegs_) {} + RegAllocFastImpl(const RegClassFilterFunc F = allocateAllRegClasses, + bool ClearVirtRegs_ = true) + : ShouldAllocateClass(F), StackSlotForVirtReg(-1), + ClearVirtRegs(ClearVirtRegs_) {} private: MachineFrameInfo *MFI = nullptr; @@ -197,8 +196,6 @@ private: /// Maps virtual regs to the frame index where these values are spilled. IndexedMap<int, VirtReg2IndexFunctor> StackSlotForVirtReg; - bool ClearVirtRegs; - /// Everything we know about a live virtual register. struct LiveReg { MachineInstr *LastUse = nullptr; ///< Last instr to use reg. @@ -318,35 +315,11 @@ private: }; public: - StringRef getPassName() const override { return "Fast Register Allocator"; } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesCFG(); - MachineFunctionPass::getAnalysisUsage(AU); - } - - MachineFunctionProperties getRequiredProperties() const override { - return MachineFunctionProperties().set( - MachineFunctionProperties::Property::NoPHIs); - } - - MachineFunctionProperties getSetProperties() const override { - if (ClearVirtRegs) { - return MachineFunctionProperties().set( - MachineFunctionProperties::Property::NoVRegs); - } - - return MachineFunctionProperties(); - } + bool ClearVirtRegs; - MachineFunctionProperties getClearedProperties() const override { - return MachineFunctionProperties().set( - MachineFunctionProperties::Property::IsSSA); - } + bool runOnMachineFunction(MachineFunction &MF); private: - bool runOnMachineFunction(MachineFunction &MF) override; - void allocateBasicBlock(MachineBasicBlock &MBB); void addRegClassDefCounts(std::vector<unsigned> &RegClassDefCounts, @@ -408,6 +381,47 @@ private: void dumpState() const; }; +class RegAllocFast : public MachineFunctionPass { + RegAllocFastImpl Impl; + +public: + static char ID; + + RegAllocFast(const RegClassFilterFunc F = allocateAllRegClasses, + bool ClearVirtRegs_ = true) + : MachineFunctionPass(ID), Impl(F, ClearVirtRegs_) {} + + bool runOnMachineFunction(MachineFunction &MF) override { + return Impl.runOnMachineFunction(MF); + } + + StringRef getPassName() const override { return "Fast Register Allocator"; } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::NoPHIs); + } + + MachineFunctionProperties getSetProperties() const override { + if (Impl.ClearVirtRegs) { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::NoVRegs); + } + + return MachineFunctionProperties(); + } + + MachineFunctionProperties getClearedProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::IsSSA); + } +}; + } // end anonymous namespace char RegAllocFast::ID = 0; @@ -415,18 +429,18 @@ char RegAllocFast::ID = 0; INITIALIZE_PASS(RegAllocFast, "regallocfast", "Fast Register Allocator", false, false) -bool RegAllocFast::shouldAllocateRegister(const Register Reg) const { +bool RegAllocFastImpl::shouldAllocateRegister(const Register Reg) const { assert(Reg.isVirtual()); const TargetRegisterClass &RC = *MRI->getRegClass(Reg); return ShouldAllocateClass(*TRI, RC); } -void RegAllocFast::setPhysRegState(MCPhysReg PhysReg, unsigned NewState) { +void RegAllocFastImpl::setPhysRegState(MCPhysReg PhysReg, unsigned NewState) { for (MCRegUnit Unit : TRI->regunits(PhysReg)) RegUnitStates[Unit] = NewState; } -bool RegAllocFast::isPhysRegFree(MCPhysReg PhysReg) const { +bool RegAllocFastImpl::isPhysRegFree(MCPhysReg PhysReg) const { for (MCRegUnit Unit : TRI->regunits(PhysReg)) { if (RegUnitStates[Unit] != regFree) return false; @@ -436,7 +450,7 @@ bool RegAllocFast::isPhysRegFree(MCPhysReg PhysReg) const { /// This allocates space for the specified virtual register to be held on the /// stack. -int RegAllocFast::getStackSpaceFor(Register VirtReg) { +int RegAllocFastImpl::getStackSpaceFor(Register VirtReg) { // Find the location Reg would belong... int SS = StackSlotForVirtReg[VirtReg]; // Already has space allocated? @@ -464,7 +478,7 @@ static bool dominates(InstrPosIndexes &PosIndexes, const MachineInstr &A, } /// Returns false if \p VirtReg is known to not live out of the current block. -bool RegAllocFast::mayLiveOut(Register VirtReg) { +bool RegAllocFastImpl::mayLiveOut(Register VirtReg) { if (MayLiveAcrossBlocks.test(Register::virtReg2Index(VirtReg))) { // Cannot be live-out if there are no successors. return !MBB->succ_empty(); @@ -517,7 +531,7 @@ bool RegAllocFast::mayLiveOut(Register VirtReg) { } /// Returns false if \p VirtReg is known to not be live into the current block. -bool RegAllocFast::mayLiveIn(Register VirtReg) { +bool RegAllocFastImpl::mayLiveIn(Register VirtReg) { if (MayLiveAcrossBlocks.test(Register::virtReg2Index(VirtReg))) return !MBB->pred_empty(); @@ -536,8 +550,9 @@ bool RegAllocFast::mayLiveIn(Register VirtReg) { /// Insert spill instruction for \p AssignedReg before \p Before. Update /// DBG_VALUEs with \p VirtReg operands with the stack slot. -void RegAllocFast::spill(MachineBasicBlock::iterator Before, Register VirtReg, - MCPhysReg AssignedReg, bool Kill, bool LiveOut) { +void RegAllocFastImpl::spill(MachineBasicBlock::iterator Before, + Register VirtReg, MCPhysReg AssignedReg, bool Kill, + bool LiveOut) { LLVM_DEBUG(dbgs() << "Spilling " << printReg(VirtReg, TRI) << " in " << printReg(AssignedReg, TRI)); int FI = getStackSpaceFor(VirtReg); @@ -596,8 +611,8 @@ void RegAllocFast::spill(MachineBasicBlock::iterator Before, Register VirtReg, } /// Insert reload instruction for \p PhysReg before \p Before. -void RegAllocFast::reload(MachineBasicBlock::iterator Before, Register VirtReg, - MCPhysReg PhysReg) { +void RegAllocFastImpl::reload(MachineBasicBlock::iterator Before, + Register VirtReg, MCPhysReg PhysReg) { LLVM_DEBUG(dbgs() << "Reloading " << printReg(VirtReg, TRI) << " into " << printReg(PhysReg, TRI) << '\n'); int FI = getStackSpaceFor(VirtReg); @@ -610,7 +625,7 @@ void RegAllocFast::reload(MachineBasicBlock::iterator Before, Register VirtReg, /// This is not just MBB.begin() because surprisingly we have EH_LABEL /// instructions marking the begin of a basic block. This means we must insert /// new instructions after such labels... -MachineBasicBlock::iterator RegAllocFast::getMBBBeginInsertionPoint( +MachineBasicBlock::iterator RegAllocFastImpl::getMBBBeginInsertionPoint( MachineBasicBlock &MBB, SmallSet<Register, 2> &PrologLiveIns) const { MachineBasicBlock::iterator I = MBB.begin(); while (I != MBB.end()) { @@ -637,7 +652,7 @@ MachineBasicBlock::iterator RegAllocFast::getMBBBeginInsertionPoint( } /// Reload all currently assigned virtual registers. -void RegAllocFast::reloadAtBegin(MachineBasicBlock &MBB) { +void RegAllocFastImpl::reloadAtBegin(MachineBasicBlock &MBB) { if (LiveVirtRegs.empty()) return; @@ -680,7 +695,7 @@ void RegAllocFast::reloadAtBegin(MachineBasicBlock &MBB) { /// Handle the direct use of a physical register. Check that the register is /// not used by a virtreg. Kill the physreg, marking it free. This may add /// implicit kills to MO->getParent() and invalidate MO. -bool RegAllocFast::usePhysReg(MachineInstr &MI, MCPhysReg Reg) { +bool RegAllocFastImpl::usePhysReg(MachineInstr &MI, MCPhysReg Reg) { assert(Register::isPhysicalRegister(Reg) && "expected physreg"); bool displacedAny = displacePhysReg(MI, Reg); setPhysRegState(Reg, regPreAssigned); @@ -688,7 +703,7 @@ bool RegAllocFast::usePhysReg(MachineInstr &MI, MCPhysReg Reg) { return displacedAny; } -bool RegAllocFast::definePhysReg(MachineInstr &MI, MCPhysReg Reg) { +bool RegAllocFastImpl::definePhysReg(MachineInstr &MI, MCPhysReg Reg) { bool displacedAny = displacePhysReg(MI, Reg); setPhysRegState(Reg, regPreAssigned); return displacedAny; @@ -697,7 +712,7 @@ bool RegAllocFast::definePhysReg(MachineInstr &MI, MCPhysReg Reg) { /// Mark PhysReg as reserved or free after spilling any virtregs. This is very /// similar to defineVirtReg except the physreg is reserved instead of /// allocated. -bool RegAllocFast::displacePhysReg(MachineInstr &MI, MCPhysReg PhysReg) { +bool RegAllocFastImpl::displacePhysReg(MachineInstr &MI, MCPhysReg PhysReg) { bool displacedAny = false; for (MCRegUnit Unit : TRI->regunits(PhysReg)) { @@ -726,7 +741,7 @@ bool RegAllocFast::displacePhysReg(MachineInstr &MI, MCPhysReg PhysReg) { return displacedAny; } -void RegAllocFast::freePhysReg(MCPhysReg PhysReg) { +void RegAllocFastImpl::freePhysReg(MCPhysReg PhysReg) { LLVM_DEBUG(dbgs() << "Freeing " << printReg(PhysReg, TRI) << ':'); MCRegister FirstUnit = *TRI->regunits(PhysReg).begin(); @@ -753,7 +768,7 @@ void RegAllocFast::freePhysReg(MCPhysReg PhysReg) { /// for allocation. Returns 0 when PhysReg is free or disabled with all aliases /// disabled - it can be allocated directly. /// \returns spillImpossible when PhysReg or an alias can't be spilled. -unsigned RegAllocFast::calcSpillCost(MCPhysReg PhysReg) const { +unsigned RegAllocFastImpl::calcSpillCost(MCPhysReg PhysReg) const { for (MCRegUnit Unit : TRI->regunits(PhysReg)) { switch (unsigned VirtReg = RegUnitStates[Unit]) { case regFree: @@ -772,8 +787,9 @@ unsigned RegAllocFast::calcSpillCost(MCPhysReg PhysReg) const { return 0; } -void RegAllocFast::assignDanglingDebugValues(MachineInstr &Definition, - Register VirtReg, MCPhysReg Reg) { +void RegAllocFastImpl::assignDanglingDebugValues(MachineInstr &Definition, + Register VirtReg, + MCPhysReg Reg) { auto UDBGValIter = DanglingDbgValues.find(VirtReg); if (UDBGValIter == DanglingDbgValues.end()) return; @@ -809,8 +825,8 @@ void RegAllocFast::assignDanglingDebugValues(MachineInstr &Definition, /// This method updates local state so that we know that PhysReg is the /// proper container for VirtReg now. The physical register must not be used /// for anything else when this is called. -void RegAllocFast::assignVirtToPhysReg(MachineInstr &AtMI, LiveReg &LR, - MCPhysReg PhysReg) { +void RegAllocFastImpl::assignVirtToPhysReg(MachineInstr &AtMI, LiveReg &LR, + MCPhysReg PhysReg) { Register VirtReg = LR.VirtReg; LLVM_DEBUG(dbgs() << "Assigning " << printReg(VirtReg, TRI) << " to " << printReg(PhysReg, TRI) << '\n'); @@ -824,7 +840,7 @@ void RegAllocFast::assignVirtToPhysReg(MachineInstr &AtMI, LiveReg &LR, static bool isCoalescable(const MachineInstr &MI) { return MI.isFullCopy(); } -Register RegAllocFast::traceCopyChain(Register Reg) const { +Register RegAllocFastImpl::traceCopyChain(Register Reg) const { static const unsigned ChainLengthLimit = 3; unsigned C = 0; do { @@ -843,7 +859,7 @@ Register RegAllocFast::traceCopyChain(Register Reg) const { /// Check if any of \p VirtReg's definitions is a copy. If it is follow the /// chain of copies to check whether we reach a physical register we can /// coalesce with. -Register RegAllocFast::traceCopies(Register VirtReg) const { +Register RegAllocFastImpl::traceCopies(Register VirtReg) const { static const unsigned DefLimit = 3; unsigned C = 0; for (const MachineInstr &MI : MRI->def_instructions(VirtReg)) { @@ -861,8 +877,8 @@ Register RegAllocFast::traceCopies(Register VirtReg) const { } /// Allocates a physical register for VirtReg. -void RegAllocFast::allocVirtReg(MachineInstr &MI, LiveReg &LR, Register Hint0, - bool LookAtPhysRegUses) { +void RegAllocFastImpl::allocVirtReg(MachineInstr &MI, LiveReg &LR, + Register Hint0, bool LookAtPhysRegUses) { const Register VirtReg = LR.VirtReg; assert(LR.PhysReg == 0); @@ -950,7 +966,7 @@ void RegAllocFast::allocVirtReg(MachineInstr &MI, LiveReg &LR, Register Hint0, assignVirtToPhysReg(MI, LR, BestReg); } -void RegAllocFast::allocVirtRegUndef(MachineOperand &MO) { +void RegAllocFastImpl::allocVirtRegUndef(MachineOperand &MO) { assert(MO.isUndef() && "expected undef use"); Register VirtReg = MO.getReg(); assert(VirtReg.isVirtual() && "Expected virtreg"); @@ -980,8 +996,9 @@ void RegAllocFast::allocVirtRegUndef(MachineOperand &MO) { /// Variation of defineVirtReg() with special handling for livethrough regs /// (tied or earlyclobber) that may interfere with preassigned uses. /// \return true if MI's MachineOperands were re-arranged/invalidated. -bool RegAllocFast::defineLiveThroughVirtReg(MachineInstr &MI, unsigned OpNum, - Register VirtReg) { +bool RegAllocFastImpl::defineLiveThroughVirtReg(MachineInstr &MI, + unsigned OpNum, + Register VirtReg) { if (!shouldAllocateRegister(VirtReg)) return false; LiveRegMap::iterator LRI = findLiveVirtReg(VirtReg); @@ -1016,8 +1033,8 @@ bool RegAllocFast::defineLiveThroughVirtReg(MachineInstr &MI, unsigned OpNum, /// - The value is live out and all uses are in different basic blocks. /// /// \return true if MI's MachineOperands were re-arranged/invalidated. -bool RegAllocFast::defineVirtReg(MachineInstr &MI, unsigned OpNum, - Register VirtReg, bool LookAtPhysRegUses) { +bool RegAllocFastImpl::defineVirtReg(MachineInstr &MI, unsigned OpNum, + Register VirtReg, bool LookAtPhysRegUses) { assert(VirtReg.isVirtual() && "Not a virtual register"); if (!shouldAllocateRegister(VirtReg)) return false; @@ -1094,8 +1111,8 @@ bool RegAllocFast::defineVirtReg(MachineInstr &MI, unsigned OpNum, /// Allocates a register for a VirtReg use. /// \return true if MI's MachineOperands were re-arranged/invalidated. -bool RegAllocFast::useVirtReg(MachineInstr &MI, MachineOperand &MO, - Register VirtReg) { +bool RegAllocFastImpl::useVirtReg(MachineInstr &MI, MachineOperand &MO, + Register VirtReg) { assert(VirtReg.isVirtual() && "Not a virtual register"); if (!shouldAllocateRegister(VirtReg)) return false; @@ -1150,8 +1167,8 @@ bool RegAllocFast::useVirtReg(MachineInstr &MI, MachineOperand &MO, /// Changes operand OpNum in MI the refer the PhysReg, considering subregs. /// \return true if MI's MachineOperands were re-arranged/invalidated. -bool RegAllocFast::setPhysReg(MachineInstr &MI, MachineOperand &MO, - MCPhysReg PhysReg) { +bool RegAllocFastImpl::setPhysReg(MachineInstr &MI, MachineOperand &MO, + MCPhysReg PhysReg) { if (!MO.getSubReg()) { MO.setReg(PhysReg); MO.setIsRenamable(true); @@ -1190,7 +1207,7 @@ bool RegAllocFast::setPhysReg(MachineInstr &MI, MachineOperand &MO, #ifndef NDEBUG -void RegAllocFast::dumpState() const { +void RegAllocFastImpl::dumpState() const { for (unsigned Unit = 1, UnitE = TRI->getNumRegUnits(); Unit != UnitE; ++Unit) { switch (unsigned VirtReg = RegUnitStates[Unit]) { @@ -1235,7 +1252,7 @@ void RegAllocFast::dumpState() const { #endif /// Count number of defs consumed from each register class by \p Reg -void RegAllocFast::addRegClassDefCounts( +void RegAllocFastImpl::addRegClassDefCounts( std::vector<unsigned> &RegClassDefCounts, Register Reg) const { assert(RegClassDefCounts.size() == TRI->getNumRegClasses()); @@ -1269,7 +1286,7 @@ void RegAllocFast::addRegClassDefCounts( /// Compute \ref DefOperandIndexes so it contains the indices of "def" operands /// that are to be allocated. Those are ordered in a way that small classes, /// early clobbers and livethroughs are allocated first. -void RegAllocFast::findAndSortDefOperandIndexes(const MachineInstr &MI) { +void RegAllocFastImpl::findAndSortDefOperandIndexes(const MachineInstr &MI) { DefOperandIndexes.clear(); // Track number of defs which may consume a register from the class. @@ -1343,7 +1360,7 @@ static bool isTiedToNotUndef(const MachineOperand &MO) { return !TiedMO.isUndef(); } -void RegAllocFast::allocateInstruction(MachineInstr &MI) { +void RegAllocFastImpl::allocateInstruction(MachineInstr &MI) { // The basic algorithm here is: // 1. Mark registers of def operands as free // 2. Allocate registers to use operands and place reload instructions for @@ -1605,7 +1622,7 @@ void RegAllocFast::allocateInstruction(MachineInstr &MI) { } } -void RegAllocFast::handleDebugValue(MachineInstr &MI) { +void RegAllocFastImpl::handleDebugValue(MachineInstr &MI) { // Ignore DBG_VALUEs that aren't based on virtual registers. These are // mostly constants and frame indices. assert(MI.isDebugValue() && "not a DBG_VALUE*"); @@ -1648,7 +1665,7 @@ void RegAllocFast::handleDebugValue(MachineInstr &MI) { } } -void RegAllocFast::handleBundle(MachineInstr &MI) { +void RegAllocFastImpl::handleBundle(MachineInstr &MI) { MachineBasicBlock::instr_iterator BundledMI = MI.getIterator(); ++BundledMI; while (BundledMI->isBundledWithPred()) { @@ -1671,7 +1688,7 @@ void RegAllocFast::handleBundle(MachineInstr &MI) { } } -void RegAllocFast::allocateBasicBlock(MachineBasicBlock &MBB) { +void RegAllocFastImpl::allocateBasicBlock(MachineBasicBlock &MBB) { this->MBB = &MBB; LLVM_DEBUG(dbgs() << "\nAllocating " << MBB); @@ -1732,7 +1749,7 @@ void RegAllocFast::allocateBasicBlock(MachineBasicBlock &MBB) { LLVM_DEBUG(MBB.dump()); } -bool RegAllocFast::runOnMachineFunction(MachineFunction &MF) { +bool RegAllocFastImpl::runOnMachineFunction(MachineFunction &MF) { LLVM_DEBUG(dbgs() << "********** FAST REGISTER ALLOCATION **********\n" << "********** Function: " << MF.getName() << '\n'); MRI = &MF.getRegInfo(); @@ -1771,6 +1788,36 @@ bool RegAllocFast::runOnMachineFunction(MachineFunction &MF) { return true; } +PreservedAnalyses RegAllocFastPass::run(MachineFunction &MF, + MachineFunctionAnalysisManager &) { + RegAllocFastImpl Impl(Opts.Filter, Opts.ClearVRegs); + bool Changed = Impl.runOnMachineFunction(MF); + if (!Changed) + return PreservedAnalyses::all(); + auto PA = getMachineFunctionPassPreservedAnalyses(); + PA.preserveSet<CFGAnalyses>(); + return PA; +} + +void RegAllocFastPass::printPipeline( + raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) { + bool PrintFilterName = Opts.FilterName != "all"; + bool PrintNoClearVRegs = !Opts.ClearVRegs; + bool PrintSemicolon = PrintFilterName && PrintNoClearVRegs; + + OS << "regallocfast"; + if (PrintFilterName || PrintNoClearVRegs) { + OS << '<'; + if (PrintFilterName) + OS << "filter=" << Opts.FilterName; + if (PrintSemicolon) + OS << ';'; + if (PrintNoClearVRegs) + OS << "no-clear-vregs"; + OS << '>'; + } +} + FunctionPass *llvm::createFastRegisterAllocator() { return new RegAllocFast(); } FunctionPass *llvm::createFastRegisterAllocator(RegClassFilterFunc Ftor, |