From 976c581d53e988e5fe1b67fdda0715b537456486 Mon Sep 17 00:00:00 2001 From: PaperChalice Date: Fri, 7 Jun 2024 19:42:23 +0800 Subject: [PATCH 1/3] [CodeGen][NewPM] Handle `--regalloc-npm` option The final register allocation pass is now determined by `PassBuilder`. However, register allocation passes are now wrapped by pass manager, start/stop options will no longer works for these passes, becuase I'm not sure will LLVM allow plugins to replace register allocator. --- llvm/include/llvm/Passes/CodeGenPassBuilder.h | 60 +++++++-------- llvm/include/llvm/Passes/PassBuilder.h | 21 +++++- llvm/include/llvm/Target/TargetMachine.h | 2 +- llvm/lib/Passes/PassBuilder.cpp | 73 ++++++++++++++++++- .../AMDGPU/AMDGPUCodeGenPassBuilder.cpp | 15 +++- .../Target/AMDGPU/AMDGPUCodeGenPassBuilder.h | 4 +- .../lib/Target/AMDGPU/AMDGPUTargetMachine.cpp | 37 ++++++++-- llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.h | 2 +- .../Target/AMDGPU/R600CodeGenPassBuilder.cpp | 8 +- .../Target/AMDGPU/R600CodeGenPassBuilder.h | 2 +- llvm/lib/Target/AMDGPU/R600TargetMachine.cpp | 12 +-- llvm/lib/Target/AMDGPU/R600TargetMachine.h | 2 +- llvm/lib/Target/X86/CMakeLists.txt | 1 + llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp | 9 +-- llvm/lib/Target/X86/X86TargetMachine.h | 2 +- .../test/tools/llc/new-pm/regalloc-amdgpu.mir | 8 ++ llvm/tools/llc/NewPMDriver.cpp | 2 +- 17 files changed, 196 insertions(+), 64 deletions(-) diff --git a/llvm/include/llvm/Passes/CodeGenPassBuilder.h b/llvm/include/llvm/Passes/CodeGenPassBuilder.h index eef1709bce5df..efef647cfd4df 100644 --- a/llvm/include/llvm/Passes/CodeGenPassBuilder.h +++ b/llvm/include/llvm/Passes/CodeGenPassBuilder.h @@ -59,10 +59,12 @@ #include "llvm/IRPrinter/IRPrintingPasses.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCTargetOptions.h" +#include "llvm/Passes/PassBuilder.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Target/CGPassBuilderOption.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/CFGuard.h" @@ -116,9 +118,8 @@ namespace llvm { template class CodeGenPassBuilder { public: explicit CodeGenPassBuilder(TargetMachineT &TM, - const CGPassBuilderOption &Opts, - PassInstrumentationCallbacks *PIC) - : TM(TM), Opt(Opts), PIC(PIC) { + const CGPassBuilderOption &Opts, PassBuilder &PB) + : TM(TM), Opt(Opts), PB(PB), PIC(PB.getPassInstrumentationCallbacks()) { // Target could set CGPassBuilderOption::MISchedPostRA to true to achieve // substitutePass(&PostRASchedulerID, &PostMachineSchedulerID) @@ -253,6 +254,7 @@ template class CodeGenPassBuilder { TargetMachineT &TM; CGPassBuilderOption Opt; + PassBuilder &PB; PassInstrumentationCallbacks *PIC; template TMC &getTM() const { return static_cast(TM); } @@ -453,13 +455,9 @@ template class CodeGenPassBuilder { /// Utilities for targets to add passes to the pass manager. /// - /// createTargetRegisterAllocator - Create the register allocator pass for - /// this target at the current optimization level. - void addTargetRegisterAllocator(AddMachinePass &, bool Optimized) const; - /// addMachinePasses helper to create the target-selected or overriden /// regalloc pass. - void addRegAllocPass(AddMachinePass &, bool Optimized) const; + Error addRegAllocPass(AddMachinePass &, StringRef FilterName = "all") const; /// Add core register alloator passes which do the actual register assignment /// and rewriting. \returns true if any passes were added. @@ -521,6 +519,9 @@ Error CodeGenPassBuilder::buildPipeline( return StartStopInfo.takeError(); setStartStopPasses(*StartStopInfo); + if (auto Err = PB.parseRegAllocOpt(Opt.RegAlloc)) + return Err; + bool PrintAsm = TargetPassConfig::willCompleteCodeGenPipeline(); bool PrintMIR = !PrintAsm && FileType != CodeGenFileType::Null; @@ -1025,45 +1026,40 @@ void CodeGenPassBuilder::addMachineSSAOptimization( /// Register Allocation Pass Configuration //===---------------------------------------------------------------------===// -/// Instantiate the default register allocator pass for this target for either -/// the optimized or unoptimized allocation path. This will be added to the pass -/// manager by addFastRegAlloc in the unoptimized case or addOptimizedRegAlloc -/// in the optimized case. -/// -/// A target that uses the standard regalloc pass order for fast or optimized -/// allocation may still override this for per-target regalloc -/// selection. But -regalloc=... always takes precedence. -template -void CodeGenPassBuilder::addTargetRegisterAllocator( - AddMachinePass &addPass, bool Optimized) const { - if (Optimized) - addPass(RAGreedyPass()); - else - addPass(RegAllocFastPass()); -} - /// Find and instantiate the register allocation pass requested by this target /// at the current optimization level. Different register allocators are /// defined as separate passes because they may require different analysis. template -void CodeGenPassBuilder::addRegAllocPass( - AddMachinePass &addPass, bool Optimized) const { - // TODO: Parse Opt.RegAlloc to add register allocator. +Error CodeGenPassBuilder::addRegAllocPass( + AddMachinePass &addPass, StringRef FilterName) const { + auto &RegAllocMap = PB.getRegAllocMap(); + if (RegAllocMap.contains("none")) + return Error::success(); + + if (!RegAllocMap.contains(FilterName)) { + return make_error( + formatv("No register allocator for register class filter '{0}'", + FilterName) + .str(), + inconvertibleErrorCode()); + } + + addPass(std::move(RegAllocMap[FilterName])); + return Error::success(); } template Error CodeGenPassBuilder::addRegAssignmentFast( AddMachinePass &addPass) const { - // TODO: Ensure allocator is default or fast. - addRegAllocPass(addPass, false); - return Error::success(); + return addRegAllocPass(addPass); } template Error CodeGenPassBuilder::addRegAssignmentOptimized( AddMachinePass &addPass) const { // Add the selected register allocation pass. - addRegAllocPass(addPass, true); + if (auto Err = addRegAllocPass(addPass)) + return Err; // Allow targets to change the register assignments before rewriting. derived().addPreRewrite(addPass); diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h index ed817127c3db1..7dac72a80a7f7 100644 --- a/llvm/include/llvm/Passes/PassBuilder.h +++ b/llvm/include/llvm/Passes/PassBuilder.h @@ -107,6 +107,7 @@ class PassBuilder { PipelineTuningOptions PTO; std::optional PGOOpt; PassInstrumentationCallbacks *PIC; + StringMap RegAllocMap; public: /// A struct to capture parsed pass pipeline names. @@ -582,12 +583,28 @@ 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. + /// separately. Currently "all" and "none" are preserved filter name. void registerRegClassFilterParsingCallback( const std::function &C) { RegClassFilterParsingCallbacks.push_back(C); } + /// Parse command line option `--regalloc-npm` + /// Should only be called by CodeGenPassBuilder. + Error parseRegAllocOpt(StringRef Text); + + /// Target hook to set default regalloc. + void setDefaultRegAllocBuilder( + const std::function &)> &C) { + DefaultRegAllocBuilder = C; + } + + /// Used by CodeGenPassBuilder to add correct regalloc pass. + /// Should only be called by CodeGenPassBuilder. + StringMap &getRegAllocMap() { + return RegAllocMap; + } + /// Register a callback for a top-level pipeline entry. /// /// If the PassManager type is not given at the top level of the pipeline @@ -807,6 +824,8 @@ class PassBuilder { // Callbacks to parse `filter` parameter in register allocation passes SmallVector, 2> RegClassFilterParsingCallbacks; + std::function &)> + DefaultRegAllocBuilder; }; /// This utility template takes care of adding require<> and invalidate<> diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h index 1ba99730ca702..509db15088123 100644 --- a/llvm/include/llvm/Target/TargetMachine.h +++ b/llvm/include/llvm/Target/TargetMachine.h @@ -472,7 +472,7 @@ class LLVMTargetMachine : public TargetMachine { virtual Error buildCodeGenPipeline(ModulePassManager &, raw_pwrite_stream &, raw_pwrite_stream *, CodeGenFileType, const CGPassBuilderOption &, - PassInstrumentationCallbacks *) { + PassBuilder &) { return make_error("buildCodeGenPipeline is not overridden", inconvertibleErrorCode()); } diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index 2c56b04a1d9c8..7ae398ce87dbb 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -409,13 +409,33 @@ class RequireAllMachineFunctionPropertiesPass } // namespace +static void defaultRegAllocBuilder(TargetMachine *TM, + StringMap &M) { + if (!TM) + return; + + MachineFunctionPassManager MFPM; + auto Opts = getCGPassBuilderOption(); + if (Opts.OptimizeRegAlloc.value_or(TM->getOptLevel() != + CodeGenOptLevel::None)) { + // TODO: Add greedy register allocator. + } else { + MFPM.addPass(RegAllocFastPass()); + } + M["all"] = std::move(MFPM); +} + PassBuilder::PassBuilder(TargetMachine *TM, PipelineTuningOptions PTO, std::optional PGOOpt, PassInstrumentationCallbacks *PIC) : TM(TM), PTO(PTO), PGOOpt(PGOOpt), PIC(PIC) { bool ShouldPopulateClassToPassNames = PIC && shouldPopulateClassToPassNames(); - if (TM) + if (TM) { + DefaultRegAllocBuilder = [TM](StringMap &M) { + defaultRegAllocBuilder(TM, M); + }; TM->registerPassBuilderCallbacks(*this, ShouldPopulateClassToPassNames); + } if (ShouldPopulateClassToPassNames) { #define MODULE_PASS(NAME, CREATE_PASS) \ PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); @@ -2219,6 +2239,18 @@ Error PassBuilder::parseAAPipeline(AAManager &AA, StringRef PipelineText) { return Error::success(); } +static StringRef getFilterName(StringRef PassName) { + PassName = PassName.drop_until([](char C) { return C == '<'; }); + StringRef Params = PassName.drop_front().drop_back(); + while (!Params.empty()) { + StringRef ParamName; + std::tie(ParamName, Params) = Params.split(';'); + if (ParamName.consume_front("filter=")) + return ParamName; + } + return "all"; +} + RegClassFilterFunc PassBuilder::parseRegAllocFilter(StringRef FilterName) { if (FilterName == "all") return allocateAllRegClasses; @@ -2228,6 +2260,45 @@ RegClassFilterFunc PassBuilder::parseRegAllocFilter(StringRef FilterName) { return nullptr; } +Error PassBuilder::parseRegAllocOpt(StringRef Text) { + assert(TM && "Need target machine to parse this option!"); + if (RegAllocMap.empty()) + DefaultRegAllocBuilder(RegAllocMap); + + MachineFunctionPassManager MFPM; + if (Text == "default") { + // Add nothing when target inserts "none" into the map. + if (RegAllocMap.contains("none")) + RegAllocMap["all"] = MachineFunctionPassManager(); + return Error::success(); + } + + if (RegAllocMap.contains("none")) { + return make_error( + "Target doesn't support register allocation!", + inconvertibleErrorCode()); + } + + bool IsOptimized = TM->getOptLevel() != CodeGenOptLevel::None; + while (!Text.empty()) { + StringRef PassName; + std::tie(PassName, Text) = Text.split(','); + if (!IsOptimized && + !PassBuilder::checkParametrizedPassName(PassName, "regallocfast")) { + return make_error( + "Must use fast (default) register allocator for " + "unoptimized regalloc.", + inconvertibleErrorCode()); + } + // FIXME: Should only accept reg-alloc passes. + if (auto Err = parsePassPipeline(MFPM, PassName)) + return Err; + RegAllocMap[getFilterName(PassName)] = std::move(MFPM); + MFPM = MachineFunctionPassManager(); + } + return Error::success(); +} + static void printPassName(StringRef PassName, raw_ostream &OS) { OS << " " << PassName << "\n"; } diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.cpp index 7c353fd102848..4cf19434dea4c 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.cpp @@ -14,9 +14,8 @@ using namespace llvm; AMDGPUCodeGenPassBuilder::AMDGPUCodeGenPassBuilder( - AMDGPUTargetMachine &TM, const CGPassBuilderOption &Opts, - PassInstrumentationCallbacks *PIC) - : CodeGenPassBuilder(TM, Opts, PIC) { + AMDGPUTargetMachine &TM, const CGPassBuilderOption &Opts, PassBuilder &PB) + : CodeGenPassBuilder(TM, Opts, PB) { Opt.RequiresCodeGenSCCOrder = true; // Exceptions and StackMaps are not supported, so these passes will never do // anything. @@ -40,3 +39,13 @@ Error AMDGPUCodeGenPassBuilder::addInstSelector(AddMachinePass &addPass) const { addPass(AMDGPUISelDAGToDAGPass(TM)); return Error::success(); } + +Error AMDGPUCodeGenPassBuilder::addRegAssignmentFast( + AddMachinePass &addPass) const { + if (auto Err = addRegAllocPass(addPass, "sgpr")) + return Err; + // TODO: Add other passes. + if (auto Err = addRegAllocPass(addPass, "vgpr")) + return Err; + return Error::success(); +} diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.h b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.h index 5f79e309703a3..d233da863ec1e 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.h +++ b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.h @@ -20,12 +20,12 @@ class AMDGPUCodeGenPassBuilder : public CodeGenPassBuilder { public: AMDGPUCodeGenPassBuilder(AMDGPUTargetMachine &TM, - const CGPassBuilderOption &Opts, - PassInstrumentationCallbacks *PIC); + const CGPassBuilderOption &Opts, PassBuilder &PB); void addPreISel(AddIRPass &addPass) const; void addAsmPrinter(AddMachinePass &, CreateMCStreamer) const; Error addInstSelector(AddMachinePass &) const; + Error addRegAssignmentFast(AddMachinePass &addPass) const; }; } // namespace llvm diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp index ce997c659094a..577dca0d2cded 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp @@ -46,6 +46,7 @@ #include "llvm/CodeGen/GlobalISel/RegBankSelect.h" #include "llvm/CodeGen/MIRParser/MIParser.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/RegAllocFast.h" #include "llvm/CodeGen/RegAllocRegistry.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/IR/IntrinsicsAMDGPU.h" @@ -650,11 +651,13 @@ parseAMDGPUAtomicOptimizerStrategy(StringRef Params) { return make_error("invalid parameter", inconvertibleErrorCode()); } -Error AMDGPUTargetMachine::buildCodeGenPipeline( - ModulePassManager &MPM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, - CodeGenFileType FileType, const CGPassBuilderOption &Opts, - PassInstrumentationCallbacks *PIC) { - AMDGPUCodeGenPassBuilder CGPB(*this, Opts, PIC); +Error AMDGPUTargetMachine::buildCodeGenPipeline(ModulePassManager &MPM, + raw_pwrite_stream &Out, + raw_pwrite_stream *DwoOut, + CodeGenFileType FileType, + const CGPassBuilderOption &Opts, + PassBuilder &PB) { + AMDGPUCodeGenPassBuilder CGPB(*this, Opts, PB); return CGPB.buildPipeline(MPM, Out, DwoOut, FileType); } @@ -749,6 +752,30 @@ void AMDGPUTargetMachine::registerPassBuilderCallbacks( return onlyAllocateVGPRs; return nullptr; }); + + PB.setDefaultRegAllocBuilder( + [TM = this](StringMap &RegAllocMap) { + auto Opts = getCGPassBuilderOption(); + if (Opts.OptimizeRegAlloc.value_or(TM->getOptLevel() != + CodeGenOptLevel::None)) { + // TODO: Add greedy register allocator. + } else { + RegAllocFastPassOptions Opts; + Opts.Filter = onlyAllocateSGPRs; + Opts.FilterName = "sgpr"; + Opts.ClearVRegs = false; + MachineFunctionPassManager MFPM; + MFPM.addPass(RegAllocFastPass(Opts)); + RegAllocMap["sgpr"] = std::move(MFPM); + + Opts.Filter = onlyAllocateVGPRs; + Opts.FilterName = "vgpr"; + Opts.ClearVRegs = true; + MFPM = MachineFunctionPassManager(); + MFPM.addPass(RegAllocFastPass(Opts)); + RegAllocMap["vgpr"] = std::move(MFPM); + } + }); } int64_t AMDGPUTargetMachine::getNullPointerValue(unsigned AddrSpace) { diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.h b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.h index 2cfd232483a8a..2385e6ce6c6b3 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.h +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.h @@ -56,7 +56,7 @@ class AMDGPUTargetMachine : public LLVMTargetMachine { raw_pwrite_stream *DwoOut, CodeGenFileType FileType, const CGPassBuilderOption &Opts, - PassInstrumentationCallbacks *PIC) override; + PassBuilder &PB) override; void registerPassBuilderCallbacks(PassBuilder &PB, bool PopulateClassToPassNames) override; diff --git a/llvm/lib/Target/AMDGPU/R600CodeGenPassBuilder.cpp b/llvm/lib/Target/AMDGPU/R600CodeGenPassBuilder.cpp index a57b3aa0adb15..183ffe56181ce 100644 --- a/llvm/lib/Target/AMDGPU/R600CodeGenPassBuilder.cpp +++ b/llvm/lib/Target/AMDGPU/R600CodeGenPassBuilder.cpp @@ -11,10 +11,10 @@ using namespace llvm; -R600CodeGenPassBuilder::R600CodeGenPassBuilder( - R600TargetMachine &TM, const CGPassBuilderOption &Opts, - PassInstrumentationCallbacks *PIC) - : CodeGenPassBuilder(TM, Opts, PIC) { +R600CodeGenPassBuilder::R600CodeGenPassBuilder(R600TargetMachine &TM, + const CGPassBuilderOption &Opts, + PassBuilder &PB) + : CodeGenPassBuilder(TM, Opts, PB) { Opt.RequiresCodeGenSCCOrder = true; } diff --git a/llvm/lib/Target/AMDGPU/R600CodeGenPassBuilder.h b/llvm/lib/Target/AMDGPU/R600CodeGenPassBuilder.h index be7c935c094d9..06820f5258266 100644 --- a/llvm/lib/Target/AMDGPU/R600CodeGenPassBuilder.h +++ b/llvm/lib/Target/AMDGPU/R600CodeGenPassBuilder.h @@ -20,7 +20,7 @@ class R600CodeGenPassBuilder : public CodeGenPassBuilder { public: R600CodeGenPassBuilder(R600TargetMachine &TM, const CGPassBuilderOption &Opts, - PassInstrumentationCallbacks *PIC); + PassBuilder &PB); void addPreISel(AddIRPass &addPass) const; void addAsmPrinter(AddMachinePass &, CreateMCStreamer) const; diff --git a/llvm/lib/Target/AMDGPU/R600TargetMachine.cpp b/llvm/lib/Target/AMDGPU/R600TargetMachine.cpp index c550cfaf06c10..f4eb0d5692a6e 100644 --- a/llvm/lib/Target/AMDGPU/R600TargetMachine.cpp +++ b/llvm/lib/Target/AMDGPU/R600TargetMachine.cpp @@ -146,10 +146,12 @@ TargetPassConfig *R600TargetMachine::createPassConfig(PassManagerBase &PM) { return new R600PassConfig(*this, PM); } -Error R600TargetMachine::buildCodeGenPipeline( - ModulePassManager &MPM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, - CodeGenFileType FileType, const CGPassBuilderOption &Opts, - PassInstrumentationCallbacks *PIC) { - R600CodeGenPassBuilder CGPB(*this, Opts, PIC); +Error R600TargetMachine::buildCodeGenPipeline(ModulePassManager &MPM, + raw_pwrite_stream &Out, + raw_pwrite_stream *DwoOut, + CodeGenFileType FileType, + const CGPassBuilderOption &Opts, + PassBuilder &PB) { + R600CodeGenPassBuilder CGPB(*this, Opts, PB); return CGPB.buildPipeline(MPM, Out, DwoOut, FileType); } diff --git a/llvm/lib/Target/AMDGPU/R600TargetMachine.h b/llvm/lib/Target/AMDGPU/R600TargetMachine.h index 29e370edef2c6..9f49c8189d53f 100644 --- a/llvm/lib/Target/AMDGPU/R600TargetMachine.h +++ b/llvm/lib/Target/AMDGPU/R600TargetMachine.h @@ -42,7 +42,7 @@ class R600TargetMachine final : public AMDGPUTargetMachine { raw_pwrite_stream *DwoOut, CodeGenFileType FileType, const CGPassBuilderOption &Opt, - PassInstrumentationCallbacks *PIC) override; + PassBuilder &PB) override; const TargetSubtargetInfo *getSubtargetImpl(const Function &) const override; diff --git a/llvm/lib/Target/X86/CMakeLists.txt b/llvm/lib/Target/X86/CMakeLists.txt index 44a54c8ec62cb..4540169fe6de4 100644 --- a/llvm/lib/Target/X86/CMakeLists.txt +++ b/llvm/lib/Target/X86/CMakeLists.txt @@ -102,6 +102,7 @@ add_llvm_target(X86CodeGen ${sources} IRPrinter Instrumentation MC + Passes ProfileData Scalar SelectionDAG diff --git a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp index 9819bfd129855..66afe31074b1a 100644 --- a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp +++ b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp @@ -26,8 +26,8 @@ class X86CodeGenPassBuilder public: explicit X86CodeGenPassBuilder(X86TargetMachine &TM, const CGPassBuilderOption &Opts, - PassInstrumentationCallbacks *PIC) - : CodeGenPassBuilder(TM, Opts, PIC) {} + PassBuilder &PB) + : CodeGenPassBuilder(TM, Opts, PB) {} void addPreISel(AddIRPass &addPass) const; void addAsmPrinter(AddMachinePass &, CreateMCStreamer) const; Error addInstSelector(AddMachinePass &) const; @@ -58,8 +58,7 @@ void X86TargetMachine::registerPassBuilderCallbacks( Error X86TargetMachine::buildCodeGenPipeline( ModulePassManager &MPM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, - CodeGenFileType FileType, const CGPassBuilderOption &Opt, - PassInstrumentationCallbacks *PIC) { - auto CGPB = X86CodeGenPassBuilder(*this, Opt, PIC); + CodeGenFileType FileType, const CGPassBuilderOption &Opt, PassBuilder &PB) { + auto CGPB = X86CodeGenPassBuilder(*this, Opt, PB); return CGPB.buildPipeline(MPM, Out, DwoOut, FileType); } diff --git a/llvm/lib/Target/X86/X86TargetMachine.h b/llvm/lib/Target/X86/X86TargetMachine.h index 4a5f20fcc0172..54f5a8a58a3bc 100644 --- a/llvm/lib/Target/X86/X86TargetMachine.h +++ b/llvm/lib/Target/X86/X86TargetMachine.h @@ -64,7 +64,7 @@ class X86TargetMachine final : public LLVMTargetMachine { Error buildCodeGenPipeline(ModulePassManager &, raw_pwrite_stream &, raw_pwrite_stream *, CodeGenFileType, const CGPassBuilderOption &, - PassInstrumentationCallbacks *) override; + PassBuilder &PB) override; bool isJIT() const { return IsJIT; } diff --git a/llvm/test/tools/llc/new-pm/regalloc-amdgpu.mir b/llvm/test/tools/llc/new-pm/regalloc-amdgpu.mir index 0603ffc4c5ea2..152d81e95eeb1 100644 --- a/llvm/test/tools/llc/new-pm/regalloc-amdgpu.mir +++ b/llvm/test/tools/llc/new-pm/regalloc-amdgpu.mir @@ -1,10 +1,18 @@ # REQUIRES: amdgpu-registered-target # RUN: llc -mtriple=amdgcn --passes='regallocfast' --print-pipeline-passes %s | FileCheck %s --check-prefix=PASS # RUN: not llc -mtriple=amdgcn --passes='regallocfast' --print-pipeline-passes --filetype=null %s 2>&1 | FileCheck %s --check-prefix=BAD-FILTER +# RUN: llc -mtriple=amdgcn-- -enable-new-pm -print-pipeline-passes --filetype=null -O0 %s | FileCheck %s --check-prefix=DEFAULT-O0-REG-ALLOC +# RUN: llc -mtriple=amdgcn-- --regalloc-npm='regallocfast' -enable-new-pm -print-pipeline-passes --filetype=null -O0 %s | FileCheck %s --check-prefix=REG-ALLOC-NPM # PASS: regallocfast # BAD-FILTER: invalid regallocfast register filter 'bad-filter' +# DEFAULT-O0-REG-ALLOC: regallocfast +# DEFAULT-O0-REG-ALLOC: regallocfast + +# REG-ALLOC-NPM: regallocfast +# REG-ALLOC-NPM: regallocfast + --- name: f ... diff --git a/llvm/tools/llc/NewPMDriver.cpp b/llvm/tools/llc/NewPMDriver.cpp index fb1959c6457f4..2eb8293c8fe7b 100644 --- a/llvm/tools/llc/NewPMDriver.cpp +++ b/llvm/tools/llc/NewPMDriver.cpp @@ -159,7 +159,7 @@ int llvm::compileModuleWithNewPM( return 1; } else { ExitOnErr(LLVMTM.buildCodeGenPipeline( - MPM, *OS, DwoOut ? &DwoOut->os() : nullptr, FileType, Opt, &PIC)); + MPM, *OS, DwoOut ? &DwoOut->os() : nullptr, FileType, Opt, PB)); } if (PrintPipelinePasses) { From 4f1ae8c9175dced1d0a74b822a34bf4024057d33 Mon Sep 17 00:00:00 2001 From: PaperChalice Date: Fri, 7 Jun 2024 21:11:52 +0800 Subject: [PATCH 2/3] Address comments, and fix getFilterName issue --- llvm/lib/Passes/PassBuilder.cpp | 5 +++-- llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp | 14 +++++--------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index 7ae398ce87dbb..98371f11071ab 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -2240,8 +2240,9 @@ Error PassBuilder::parseAAPipeline(AAManager &AA, StringRef PipelineText) { } static StringRef getFilterName(StringRef PassName) { - PassName = PassName.drop_until([](char C) { return C == '<'; }); - StringRef Params = PassName.drop_front().drop_back(); + StringRef Params = PassName.drop_until([](char C) { return C == '<'; }); + if (!Params.empty()) + Params = Params.drop_front().drop_back(); while (!Params.empty()) { StringRef ParamName; std::tie(ParamName, Params) = Params.split(';'); diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp index 577dca0d2cded..6cf76e1724629 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp @@ -760,19 +760,15 @@ void AMDGPUTargetMachine::registerPassBuilderCallbacks( CodeGenOptLevel::None)) { // TODO: Add greedy register allocator. } else { - RegAllocFastPassOptions Opts; - Opts.Filter = onlyAllocateSGPRs; - Opts.FilterName = "sgpr"; - Opts.ClearVRegs = false; + RegAllocFastPassOptions SGPRRunOpts{allocateAllRegClasses, "sgpr", + false}; MachineFunctionPassManager MFPM; - MFPM.addPass(RegAllocFastPass(Opts)); + MFPM.addPass(RegAllocFastPass(SGPRRunOpts)); RegAllocMap["sgpr"] = std::move(MFPM); - Opts.Filter = onlyAllocateVGPRs; - Opts.FilterName = "vgpr"; - Opts.ClearVRegs = true; + RegAllocFastPassOptions VGPRRunOpts{onlyAllocateVGPRs, "vgpr", true}; MFPM = MachineFunctionPassManager(); - MFPM.addPass(RegAllocFastPass(Opts)); + MFPM.addPass(RegAllocFastPass(VGPRRunOpts)); RegAllocMap["vgpr"] = std::move(MFPM); } }); From 51df332f036db59e31a0af2ff418769ac2c80e76 Mon Sep 17 00:00:00 2001 From: PaperChalice Date: Sat, 8 Jun 2024 16:38:34 +0800 Subject: [PATCH 3/3] Fix more issues in CodeGenPassBuilder --- llvm/include/llvm/Passes/CodeGenPassBuilder.h | 34 +++++++++++-------- .../AMDGPU/AMDGPUCodeGenPassBuilder.cpp | 6 ++++ .../Target/AMDGPU/AMDGPUCodeGenPassBuilder.h | 1 + 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/llvm/include/llvm/Passes/CodeGenPassBuilder.h b/llvm/include/llvm/Passes/CodeGenPassBuilder.h index efef647cfd4df..54343f96b5cb3 100644 --- a/llvm/include/llvm/Passes/CodeGenPassBuilder.h +++ b/llvm/include/llvm/Passes/CodeGenPassBuilder.h @@ -433,7 +433,7 @@ template class CodeGenPassBuilder { /// addOptimizedRegAlloc - Add passes related to register allocation. /// LLVMTargetMachine provides standard regalloc passes for most targets. - void addOptimizedRegAlloc(AddMachinePass &) const; + Error addOptimizedRegAlloc(AddMachinePass &) const; /// Add passes that optimize machine instructions after register allocation. void addMachineLateOptimization(AddMachinePass &) const; @@ -896,7 +896,8 @@ Error CodeGenPassBuilder::addMachinePasses( // Run register allocation and passes that are tightly coupled with it, // including phi elimination and scheduling. if (*Opt.OptimizeRegAlloc) { - derived().addOptimizedRegAlloc(addPass); + if (auto Err = derived().addOptimizedRegAlloc(addPass)) + return Err; } else { if (auto Err = derived().addFastRegAlloc(addPass)) return Err; @@ -1089,7 +1090,7 @@ Error CodeGenPassBuilder::addFastRegAlloc( /// optimized register allocation, including coalescing, machine instruction /// scheduling, and register allocation itself. template -void CodeGenPassBuilder::addOptimizedRegAlloc( +Error CodeGenPassBuilder::addOptimizedRegAlloc( AddMachinePass &addPass) const { addPass(DetectDeadLanesPass()); @@ -1115,20 +1116,23 @@ void CodeGenPassBuilder::addOptimizedRegAlloc( // PreRA instruction scheduling. addPass(MachineSchedulerPass()); - if (derived().addRegAssignmentOptimized(addPass)) { - // Allow targets to expand pseudo instructions depending on the choice of - // registers before MachineCopyPropagation. - derived().addPostRewrite(addPass); + if (auto Err = derived().addRegAssignmentOptimized(addPass)) + return Err; - // Copy propagate to forward register uses and try to eliminate COPYs that - // were not coalesced. - addPass(MachineCopyPropagationPass()); + // Allow targets to expand pseudo instructions depending on the choice of + // registers before MachineCopyPropagation. + derived().addPostRewrite(addPass); - // Run post-ra machine LICM to hoist reloads / remats. - // - // FIXME: can this move into MachineLateOptimization? - addPass(MachineLICMPass()); - } + // Copy propagate to forward register uses and try to eliminate COPYs that + // were not coalesced. + addPass(MachineCopyPropagationPass()); + + // Run post-ra machine LICM to hoist reloads / remats. + // + // FIXME: can this move into MachineLateOptimization? + addPass(MachineLICMPass()); + + return Error::success(); } //===---------------------------------------------------------------------===// diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.cpp index 4cf19434dea4c..3a93c498fd9dd 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.cpp @@ -49,3 +49,9 @@ Error AMDGPUCodeGenPassBuilder::addRegAssignmentFast( return Err; return Error::success(); } + +Error AMDGPUCodeGenPassBuilder::addRegAssignmentOptimized( + AddMachinePass &addPass) const { + // TODO: Add greedy register allocator. + return Error::success(); +} diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.h b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.h index d233da863ec1e..351225c0d041c 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.h +++ b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.h @@ -26,6 +26,7 @@ class AMDGPUCodeGenPassBuilder void addAsmPrinter(AddMachinePass &, CreateMCStreamer) const; Error addInstSelector(AddMachinePass &) const; Error addRegAssignmentFast(AddMachinePass &addPass) const; + Error addRegAssignmentOptimized(AddMachinePass &) const; }; } // namespace llvm