diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -360,6 +360,7 @@ void initializeRedundantDbgInstEliminationPass(PassRegistry&); void initializeRegAllocEvictionAdvisorAnalysisPass(PassRegistry &); void initializeRegAllocFastPass(PassRegistry&); +void initializeRegAllocPriorityAdvisorAnalysisPass(PassRegistry &); void initializeRegAllocScoringPass(PassRegistry &); void initializeRegBankSelectPass(PassRegistry&); void initializeRegToMemLegacyPass(PassRegistry&); diff --git a/llvm/lib/CodeGen/RegAllocGreedy.h b/llvm/lib/CodeGen/RegAllocGreedy.h --- a/llvm/lib/CodeGen/RegAllocGreedy.h +++ b/llvm/lib/CodeGen/RegAllocGreedy.h @@ -153,9 +153,6 @@ return RegClassPriorityTrumpsGlobalness; } bool getReverseLocalAssignment() const { return ReverseLocalAssignment; } - // FIXME: this is unnecessary once priority advisers are created by an - // analysis pass, which can fetch the SlotIndexes analysis itself. - SlotIndexes *getIndexes() const { return Indexes; } // end (interface to priority advisers) private: diff --git a/llvm/lib/CodeGen/RegAllocGreedy.cpp b/llvm/lib/CodeGen/RegAllocGreedy.cpp --- a/llvm/lib/CodeGen/RegAllocGreedy.cpp +++ b/llvm/lib/CodeGen/RegAllocGreedy.cpp @@ -17,6 +17,7 @@ #include "LiveDebugVariables.h" #include "RegAllocBase.h" #include "RegAllocEvictionAdvisor.h" +#include "RegAllocPriorityAdvisor.h" #include "SpillPlacement.h" #include "SplitKit.h" #include "llvm/ADT/ArrayRef.h" @@ -163,6 +164,7 @@ INITIALIZE_PASS_DEPENDENCY(SpillPlacement) INITIALIZE_PASS_DEPENDENCY(MachineOptimizationRemarkEmitterPass) INITIALIZE_PASS_DEPENDENCY(RegAllocEvictionAdvisorAnalysis) +INITIALIZE_PASS_DEPENDENCY(RegAllocPriorityAdvisorAnalysis) INITIALIZE_PASS_END(RAGreedy, "greedy", "Greedy Register Allocator", false, false) @@ -219,6 +221,7 @@ AU.addRequired(); AU.addRequired(); AU.addRequired(); + AU.addRequired(); MachineFunctionPass::getAnalysisUsage(AU); } @@ -2565,7 +2568,8 @@ ExtraInfo.emplace(); EvictAdvisor = getAnalysis().getAdvisor(*MF, *this); - PriorityAdvisor = std::make_unique(*MF, *this); + PriorityAdvisor = + getAnalysis().getAdvisor(*MF, *this); VRAI = std::make_unique(*MF, *LIS, *VRM, *Loops, *MBFI); SpillerInstance.reset(createInlineSpiller(*this, *MF, *VRM, *VRAI)); diff --git a/llvm/lib/CodeGen/RegAllocPriorityAdvisor.h b/llvm/lib/CodeGen/RegAllocPriorityAdvisor.h --- a/llvm/lib/CodeGen/RegAllocPriorityAdvisor.h +++ b/llvm/lib/CodeGen/RegAllocPriorityAdvisor.h @@ -31,7 +31,8 @@ /// prefers it. virtual unsigned getPriority(const LiveInterval &LI) const = 0; - RegAllocPriorityAdvisor(const MachineFunction &MF, const RAGreedy &RA); + RegAllocPriorityAdvisor(const MachineFunction &MF, const RAGreedy &RA, + SlotIndexes *const Indexes); protected: const RAGreedy &RA; @@ -47,12 +48,47 @@ class DefaultPriorityAdvisor : public RegAllocPriorityAdvisor { public: - DefaultPriorityAdvisor(const MachineFunction &MF, const RAGreedy &RA) - : RegAllocPriorityAdvisor(MF, RA) {} + DefaultPriorityAdvisor(const MachineFunction &MF, const RAGreedy &RA, + SlotIndexes *const Indexes) + : RegAllocPriorityAdvisor(MF, RA, Indexes) {} private: unsigned getPriority(const LiveInterval &LI) const override; }; + +class RegAllocPriorityAdvisorAnalysis : public ImmutablePass { +public: + enum class AdvisorMode : int { Default, Release, Development }; + + RegAllocPriorityAdvisorAnalysis(AdvisorMode Mode) + : ImmutablePass(ID), Mode(Mode){}; + static char ID; + + /// Get an advisor for the given context (i.e. machine function, etc) + virtual std::unique_ptr + getAdvisor(const MachineFunction &MF, const RAGreedy &RA) = 0; + AdvisorMode getAdvisorMode() const { return Mode; } + +protected: + // This analysis preserves everything, and subclasses may have additional + // requirements. + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } + +private: + StringRef getPassName() const override; + const AdvisorMode Mode; +}; + +/// Specialization for the API used by the analysis infrastructure to create +/// an instance of the priority advisor. +template <> Pass *callDefaultCtor(); + +RegAllocPriorityAdvisorAnalysis *createReleaseModePriorityAdvisor(); + +RegAllocPriorityAdvisorAnalysis *createDevelopmentModePriorityAdvisor(); + } // namespace llvm #endif // LLVM_CODEGEN_REGALLOCPRIORITYADVISOR_H diff --git a/llvm/lib/CodeGen/RegAllocPriorityAdvisor.cpp b/llvm/lib/CodeGen/RegAllocPriorityAdvisor.cpp --- a/llvm/lib/CodeGen/RegAllocPriorityAdvisor.cpp +++ b/llvm/lib/CodeGen/RegAllocPriorityAdvisor.cpp @@ -14,16 +14,97 @@ #include "RegAllocGreedy.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/VirtRegMap.h" +#include "llvm/IR/Module.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" using namespace llvm; +static cl::opt Mode( + "regalloc-enable-priority-advisor", cl::Hidden, + cl::init(RegAllocPriorityAdvisorAnalysis::AdvisorMode::Default), + cl::desc("Enable regalloc advisor mode"), + cl::values( + clEnumValN(RegAllocPriorityAdvisorAnalysis::AdvisorMode::Default, + "default", "Default"), + clEnumValN(RegAllocPriorityAdvisorAnalysis::AdvisorMode::Release, + "release", "precompiled"), + clEnumValN(RegAllocPriorityAdvisorAnalysis::AdvisorMode::Development, + "development", "for training"))); + +char RegAllocPriorityAdvisorAnalysis::ID = 0; +INITIALIZE_PASS(RegAllocPriorityAdvisorAnalysis, "regalloc-priority", + "Regalloc priority policy", false, true) + +namespace { +class DefaultPriorityAdvisorAnalysis final + : public RegAllocPriorityAdvisorAnalysis { +public: + DefaultPriorityAdvisorAnalysis(bool NotAsRequested) + : RegAllocPriorityAdvisorAnalysis(AdvisorMode::Default), + NotAsRequested(NotAsRequested) {} + + // support for isa<> and dyn_cast. + static bool classof(const RegAllocPriorityAdvisorAnalysis *R) { + return R->getAdvisorMode() == AdvisorMode::Default; + } + +private: + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addRequired(); + RegAllocPriorityAdvisorAnalysis::getAnalysisUsage(AU); + } + std::unique_ptr + getAdvisor(const MachineFunction &MF, const RAGreedy &RA) override { + return std::make_unique( + MF, RA, &getAnalysis()); + } + bool doInitialization(Module &M) override { + if (NotAsRequested) + M.getContext().emitError("Requested regalloc priority advisor analysis " + "could be created. Using default"); + return RegAllocPriorityAdvisorAnalysis::doInitialization(M); + } + const bool NotAsRequested; +}; +} // namespace + +template <> Pass *llvm::callDefaultCtor() { + Pass *Ret = nullptr; + switch (Mode) { + case RegAllocPriorityAdvisorAnalysis::AdvisorMode::Default: + Ret = new DefaultPriorityAdvisorAnalysis(/*NotAsRequested*/ false); + break; + case RegAllocPriorityAdvisorAnalysis::AdvisorMode::Development: + // TODO: add implementation + break; + case RegAllocPriorityAdvisorAnalysis::AdvisorMode::Release: + // TODO: add implementation + break; + } + if (Ret) + return Ret; + return new DefaultPriorityAdvisorAnalysis(/*NotAsRequested*/ true); +} + +StringRef RegAllocPriorityAdvisorAnalysis::getPassName() const { + switch (getAdvisorMode()) { + case AdvisorMode::Default: + return "Default Regalloc Priority Advisor"; + case AdvisorMode::Release: + return "Release mode Regalloc Priority Advisor"; + case AdvisorMode::Development: + return "Development mode Regalloc Priority Advisor"; + } + llvm_unreachable("Unknown advisor kind"); +} + RegAllocPriorityAdvisor::RegAllocPriorityAdvisor(const MachineFunction &MF, - const RAGreedy &RA) + const RAGreedy &RA, + SlotIndexes *const Indexes) : RA(RA), LIS(RA.getLiveIntervals()), VRM(RA.getVirtRegMap()), MRI(&VRM->getRegInfo()), TRI(MF.getSubtarget().getRegisterInfo()), - RegClassInfo(RA.getRegClassInfo()), Indexes(RA.getIndexes()), + RegClassInfo(RA.getRegClassInfo()), Indexes(Indexes), RegClassPriorityTrumpsGlobalness( RA.getRegClassPriorityTrumpsGlobalness()), ReverseLocalAssignment(RA.getReverseLocalAssignment()) {} diff --git a/llvm/test/CodeGen/AArch64/O3-pipeline.ll b/llvm/test/CodeGen/AArch64/O3-pipeline.ll --- a/llvm/test/CodeGen/AArch64/O3-pipeline.ll +++ b/llvm/test/CodeGen/AArch64/O3-pipeline.ll @@ -15,6 +15,7 @@ ; CHECK-NEXT: Create Garbage Collector Module Metadata ; CHECK-NEXT: Machine Branch Probability Analysis ; CHECK-NEXT: Default Regalloc Eviction Advisor +; CHECK-NEXT: Default Regalloc Priority Advisor ; CHECK-NEXT: ModulePass Manager ; CHECK-NEXT: Pre-ISel Intrinsic Lowering ; CHECK-NEXT: FunctionPass Manager diff --git a/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll b/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll --- a/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll +++ b/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll @@ -161,6 +161,7 @@ ; GCN-O1-NEXT:Machine Branch Probability Analysis ; GCN-O1-NEXT:Register Usage Information Storage ; GCN-O1-NEXT:Default Regalloc Eviction Advisor +; GCN-O1-NEXT:Default Regalloc Priority Advisor ; GCN-O1-NEXT: ModulePass Manager ; GCN-O1-NEXT: Pre-ISel Intrinsic Lowering ; GCN-O1-NEXT: FunctionPass Manager @@ -420,6 +421,7 @@ ; GCN-O1-OPTS-NEXT:Machine Branch Probability Analysis ; GCN-O1-OPTS-NEXT:Register Usage Information Storage ; GCN-O1-OPTS-NEXT:Default Regalloc Eviction Advisor +; GCN-O1-OPTS-NEXT:Default Regalloc Priority Advisor ; GCN-O1-OPTS-NEXT: ModulePass Manager ; GCN-O1-OPTS-NEXT: Pre-ISel Intrinsic Lowering ; GCN-O1-OPTS-NEXT: FunctionPass Manager @@ -711,6 +713,7 @@ ; GCN-O2-NEXT:Machine Branch Probability Analysis ; GCN-O2-NEXT:Register Usage Information Storage ; GCN-O2-NEXT:Default Regalloc Eviction Advisor +; GCN-O2-NEXT:Default Regalloc Priority Advisor ; GCN-O2-NEXT: ModulePass Manager ; GCN-O2-NEXT: Pre-ISel Intrinsic Lowering ; GCN-O2-NEXT: FunctionPass Manager @@ -1005,6 +1008,7 @@ ; GCN-O3-NEXT:Machine Branch Probability Analysis ; GCN-O3-NEXT:Register Usage Information Storage ; GCN-O3-NEXT:Default Regalloc Eviction Advisor +; GCN-O3-NEXT:Default Regalloc Priority Advisor ; GCN-O3-NEXT: ModulePass Manager ; GCN-O3-NEXT: Pre-ISel Intrinsic Lowering ; GCN-O3-NEXT: FunctionPass Manager diff --git a/llvm/test/CodeGen/Generic/llc-start-stop.ll b/llvm/test/CodeGen/Generic/llc-start-stop.ll --- a/llvm/test/CodeGen/Generic/llc-start-stop.ll +++ b/llvm/test/CodeGen/Generic/llc-start-stop.ll @@ -21,7 +21,7 @@ ; START-AFTER-NEXT: Dominator Tree Construction ; RUN: llc < %s -debug-pass=Structure -start-before=loop-reduce -o /dev/null 2>&1 | FileCheck %s -check-prefix=START-BEFORE -; START-BEFORE: -machine-branch-prob -regalloc-evict -domtree +; START-BEFORE: -machine-branch-prob -regalloc-evict -regalloc-priority -domtree ; START-BEFORE: FunctionPass Manager ; START-BEFORE: Loop Strength Reduction ; START-BEFORE-NEXT: Basic Alias Analysis (stateless AA impl) diff --git a/llvm/test/CodeGen/MLRegalloc/default-priority-advisor.ll b/llvm/test/CodeGen/MLRegalloc/default-priority-advisor.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/MLRegalloc/default-priority-advisor.ll @@ -0,0 +1,20 @@ +; Check that, in the absence of dependencies, we emit an error message when +; trying to use ML-driven advisor. +; REQUIRES: !have_tf_aot +; REQUIRES: !have_tf_api +; REQUIRES: default_triple +; RUN: not llc -O2 -regalloc-enable-priority-advisor=development < %s 2>&1 | FileCheck %s +; RUN: not llc -O2 -regalloc-enable-priority-advisor=release < %s 2>&1 | FileCheck %s +; RUN: llc -O2 -regalloc-enable-priority-advisor=default < %s 2>&1 | FileCheck %s --check-prefix=DEFAULT + +; regalloc-enable-priority-advisor is not enabled for NVPTX +; UNSUPPORTED: nvptx + +define void @f2(i64 %lhs, i64 %rhs, i64* %addr) { + %sum = add i64 %lhs, %rhs + store i64 %sum, i64* %addr + ret void +} + +; CHECK: Requested regalloc priority advisor analysis could be created. Using default +; DEFAULT-NOT: Requested regalloc priority advisor analysis could be created. Using default diff --git a/llvm/test/CodeGen/PowerPC/O3-pipeline.ll b/llvm/test/CodeGen/PowerPC/O3-pipeline.ll --- a/llvm/test/CodeGen/PowerPC/O3-pipeline.ll +++ b/llvm/test/CodeGen/PowerPC/O3-pipeline.ll @@ -15,6 +15,7 @@ ; CHECK-NEXT: Create Garbage Collector Module Metadata ; CHECK-NEXT: Machine Branch Probability Analysis ; CHECK-NEXT: Default Regalloc Eviction Advisor +; CHECK-NEXT: Default Regalloc Priority Advisor ; CHECK-NEXT: ModulePass Manager ; CHECK-NEXT: Pre-ISel Intrinsic Lowering ; CHECK-NEXT: FunctionPass Manager diff --git a/llvm/test/CodeGen/RISCV/O3-pipeline.ll b/llvm/test/CodeGen/RISCV/O3-pipeline.ll --- a/llvm/test/CodeGen/RISCV/O3-pipeline.ll +++ b/llvm/test/CodeGen/RISCV/O3-pipeline.ll @@ -19,6 +19,7 @@ ; CHECK-NEXT: Create Garbage Collector Module Metadata ; CHECK-NEXT: Machine Branch Probability Analysis ; CHECK-NEXT: Default Regalloc Eviction Advisor +; CHECK-NEXT: Default Regalloc Priority Advisor ; CHECK-NEXT: ModulePass Manager ; CHECK-NEXT: Pre-ISel Intrinsic Lowering ; CHECK-NEXT: FunctionPass Manager diff --git a/llvm/test/CodeGen/X86/opt-pipeline.ll b/llvm/test/CodeGen/X86/opt-pipeline.ll --- a/llvm/test/CodeGen/X86/opt-pipeline.ll +++ b/llvm/test/CodeGen/X86/opt-pipeline.ll @@ -23,6 +23,7 @@ ; CHECK-NEXT: Create Garbage Collector Module Metadata ; CHECK-NEXT: Machine Branch Probability Analysis ; CHECK-NEXT: Default Regalloc Eviction Advisor +; CHECK-NEXT: Default Regalloc Priority Advisor ; CHECK-NEXT: ModulePass Manager ; CHECK-NEXT: Pre-ISel Intrinsic Lowering ; CHECK-NEXT: FunctionPass Manager