diff --git a/llvm/include/llvm/CodeGen/MachinePassManager.h b/llvm/include/llvm/CodeGen/MachinePassManager.h index 852b1a0f41613..7d15664fbe754 100644 --- a/llvm/include/llvm/CodeGen/MachinePassManager.h +++ b/llvm/include/llvm/CodeGen/MachinePassManager.h @@ -61,7 +61,7 @@ struct MachinePassModel #ifndef NDEBUG if constexpr (is_detected<has_get_required_properties_t, PassT>::value) { auto &MFProps = IR.getProperties(); - auto RequiredProperties = PassT::getRequiredProperties(); + auto RequiredProperties = this->Pass.getRequiredProperties(); if (!MFProps.verifyRequiredProperties(RequiredProperties)) { errs() << "MachineFunctionProperties required by " << PassT::name() << " pass are not met by function " << IR.getName() << ".\n" @@ -78,9 +78,9 @@ struct MachinePassModel auto PA = this->Pass.run(IR, AM); if constexpr (is_detected<has_get_set_properties_t, PassT>::value) - IR.getProperties().set(PassT::getSetProperties()); + IR.getProperties().set(this->Pass.getSetProperties()); if constexpr (is_detected<has_get_cleared_properties_t, PassT>::value) - IR.getProperties().reset(PassT::getClearedProperties()); + IR.getProperties().reset(this->Pass.getClearedProperties()); return PA; } diff --git a/llvm/include/llvm/CodeGen/RegAllocFast.h b/llvm/include/llvm/CodeGen/RegAllocFast.h new file mode 100644 index 0000000000000..c50deccabd995 --- /dev/null +++ b/llvm/include/llvm/CodeGen/RegAllocFast.h @@ -0,0 +1,57 @@ +//==- RegAllocFast.h ----------- fast register allocator ----------*-C++-*-==// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_REGALLOCFAST_H +#define LLVM_CODEGEN_REGALLOCFAST_H + +#include "llvm/CodeGen/MachinePassManager.h" +#include "llvm/CodeGen/RegAllocCommon.h" + +namespace llvm { + +struct RegAllocFastPassOptions { + RegClassFilterFunc Filter = allocateAllRegClasses; + StringRef FilterName = "all"; + bool ClearVRegs = true; +}; + +class RegAllocFastPass : public PassInfoMixin<RegAllocFastPass> { + RegAllocFastPassOptions Opts; + +public: + RegAllocFastPass(RegAllocFastPassOptions Opts = RegAllocFastPassOptions()) + : Opts(Opts) {} + + MachineFunctionProperties getRequiredProperties() { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::NoPHIs); + } + + MachineFunctionProperties getSetProperties() { + if (Opts.ClearVRegs) { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::NoVRegs); + } + + return MachineFunctionProperties(); + } + + MachineFunctionProperties getClearedProperties() { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::IsSSA); + } + + PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &); + + void printPipeline(raw_ostream &OS, + function_ref<StringRef(StringRef)> MapClassName2PassName); +}; + +} // namespace llvm + +#endif // LLVM_CODEGEN_REGALLOCFAST_H diff --git a/llvm/include/llvm/Passes/CodeGenPassBuilder.h b/llvm/include/llvm/Passes/CodeGenPassBuilder.h index 3c4723a0513ce..c8263575e3045 100644 --- a/llvm/include/llvm/Passes/CodeGenPassBuilder.h +++ b/llvm/include/llvm/Passes/CodeGenPassBuilder.h @@ -42,6 +42,7 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachinePassManager.h" #include "llvm/CodeGen/PreISelIntrinsicLowering.h" +#include "llvm/CodeGen/RegAllocFast.h" #include "llvm/CodeGen/ReplaceWithVeclib.h" #include "llvm/CodeGen/SafeStack.h" #include "llvm/CodeGen/SelectOptimize.h" @@ -1037,7 +1038,7 @@ void CodeGenPassBuilder<Derived, TargetMachineT>::addTargetRegisterAllocator( if (Optimized) addPass(RAGreedyPass()); else - addPass(RAFastPass()); + addPass(RegAllocFastPass()); } /// Find and instantiate the register allocation pass requested by this target diff --git a/llvm/include/llvm/Passes/MachinePassRegistry.def b/llvm/include/llvm/Passes/MachinePassRegistry.def index fc2beb7286455..4f49592df6cb6 100644 --- a/llvm/include/llvm/Passes/MachinePassRegistry.def +++ b/llvm/include/llvm/Passes/MachinePassRegistry.def @@ -132,6 +132,19 @@ MACHINE_FUNCTION_PASS("require-all-machine-function-properties", MACHINE_FUNCTION_PASS("trigger-verifier-error", TriggerVerifierErrorPass()) #undef MACHINE_FUNCTION_PASS +#ifndef MACHINE_FUNCTION_PASS_WITH_PARAMS +#define MACHINE_FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, \ + PARAMS) +#endif +MACHINE_FUNCTION_PASS_WITH_PARAMS( + "regallocfast", "RegAllocFast", + [](RegAllocFastPassOptions Opts) { return RegAllocFastPass(Opts); }, + [PB = this](StringRef Params) { + return parseRegAllocFastPassOptions(*PB, Params); + }, + "filter=reg-filter;no-clear-vregs") +#undef MACHINE_FUNCTION_PASS_WITH_PARAMS + // After a pass is converted to new pass manager, its entry should be moved from // dummy table to the normal one. For example, for a machine function pass, // DUMMY_MACHINE_FUNCTION_PASS to MACHINE_FUNCTION_PASS. @@ -211,7 +224,6 @@ DUMMY_MACHINE_FUNCTION_PASS("processimpdefs", ProcessImplicitDefsPass) DUMMY_MACHINE_FUNCTION_PASS("prologepilog", PrologEpilogInserterPass) DUMMY_MACHINE_FUNCTION_PASS("prologepilog-code", PrologEpilogCodeInserterPass) DUMMY_MACHINE_FUNCTION_PASS("ra-basic", RABasicPass) -DUMMY_MACHINE_FUNCTION_PASS("ra-fast", RAFastPass) DUMMY_MACHINE_FUNCTION_PASS("ra-greedy", RAGreedyPass) DUMMY_MACHINE_FUNCTION_PASS("ra-pbqp", RAPBQPPass) DUMMY_MACHINE_FUNCTION_PASS("reg-usage-collector", RegUsageInfoCollectorPass) diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h index 8de0f024a4b11..ed817127c3db1 100644 --- a/llvm/include/llvm/Passes/PassBuilder.h +++ b/llvm/include/llvm/Passes/PassBuilder.h @@ -17,6 +17,7 @@ #include "llvm/Analysis/CGSCCPassManager.h" #include "llvm/CodeGen/MachinePassManager.h" +#include "llvm/CodeGen/RegAllocCommon.h" #include "llvm/IR/PassManager.h" #include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/Error.h" @@ -388,6 +389,9 @@ class PassBuilder { /// returns false. Error parseAAPipeline(AAManager &AA, StringRef PipelineText); + /// Parse RegClassFilterName to get RegClassFilterFunc. + RegClassFilterFunc parseRegAllocFilter(StringRef RegClassFilterName); + /// Print pass names. void printPassNames(raw_ostream &OS); @@ -576,6 +580,14 @@ class PassBuilder { } /// @}} + /// Register callbacks to parse target specific filter field if regalloc pass + /// needs it. E.g. AMDGPU requires regalloc passes can handle sgpr and vgpr + /// separately. + void registerRegClassFilterParsingCallback( + const std::function<RegClassFilterFunc(StringRef)> &C) { + RegClassFilterParsingCallbacks.push_back(C); + } + /// Register a callback for a top-level pipeline entry. /// /// If the PassManager type is not given at the top level of the pipeline @@ -792,6 +804,9 @@ class PassBuilder { ArrayRef<PipelineElement>)>, 2> MachineFunctionPipelineParsingCallbacks; + // Callbacks to parse `filter` parameter in register allocation passes + SmallVector<std::function<RegClassFilterFunc(StringRef)>, 2> + RegClassFilterParsingCallbacks; }; /// This utility template takes care of adding require<> and invalidate<> diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp index 6740e1f0edb4f..09ce8c42a3850 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 @@ class InstrPosIndexes { 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 @@ class RegAllocFast : public MachineFunctionPass { /// 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 @@ class RegAllocFast : public MachineFunctionPass { }; 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 @@ class RegAllocFast : public MachineFunctionPass { 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, diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index 09231504ef906..4b309fc235660 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -96,6 +96,7 @@ #include "llvm/CodeGen/MachinePassManager.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PreISelIntrinsicLowering.h" +#include "llvm/CodeGen/RegAllocFast.h" #include "llvm/CodeGen/SafeStack.h" #include "llvm/CodeGen/SelectOptimize.h" #include "llvm/CodeGen/ShadowStackGCLowering.h" @@ -1161,6 +1162,38 @@ Expected<SmallVector<std::string, 0>> parseInternalizeGVs(StringRef Params) { return Expected<SmallVector<std::string, 0>>(std::move(PreservedGVs)); } +Expected<RegAllocFastPassOptions> +parseRegAllocFastPassOptions(PassBuilder &PB, StringRef Params) { + RegAllocFastPassOptions Opts; + while (!Params.empty()) { + StringRef ParamName; + std::tie(ParamName, Params) = Params.split(';'); + + if (ParamName.consume_front("filter=")) { + RegClassFilterFunc Filter = PB.parseRegAllocFilter(ParamName); + if (!Filter) { + return make_error<StringError>( + formatv("invalid regallocfast register filter '{0}' ", ParamName) + .str(), + inconvertibleErrorCode()); + } + Opts.Filter = Filter; + Opts.FilterName = ParamName; + continue; + } + + if (ParamName == "no-clear-vregs") { + Opts.ClearVRegs = false; + continue; + } + + return make_error<StringError>( + formatv("invalid regallocfast pass parameter '{0}' ", ParamName).str(), + inconvertibleErrorCode()); + } + return Opts; +} + } // namespace /// Tests whether a pass name starts with a valid prefix for a default pipeline @@ -1294,6 +1327,11 @@ static bool isMachineFunctionPassName(StringRef Name, CallbacksT &Callbacks) { #define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS) \ if (Name == NAME) \ return true; +#define MACHINE_FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, \ + PARAMS) \ + if (PassBuilder::checkParametrizedPassName(Name, NAME)) \ + return true; + #define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \ return true; @@ -1923,6 +1961,15 @@ Error PassBuilder::parseMachinePass(MachineFunctionPassManager &MFPM, MFPM.addPass(CREATE_PASS); \ return Error::success(); \ } +#define MACHINE_FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, \ + PARAMS) \ + if (checkParametrizedPassName(Name, NAME)) { \ + auto Params = parsePassParameters(PARSER, Name, NAME); \ + if (!Params) \ + return Params.takeError(); \ + MFPM.addPass(CREATE_PASS(Params.get())); \ + return Error::success(); \ + } #include "llvm/Passes/MachinePassRegistry.def" for (auto &C : MachineFunctionPipelineParsingCallbacks) @@ -2170,6 +2217,15 @@ Error PassBuilder::parseAAPipeline(AAManager &AA, StringRef PipelineText) { return Error::success(); } +RegClassFilterFunc PassBuilder::parseRegAllocFilter(StringRef FilterName) { + if (FilterName == "all") + return allocateAllRegClasses; + for (auto &C : RegClassFilterParsingCallbacks) + if (auto F = C(FilterName)) + return F; + return nullptr; +} + static void printPassName(StringRef PassName, raw_ostream &OS) { OS << " " << PassName << "\n"; } diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp index 9c94ca1e47080..4eb8b48e15b84 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp @@ -739,6 +739,15 @@ void AMDGPUTargetMachine::registerPassBuilderCallbacks( if (EnableLowerModuleLDS) PM.addPass(AMDGPULowerModuleLDSPass(*this)); }); + + PB.registerRegClassFilterParsingCallback( + [](StringRef FilterName) -> RegClassFilterFunc { + if (FilterName == "sgpr") + return onlyAllocateSGPRs; + if (FilterName == "vgpr") + return onlyAllocateVGPRs; + return nullptr; + }); } int64_t AMDGPUTargetMachine::getNullPointerValue(unsigned AddrSpace) { diff --git a/llvm/test/CodeGen/AArch64/fast-regalloc-empty-bb-with-liveins.mir b/llvm/test/CodeGen/AArch64/fast-regalloc-empty-bb-with-liveins.mir index f620cd22901ca..ff5ac24f713d0 100644 --- a/llvm/test/CodeGen/AArch64/fast-regalloc-empty-bb-with-liveins.mir +++ b/llvm/test/CodeGen/AArch64/fast-regalloc-empty-bb-with-liveins.mir @@ -1,5 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple aarch64-apple-ios -run-pass regallocfast -o - %s | FileCheck %s +# RUN: llc -mtriple aarch64-apple-ios -passes=regallocfast -o - %s | FileCheck %s # This test used to crash the fast register alloc. # Basically, when a basic block has liveins, the fast regalloc # was deferencing the begin iterator of this block. However, diff --git a/llvm/test/CodeGen/AMDGPU/fast-ra-kills-vcc.mir b/llvm/test/CodeGen/AMDGPU/fast-ra-kills-vcc.mir index 0fa6577b0dd03..01cd5f74dcb48 100644 --- a/llvm/test/CodeGen/AMDGPU/fast-ra-kills-vcc.mir +++ b/llvm/test/CodeGen/AMDGPU/fast-ra-kills-vcc.mir @@ -1,5 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -verify-machineinstrs -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -run-pass=regallocfast -o - %s | FileCheck %s +# RUN: llc -verify-machineinstrs -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -passes=regallocfast -o - %s | FileCheck %s # Make sure incorrect kills aren't emitted on vcc diff --git a/llvm/test/CodeGen/AMDGPU/fast-regalloc-bundles.mir b/llvm/test/CodeGen/AMDGPU/fast-regalloc-bundles.mir index ea03f2c57ea59..8c969eb0ef9b6 100644 --- a/llvm/test/CodeGen/AMDGPU/fast-regalloc-bundles.mir +++ b/llvm/test/CodeGen/AMDGPU/fast-regalloc-bundles.mir @@ -1,5 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple=amdgcn -mcpu=gfx902 -verify-machineinstrs -run-pass=regallocfast %s -o - | FileCheck --check-prefix=GCN %s +# RUN: llc -mtriple=amdgcn -mcpu=gfx902 -verify-machineinstrs -passes=regallocfast %s -o - | FileCheck --check-prefix=GCN %s --- name: fast_regalloc_bundle_handling diff --git a/llvm/test/CodeGen/AMDGPU/fastregalloc-illegal-subreg-physreg.mir b/llvm/test/CodeGen/AMDGPU/fastregalloc-illegal-subreg-physreg.mir index 7642775aafdaf..6a2a2b0c3939f 100644 --- a/llvm/test/CodeGen/AMDGPU/fastregalloc-illegal-subreg-physreg.mir +++ b/llvm/test/CodeGen/AMDGPU/fastregalloc-illegal-subreg-physreg.mir @@ -1,5 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple=amdgcn -mcpu=gfx900 -verify-machineinstrs -run-pass=regallocfast -o - %s | FileCheck %s +# RUN: llc -mtriple=amdgcn -mcpu=gfx900 -verify-machineinstrs -passes=regallocfast -o - %s | FileCheck %s # This would hit "Illegal subregister index for physical register" verifier error since # tied operands would skip dropping the subregister index. diff --git a/llvm/test/CodeGen/AMDGPU/fastregalloc-self-loop-heuristic.mir b/llvm/test/CodeGen/AMDGPU/fastregalloc-self-loop-heuristic.mir index 24b82f4862afd..918242e9f9967 100644 --- a/llvm/test/CodeGen/AMDGPU/fastregalloc-self-loop-heuristic.mir +++ b/llvm/test/CodeGen/AMDGPU/fastregalloc-self-loop-heuristic.mir @@ -1,5 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -verify-machineinstrs -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -run-pass=regallocfast -o - %s | FileCheck -check-prefix=GCN %s +# RUN: llc -verify-machineinstrs -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -passes=regallocfast -o - %s | FileCheck -check-prefix=GCN %s --- name: self_loop_single_def_use diff --git a/llvm/test/CodeGen/AMDGPU/spill-agpr.mir b/llvm/test/CodeGen/AMDGPU/spill-agpr.mir index 981a853cb097c..8e6da4bf92ee0 100644 --- a/llvm/test/CodeGen/AMDGPU/spill-agpr.mir +++ b/llvm/test/CodeGen/AMDGPU/spill-agpr.mir @@ -1,7 +1,9 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple=amdgcn -mcpu=gfx908 -run-pass=regallocfast -o - %s | FileCheck -check-prefix=GFX908-SPILLED %s +# RUN: llc -mtriple=amdgcn -mcpu=gfx908 -passes=regallocfast -o - %s | FileCheck -check-prefix=GFX908-SPILLED %s # RUN: llc -mtriple=amdgcn -mcpu=gfx908 -run-pass=regallocfast,prologepilog -o - %s | FileCheck -check-prefix=GFX908-EXPANDED %s # RUN: llc -mtriple=amdgcn -mcpu=gfx90a -run-pass=regallocfast -o - %s | FileCheck -check-prefix=GFX90A-SPILLED %s +# RUN: llc -mtriple=amdgcn -mcpu=gfx90a -passes=regallocfast -o - %s | FileCheck -check-prefix=GFX90A-SPILLED %s # RUN: llc -mtriple=amdgcn -mcpu=gfx90a -run-pass=regallocfast,prologepilog -o - %s | FileCheck -check-prefix=GFX90A-EXPANDED %s --- diff --git a/llvm/test/CodeGen/AMDGPU/spill192.mir b/llvm/test/CodeGen/AMDGPU/spill192.mir index 56882cd83106e..42c792b1538ae 100644 --- a/llvm/test/CodeGen/AMDGPU/spill192.mir +++ b/llvm/test/CodeGen/AMDGPU/spill192.mir @@ -1,5 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s +# RUN: llc -mtriple=amdgcn -mcpu=tahiti -passes=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s # RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast,si-lower-sgpr-spills -o - %s | FileCheck -check-prefix=EXPANDED %s # Make sure spill/restore of 192 bit registers works. We have to diff --git a/llvm/test/CodeGen/AMDGPU/spill224.mir b/llvm/test/CodeGen/AMDGPU/spill224.mir index 4525fc1cb70e6..5e53f93df95f7 100644 --- a/llvm/test/CodeGen/AMDGPU/spill224.mir +++ b/llvm/test/CodeGen/AMDGPU/spill224.mir @@ -1,5 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s +# RUN: llc -mtriple=amdgcn -mcpu=tahiti -passes=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s # RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast,si-lower-sgpr-spills -o - %s | FileCheck -check-prefix=EXPANDED %s # Make sure spill/restore of 224 bit registers works. diff --git a/llvm/test/CodeGen/AMDGPU/spill288.mir b/llvm/test/CodeGen/AMDGPU/spill288.mir index 173056e6b9132..3d5404a9c1ad5 100644 --- a/llvm/test/CodeGen/AMDGPU/spill288.mir +++ b/llvm/test/CodeGen/AMDGPU/spill288.mir @@ -1,5 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s +# RUN: llc -mtriple=amdgcn -mcpu=tahiti -passes=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s # RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast,si-lower-sgpr-spills -o - %s | FileCheck -check-prefix=EXPANDED %s # Make sure spill/restore of 288 bit registers works. diff --git a/llvm/test/CodeGen/AMDGPU/spill320.mir b/llvm/test/CodeGen/AMDGPU/spill320.mir index 828f524bb0677..4473a4d6648ef 100644 --- a/llvm/test/CodeGen/AMDGPU/spill320.mir +++ b/llvm/test/CodeGen/AMDGPU/spill320.mir @@ -1,5 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s +# RUN: llc -mtriple=amdgcn -mcpu=tahiti -passes=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s # RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast,si-lower-sgpr-spills -o - %s | FileCheck -check-prefix=EXPANDED %s # Make sure spill/restore of 320 bit registers works. diff --git a/llvm/test/CodeGen/AMDGPU/spill352.mir b/llvm/test/CodeGen/AMDGPU/spill352.mir index ef620fae5b104..8fa053a908b60 100644 --- a/llvm/test/CodeGen/AMDGPU/spill352.mir +++ b/llvm/test/CodeGen/AMDGPU/spill352.mir @@ -1,5 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s +# RUN: llc -mtriple=amdgcn -mcpu=tahiti -passes=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s # RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast,si-lower-sgpr-spills -o - %s | FileCheck -check-prefix=EXPANDED %s # Make sure spill/restore of 352 bit registers works. diff --git a/llvm/test/CodeGen/AMDGPU/spill384.mir b/llvm/test/CodeGen/AMDGPU/spill384.mir index 37cf5d0fc83cf..cd604e4483b9c 100644 --- a/llvm/test/CodeGen/AMDGPU/spill384.mir +++ b/llvm/test/CodeGen/AMDGPU/spill384.mir @@ -1,5 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s +# RUN: llc -mtriple=amdgcn -mcpu=tahiti -passes=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s # RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast,si-lower-sgpr-spills -o - %s | FileCheck -check-prefix=EXPANDED %s # Make sure spill/restore of 384 bit registers works. diff --git a/llvm/test/CodeGen/AMDGPU/unexpected-reg-unit-state.mir b/llvm/test/CodeGen/AMDGPU/unexpected-reg-unit-state.mir index 1652f31334745..0f0dd2374156f 100644 --- a/llvm/test/CodeGen/AMDGPU/unexpected-reg-unit-state.mir +++ b/llvm/test/CodeGen/AMDGPU/unexpected-reg-unit-state.mir @@ -1,5 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -verify-machineinstrs -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -run-pass=regallocfast -o - %s | FileCheck %s +# RUN: llc -verify-machineinstrs -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -passes=regallocfast -o - %s | FileCheck %s --- name: bar diff --git a/llvm/test/CodeGen/ARM/regalloc-fast-rewrite-implicits.mir b/llvm/test/CodeGen/ARM/regalloc-fast-rewrite-implicits.mir index b7a007f7e3ff0..7de911486ddf7 100644 --- a/llvm/test/CodeGen/ARM/regalloc-fast-rewrite-implicits.mir +++ b/llvm/test/CodeGen/ARM/regalloc-fast-rewrite-implicits.mir @@ -1,5 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple=armv7-apple-ios -run-pass=regallocfast -o - %s | FileCheck %s +# RUN: llc -mtriple=armv7-apple-ios -passes=regallocfast -o - %s | FileCheck %s # tBX_RET uses an implicit vreg with a sub-register. That implicit use will diff --git a/llvm/test/CodeGen/MIR/Generic/runPass.mir b/llvm/test/CodeGen/MIR/Generic/runPass.mir index 54c1dd221bdb7..75763c5389b09 100644 --- a/llvm/test/CodeGen/MIR/Generic/runPass.mir +++ b/llvm/test/CodeGen/MIR/Generic/runPass.mir @@ -1,6 +1,7 @@ # RUN: llc -run-pass=greedy -debug-pass=Arguments -o - %s | FileCheck %s # RUN: llc -run-pass=regallocbasic -debug-pass=Arguments -o - %s | FileCheck %s # RUN: llc -run-pass=regallocfast -debug-pass=Arguments -o - %s | FileCheck %s +# RUN: llc -passes=regallocfast -o - %s | FileCheck %s # Check that passes are initialized correctly, so that it's possible to # use -run-pass. diff --git a/llvm/test/CodeGen/PowerPC/spill-nor0.mir b/llvm/test/CodeGen/PowerPC/spill-nor0.mir index 2f50ff3701d13..6658ca156d4d2 100644 --- a/llvm/test/CodeGen/PowerPC/spill-nor0.mir +++ b/llvm/test/CodeGen/PowerPC/spill-nor0.mir @@ -1,4 +1,5 @@ # RUN: llc -o - %s -mtriple=powerpc64-- -run-pass=regallocfast | FileCheck %s +# RUN: llc -o - %s -mtriple=powerpc64-- -passes=regallocfast | FileCheck %s --- # CHECK-LABEL: name: func name: func diff --git a/llvm/test/CodeGen/SystemZ/regalloc-fast-invalid-kill-flag.mir b/llvm/test/CodeGen/SystemZ/regalloc-fast-invalid-kill-flag.mir index bcd7f51cdf780..917cc776e3ef0 100644 --- a/llvm/test/CodeGen/SystemZ/regalloc-fast-invalid-kill-flag.mir +++ b/llvm/test/CodeGen/SystemZ/regalloc-fast-invalid-kill-flag.mir @@ -1,4 +1,5 @@ # RUN: llc -verify-machineinstrs -run-pass regallocfast -mtriple s390x-ibm-linux -o - %s | FileCheck %s +# RUN: llc -verify-machineinstrs -passes=regallocfast -mtriple s390x-ibm-linux -o - %s | FileCheck %s --- | @g_167 = external global [5 x i64], align 8 diff --git a/llvm/test/CodeGen/Thumb/high-reg-clobber.mir b/llvm/test/CodeGen/Thumb/high-reg-clobber.mir index ab73f1448d715..1402c7c2cbca3 100644 --- a/llvm/test/CodeGen/Thumb/high-reg-clobber.mir +++ b/llvm/test/CodeGen/Thumb/high-reg-clobber.mir @@ -2,6 +2,7 @@ # RUN: llc -mtriple thumbv6m-arm-none-eabi -run-pass regallocbasic %s -o - | FileCheck %s # RUN: llc -mtriple thumbv6m-arm-none-eabi -run-pass greedy %s -o - | FileCheck %s # RUN: llc -mtriple thumbv6m-arm-none-eabi -run-pass regallocfast %s -o - | FileCheck %s --check-prefix=FAST +# RUN: llc -mtriple thumbv6m-arm-none-eabi -passes=regallocfast %s -o - | FileCheck %s --check-prefix=FAST ... --- diff --git a/llvm/test/CodeGen/Thumb2/high-reg-spill.mir b/llvm/test/CodeGen/Thumb2/high-reg-spill.mir index 1cf58da63fe83..8c92020fb0519 100644 --- a/llvm/test/CodeGen/Thumb2/high-reg-spill.mir +++ b/llvm/test/CodeGen/Thumb2/high-reg-spill.mir @@ -1,5 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -run-pass regallocfast %s -o - | FileCheck %s +# RUN: llc -passes=regallocfast %s -o - | FileCheck %s # This test examines register allocation and spilling with Fast Register # Allocator. The test uses inline assembler that requests an input variable to diff --git a/llvm/test/CodeGen/X86/bug47278-eflags-error.mir b/llvm/test/CodeGen/X86/bug47278-eflags-error.mir index e4e68451850b7..65d368ee224de 100644 --- a/llvm/test/CodeGen/X86/bug47278-eflags-error.mir +++ b/llvm/test/CodeGen/X86/bug47278-eflags-error.mir @@ -1,5 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple=i386-unknown-linux-musl -verify-machineinstrs -run-pass=regallocfast -o - %s | FileCheck %s +# RUN: llc -mtriple=i386-unknown-linux-musl -verify-machineinstrs -passes=regallocfast -o - %s | FileCheck %s # Test for correct management of allocatable and non-allocatable # live-ins in fastregalloc diff --git a/llvm/test/CodeGen/X86/bug47278.mir b/llvm/test/CodeGen/X86/bug47278.mir index 0b01c9de19c0b..ea7bb09616981 100644 --- a/llvm/test/CodeGen/X86/bug47278.mir +++ b/llvm/test/CodeGen/X86/bug47278.mir @@ -1,5 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple=i386-unknown-linux-musl -verify-machineinstrs -run-pass=regallocfast -o - %s | FileCheck %s +# RUN: llc -mtriple=i386-unknown-linux-musl -verify-machineinstrs -passes=regallocfast -o - %s | FileCheck %s # Make sure this case doesn't assert or try to assign $ecx to %1 on # SHRD32rrCL diff --git a/llvm/test/CodeGen/X86/callbr-asm-outputs-regallocfast.mir b/llvm/test/CodeGen/X86/callbr-asm-outputs-regallocfast.mir index 6417538b269cc..6263a3f09b0d3 100644 --- a/llvm/test/CodeGen/X86/callbr-asm-outputs-regallocfast.mir +++ b/llvm/test/CodeGen/X86/callbr-asm-outputs-regallocfast.mir @@ -1,5 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -run-pass=regallocfast -verify-machineinstrs %s -o - | FileCheck %s +# RUN: llc -passes=regallocfast -verify-machineinstrs %s -o - | FileCheck %s --- | ; ModuleID = 'x.c' source_filename = "x.c" diff --git a/llvm/test/CodeGen/X86/fastregalloc-selfloop.mir b/llvm/test/CodeGen/X86/fastregalloc-selfloop.mir index d60632a98fb00..1872e703d6cd4 100644 --- a/llvm/test/CodeGen/X86/fastregalloc-selfloop.mir +++ b/llvm/test/CodeGen/X86/fastregalloc-selfloop.mir @@ -1,4 +1,5 @@ # RUN: llc -mtriple=x86_64-- -run-pass=regallocfast -o - %s | FileCheck %s +# RUN: llc -mtriple=x86_64-- -passes=regallocfast -o - %s | FileCheck %s ... --- diff --git a/llvm/test/CodeGen/X86/fastregalloc-tied-undef.mir b/llvm/test/CodeGen/X86/fastregalloc-tied-undef.mir index 8a6311eabacad..18de9c11439c9 100644 --- a/llvm/test/CodeGen/X86/fastregalloc-tied-undef.mir +++ b/llvm/test/CodeGen/X86/fastregalloc-tied-undef.mir @@ -1,4 +1,5 @@ # RUN: llc -mtriple=x86_64-- -run-pass=regallocfast -o - %s | FileCheck %s +# RUN: llc -mtriple=x86_64-- -passes=regallocfast -o - %s | FileCheck %s # If the tied use is undef value, fastregalloc should free the def register. # There is no reload needed for the undef value. diff --git a/llvm/test/CodeGen/X86/regalloc-fast-missing-live-out-spill.mir b/llvm/test/CodeGen/X86/regalloc-fast-missing-live-out-spill.mir index 6a2eae9dbbc4c..143b6864b1191 100644 --- a/llvm/test/CodeGen/X86/regalloc-fast-missing-live-out-spill.mir +++ b/llvm/test/CodeGen/X86/regalloc-fast-missing-live-out-spill.mir @@ -1,5 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple=x86_64-grtev4-linux-gnu -run-pass=regallocfast -o - %s | FileCheck %s +# RUN: llc -mtriple=x86_64-grtev4-linux-gnu -passes=regallocfast -o - %s | FileCheck %s # Bug 41973. Make sure %12 is detected as live out of %bb.0, even # though the use is allocated before the def block %bb.3. Previously diff --git a/llvm/test/CodeGen/X86/statepoint-fastregalloc.mir b/llvm/test/CodeGen/X86/statepoint-fastregalloc.mir index 8bac14018a7dd..f683e9ebec81d 100644 --- a/llvm/test/CodeGen/X86/statepoint-fastregalloc.mir +++ b/llvm/test/CodeGen/X86/statepoint-fastregalloc.mir @@ -1,4 +1,5 @@ # RUN: llc -mtriple=x86_64-- -run-pass=regallocfast -o - %s | FileCheck %s +# RUN: llc -mtriple=x86_64-- -passes=regallocfast -o - %s | FileCheck %s # Check that fastregalloc does not displace register assigned to tied def when # RegMask operand is present. STATEPOINT is an example of such instruction. diff --git a/llvm/test/CodeGen/X86/virtreg-physreg-def-regallocfast.mir b/llvm/test/CodeGen/X86/virtreg-physreg-def-regallocfast.mir index 6cdac85f96fe9..5222b3d9fdb85 100644 --- a/llvm/test/CodeGen/X86/virtreg-physreg-def-regallocfast.mir +++ b/llvm/test/CodeGen/X86/virtreg-physreg-def-regallocfast.mir @@ -1,4 +1,5 @@ # RUN: llc -o - -mtriple=x86_64-- -run-pass=regallocfast %s | FileCheck %s +# RUN: llc -o - -mtriple=x86_64-- -passes=regallocfast %s | FileCheck %s # Fast regalloc used to not collect physical register definitions # before walking and assigning the virtual definition. # Therefore it was possible for a virtual definition to end up diff --git a/llvm/test/tools/llc/new-pm/regalloc-amdgpu.mir b/llvm/test/tools/llc/new-pm/regalloc-amdgpu.mir new file mode 100644 index 0000000000000..872c35237c20a --- /dev/null +++ b/llvm/test/tools/llc/new-pm/regalloc-amdgpu.mir @@ -0,0 +1,10 @@ +# REQUIRES: amdgpu-registered-target +# RUN: llc -mtriple=amdgcn --passes='regallocfast<filter=sgpr>' --print-pipeline-passes %s | FileCheck %s --check-prefix=PASS +# RUN: not llc -mtriple=amdgcn --passes='regallocfast<filter=bad-filter>' --print-pipeline-passes %s 2>&1 | FileCheck %s --check-prefix=BAD-FILTER + +# PASS: regallocfast<filter=sgpr> +# BAD-FILTER: invalid regallocfast register filter 'bad-filter' + +--- +name: f +...