[llvm] [CodeGen][NewPM] Introduce CodeGenPassManager (PR #210473)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Jul 19 04:45:02 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-webassembly
Author: paperchalice
<details>
<summary>Changes</summary>
I still believe that coupling CodeGenPassBuilder with pass managers is not a good idea. It currently:
- Can't handle {start,stop}-{before,after} with insertPass.
- For pass plugins, we need to expose methods in `CodeGenPassBuilder` so users can use start,stop}-{before,after} with custom passes.
This pull request introduces CodeGenPassManagers which is dedicated to build CodeGen pass pipeline. It supports `eraseIf` and pass insertion. This also can detect return type from hooks like `addAsmPrinter` etc. to avoid unexpected usage, see also addISelPrepare, which might return CodeGenModulePassManager.
---
Patch is 143.75 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/210473.diff
19 Files Affected:
- (modified) llvm/include/llvm/Passes/CodeGenPassBuilder.h (+366-404)
- (added) llvm/include/llvm/Passes/CodeGenPassManager.h (+238)
- (modified) llvm/lib/Passes/CMakeLists.txt (+1)
- (added) llvm/lib/Passes/CodeGenPassManager.cpp (+227)
- (modified) llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp (+4-1)
- (modified) llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp (+190-183)
- (modified) llvm/lib/Target/AMDGPU/R600TargetMachine.cpp (+15-10)
- (modified) llvm/lib/Target/BPF/BPFCodeGenPassBuilder.cpp (+35-28)
- (modified) llvm/lib/Target/Lanai/CMakeLists.txt (+1)
- (modified) llvm/lib/Target/Lanai/LanaiCodeGenPassBuilder.cpp (+30-22)
- (modified) llvm/lib/Target/MSP430/CMakeLists.txt (+1)
- (modified) llvm/lib/Target/MSP430/MSP430CodeGenPassBuilder.cpp (+26-19)
- (modified) llvm/lib/Target/WebAssembly/CMakeLists.txt (+1)
- (modified) llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp (+43-36)
- (modified) llvm/lib/Target/X86/CMakeLists.txt (+1)
- (modified) llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp (+101-87)
- (modified) llvm/test/CodeGen/AMDGPU/llc-pipeline-npm.ll (-3)
- (modified) llvm/test/tools/llc/new-pm/start-stop-inserted.ll (+2-4)
- (modified) llvm/test/tools/llc/new-pm/start-stop.ll (+28-4)
``````````diff
diff --git a/llvm/include/llvm/Passes/CodeGenPassBuilder.h b/llvm/include/llvm/Passes/CodeGenPassBuilder.h
index 6a93e61ea111d..af421976d597c 100644
--- a/llvm/include/llvm/Passes/CodeGenPassBuilder.h
+++ b/llvm/include/llvm/Passes/CodeGenPassBuilder.h
@@ -106,6 +106,7 @@
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Passes/CodeGenPassManager.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
@@ -155,18 +156,6 @@ namespace llvm {
};
#include "llvm/Passes/MachinePassRegistry.def"
-class PassManagerWrapper {
-private:
- PassManagerWrapper(ModulePassManager &ModulePM) : MPM(ModulePM) {};
-
- ModulePassManager &MPM;
- FunctionPassManager FPM;
- MachineFunctionPassManager MFPM;
-
- template <typename DerivedT, typename TargetMachineT>
- friend class CodeGenPassBuilder;
-};
-
/// This class provides access to building LLVM's passes.
///
/// Its members provide the baseline state available to passes during their
@@ -209,93 +198,6 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
}
protected:
- template <typename PassT>
- using is_module_pass_t = decltype(std::declval<PassT &>().run(
- std::declval<Module &>(), std::declval<ModuleAnalysisManager &>()));
-
- template <typename PassT>
- using is_function_pass_t = decltype(std::declval<PassT &>().run(
- std::declval<Function &>(), std::declval<FunctionAnalysisManager &>()));
-
- template <typename PassT>
- using is_machine_function_pass_t = decltype(std::declval<PassT &>().run(
- std::declval<MachineFunction &>(),
- std::declval<MachineFunctionAnalysisManager &>()));
-
- template <typename PassT>
- void addFunctionPass(PassT &&Pass, PassManagerWrapper &PMW,
- bool Force = false,
- StringRef Name = PassT::name()) const {
- static_assert(is_detected<is_function_pass_t, PassT>::value &&
- "Only function passes are supported.");
- if (!Force && !runBeforeAdding(Name))
- return;
- PMW.FPM.addPass(std::forward<PassT>(Pass));
- }
-
- template <typename PassT>
- void addModulePass(PassT &&Pass, PassManagerWrapper &PMW, bool Force = false,
- StringRef Name = PassT::name()) const {
- static_assert(is_detected<is_module_pass_t, PassT>::value &&
- "Only module passes are suported.");
- assert(PMW.FPM.isEmpty() && PMW.MFPM.isEmpty() &&
- "You cannot insert a module pass without first flushing the current "
- "function pipelines to the module pipeline.");
- if (!Force && !runBeforeAdding(Name))
- return;
- PMW.MPM.addPass(std::forward<PassT>(Pass));
- }
-
- template <typename PassT>
- void addMachineFunctionPass(PassT &&Pass, PassManagerWrapper &PMW,
- bool Force = false,
- StringRef Name = PassT::name()) const {
- static_assert(is_detected<is_machine_function_pass_t, PassT>::value &&
- "Only machine function passes are supported.");
-
- if (!Force && !runBeforeAdding(Name))
- return;
- PMW.MFPM.addPass(std::forward<PassT>(Pass));
- for (auto &C : AfterCallbacks)
- C(Name, PMW.MFPM);
- }
-
- void flushFPMsToMPM(PassManagerWrapper &PMW,
- bool FreeMachineFunctions = false) const {
- if (PMW.FPM.isEmpty() && PMW.MFPM.isEmpty())
- return;
- if (!PMW.MFPM.isEmpty()) {
- PMW.FPM.addPass(
- createFunctionToMachineFunctionPassAdaptor(std::move(PMW.MFPM)));
- PMW.MFPM = MachineFunctionPassManager();
- }
- if (FreeMachineFunctions)
- PMW.FPM.addPass(FreeMachineFunctionPass());
- if (AddInCGSCCOrder) {
- PMW.MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
- createCGSCCToFunctionPassAdaptor(std::move(PMW.FPM))));
- } else {
- PMW.MPM.addPass(createModuleToFunctionPassAdaptor(std::move(PMW.FPM)));
- }
- PMW.FPM = FunctionPassManager();
- }
-
- void requireCGSCCOrder(PassManagerWrapper &PMW) const {
- assert(!AddInCGSCCOrder);
- assert(PMW.FPM.isEmpty() && PMW.MFPM.isEmpty() &&
- "Requiring CGSCC ordering requires flushing the current function "
- "pipelines to the MPM.");
- AddInCGSCCOrder = true;
- }
-
- void stopAddingInCGSCCOrder(PassManagerWrapper &PMW) const {
- assert(AddInCGSCCOrder);
- assert(PMW.FPM.isEmpty() && PMW.MFPM.isEmpty() &&
- "Stopping CGSCC ordering requires flushing the current function "
- "pipelines to the MPM.");
- AddInCGSCCOrder = false;
- }
-
TargetMachineT &TM;
CGPassBuilderOption Opt;
PassInstrumentationCallbacks *PIC;
@@ -319,13 +221,13 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
/// addInstSelector - This method should install an instruction selector pass,
/// which converts from LLVM code to machine instructions.
- Error addInstSelector(PassManagerWrapper &PMW) const {
+ Error addInstSelector(CodeGenMachineFunctionPassManager &CGMFPM) const {
return make_error<StringError>("addInstSelector is not overridden",
inconvertibleErrorCode());
}
/// Target can override this to add GlobalMergePass before all IR passes.
- void addGlobalMergePass(PassManagerWrapper &PMW) const {}
+ void addGlobalMergePass(CodeGenModulePassManager &CGMPM) const {}
/// Add passes that optimize instruction level parallelism for out-of-order
/// targets. These passes are run while the machine code is still in SSA
@@ -333,11 +235,11 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
///
/// All passes added here should preserve the MachineDominatorTree,
/// MachineLoopInfo, and MachineTraceMetrics analyses.
- void addILPOpts(PassManagerWrapper &PMW) const {}
+ void addILPOpts(CodeGenMachineFunctionPassManager &CGMFPM) const {}
/// This method may be implemented by targets that want to run passes
/// immediately before register allocation.
- void addPreRegAlloc(PassManagerWrapper &PMW) const {}
+ void addPreRegAlloc(CodeGenMachineFunctionPassManager &CGMFPM) const {}
/// addPreRewrite - Add passes to the optimized register allocation pipeline
/// after register allocation is complete, but before virtual registers are
@@ -351,77 +253,82 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
/// Note if the target overloads addRegAssignAndRewriteOptimized, this may not
/// be honored. This is also not generally used for the fast variant,
/// where the allocation and rewriting are done in one pass.
- void addPreRewrite(PassManagerWrapper &PMW) const {}
+ void addPreRewrite(CodeGenMachineFunctionPassManager &CGMFPM) const {}
/// Add passes to be run immediately after virtual registers are rewritten
/// to physical registers.
- void addPostRewrite(PassManagerWrapper &PMW) const {}
+ void addPostRewrite(CodeGenMachineFunctionPassManager &CGMFPM) const {}
/// This method may be implemented by targets that want to run passes after
/// register allocation pass pipeline but before prolog-epilog insertion.
- void addPostRegAlloc(PassManagerWrapper &PMW) const {}
+ void addPostRegAlloc(CodeGenMachineFunctionPassManager &CGMFPM) const {}
/// This method may be implemented by targets that want to run passes after
/// prolog-epilog insertion and before the second instruction scheduling pass.
- void addPreSched2(PassManagerWrapper &PMW) const {}
+ void addPreSched2(CodeGenMachineFunctionPassManager &CGMFPM) const {}
/// This pass may be implemented by targets that want to run passes
/// immediately before machine code is emitted.
- void addPreEmitPass(PassManagerWrapper &PMW) const {}
+ void addPreEmitPass(CodeGenMachineFunctionPassManager &CGMFPM) const {}
/// Targets may add passes immediately before machine code is emitted in this
/// callback. This is called even later than `addPreEmitPass`.
// FIXME: Rename `addPreEmitPass` to something more sensible given its actual
// position and remove the `2` suffix here as this callback is what
// `addPreEmitPass` *should* be but in reality isn't.
- void addPreEmitPass2(PassManagerWrapper &PMW) const {}
+ void addPreEmitPass2(CodeGenMachineFunctionPassManager &CGMFPM) const {}
/// {{@ For GlobalISel
///
/// addPreISel - This method should add any "last minute" LLVM->LLVM
/// passes (which are run just before instruction selector).
- void addPreISel(PassManagerWrapper &PMW) const {}
+ CodeGenFunctionPassManager addPreISel() const {
+ return CodeGenFunctionPassManager();
+ }
/// This method should install an IR translator pass, which converts from
/// LLVM code to machine instructions with possibly generic opcodes.
- Error addIRTranslator(PassManagerWrapper &PMW) const {
+ Error addIRTranslator(CodeGenMachineFunctionPassManager &CGMFPM) const {
return make_error<StringError>("addIRTranslator is not overridden",
inconvertibleErrorCode());
}
/// This method may be implemented by targets that want to run passes
/// immediately before legalization.
- void addPreLegalizeMachineIR(PassManagerWrapper &PMW) const {}
+ void
+ addPreLegalizeMachineIR(CodeGenMachineFunctionPassManager &CGMFPM) const {}
/// This method should install a legalize pass, which converts the instruction
/// sequence into one that can be selected by the target.
- Error addLegalizeMachineIR(PassManagerWrapper &PMW) const {
+ Error addLegalizeMachineIR(CodeGenMachineFunctionPassManager &CGMFPM) const {
return make_error<StringError>("addLegalizeMachineIR is not overridden",
inconvertibleErrorCode());
}
/// This method may be implemented by targets that want to run passes
/// immediately before the register bank selection.
- void addPreRegBankSelect(PassManagerWrapper &PMW) const {}
+ void addPreRegBankSelect(CodeGenMachineFunctionPassManager &CGMFPM) const {}
/// This method should install a register bank selector pass, which
/// assigns register banks to virtual registers without a register
/// class or register banks.
- Error addRegBankSelect(PassManagerWrapper &PMW) const {
+ Error addRegBankSelect(CodeGenMachineFunctionPassManager &CGMFPM) const {
return make_error<StringError>("addRegBankSelect is not overridden",
inconvertibleErrorCode());
}
/// This method may be implemented by targets that want to run passes
/// immediately before the (global) instruction selection.
- void addPreGlobalInstructionSelect(PassManagerWrapper &PMW) const {}
+ void addPreGlobalInstructionSelect(
+ CodeGenMachineFunctionPassManager &CGMFPM) const {}
/// This method should install a (global) instruction selector pass, which
/// converts possibly generic instructions to fully target-specific
/// instructions, thereby constraining all generic virtual registers to
/// register classes.
- Error addGlobalInstructionSelect(PassManagerWrapper &PMWM) const {
+ Error
+ addGlobalInstructionSelect(CodeGenMachineFunctionPassManager &CGMFPM) const {
return make_error<StringError>(
"addGlobalInstructionSelect is not overridden",
inconvertibleErrorCode());
@@ -432,30 +339,30 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
/// representation to the MI representation.
/// Adds IR based lowering and target specific optimization passes and finally
/// the core instruction selection passes.
- void addISelPasses(PassManagerWrapper &PMW) const;
+ void addISelPasses(CodeGenModulePassManager &CGMPM) const;
/// Add the actual instruction selection passes. This does not include
/// preparation passes on IR.
- Error addCoreISelPasses(PassManagerWrapper &PMW) const;
+ Error addCoreISelPasses(CodeGenMachineFunctionPassManager &CGMFPM) const;
/// Add the complete, standard set of LLVM CodeGen passes.
/// Fully developed targets will not generally override this.
- Error addMachinePasses(PassManagerWrapper &PMW) const;
+ Error addMachinePasses(CodeGenModulePassManager &CGMPM) const;
/// Add passes to lower exception handling for the code generator.
- void addPassesToHandleExceptions(PassManagerWrapper &PMW) const;
+ void addPassesToHandleExceptions(CodeGenFunctionPassManager &CGFPM) const;
/// Add common target configurable passes that perform LLVM IR to IR
/// transforms following machine independent optimization.
- void addIRPasses(PassManagerWrapper &PMW) const;
+ void addIRPasses(CodeGenModulePassManager &CGMPM) const;
/// Add pass to prepare the LLVM IR for code generation. This should be done
/// before exception handling preparation passes.
- void addCodeGenPrepare(PassManagerWrapper &PMW) const;
+ CodeGenFunctionPassManager addCodeGenPrepare() const;
/// Add common passes that perform LLVM IR to IR transforms in preparation for
/// instruction selection.
- void addISelPrepare(PassManagerWrapper &PMW) const;
+ void addISelPrepare(CodeGenModulePassManager &CGMPM) const;
/// Methods with trivial inline returns are convenient points in the common
/// codegen pass pipeline where targets may insert passes. Methods with
@@ -466,39 +373,41 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
/// addMachineSSAOptimization - Add standard passes that optimize machine
/// instructions in SSA form.
- void addMachineSSAOptimization(PassManagerWrapper &PMW) const;
+ void
+ addMachineSSAOptimization(CodeGenMachineFunctionPassManager &CGMFPM) const;
/// addFastRegAlloc - Add the minimum set of target-independent passes that
/// are required for fast register allocation.
- Error addFastRegAlloc(PassManagerWrapper &PMW) const;
+ Error addFastRegAlloc(CodeGenMachineFunctionPassManager &CGMFPM) const;
/// addOptimizedRegAlloc - Add passes related to register allocation.
/// CodeGenTargetMachineImpl provides standard regalloc passes for most
/// targets.
- Error addOptimizedRegAlloc(PassManagerWrapper &PMW) const;
+ Error addOptimizedRegAlloc(CodeGenMachineFunctionPassManager &CGMFPM) const;
/// Add passes that optimize machine instructions after register allocation.
- void addMachineLateOptimization(PassManagerWrapper &PMW) const;
+ void
+ addMachineLateOptimization(CodeGenMachineFunctionPassManager &CGMFPM) const;
/// addGCPasses - Add late codegen passes that analyze code for garbage
/// collection. This should return true if GC info should be printed after
/// these passes.
- void addGCPasses(PassManagerWrapper &PMW) const {}
+ void addGCPasses(CodeGenMachineFunctionPassManager &CGMFPM) const {}
/// Add standard basic block placement passes.
- void addBlockPlacement(PassManagerWrapper &PMW) const;
+ void addBlockPlacement(CodeGenMachineFunctionPassManager &CGMFPM) const;
- void addPostBBSections(PassManagerWrapper &PMW) const {}
+ void addPostBBSections(CodeGenMachineFunctionPassManager &CGMFPM) const {}
- void addAsmPrinterBegin(PassManagerWrapper &PMW) const {
+ void addAsmPrinterBegin(CodeGenModulePassManager &CGMPM) const {
llvm_unreachable("addAsmPrinterBegin is not overriden");
}
- void addAsmPrinter(PassManagerWrapper &PMW) const {
+ void addAsmPrinter(CodeGenMachineFunctionPassManager &CGMFPM) const {
llvm_unreachable("addAsmPrinter is not overridden");
}
- void addAsmPrinterEnd(PassManagerWrapper &PMW) const {
+ void addAsmPrinterEnd(CodeGenModulePassManager &CGMPM) const {
llvm_unreachable("addAsmPrinterEnd is not overriden");
}
@@ -507,34 +416,38 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
/// createTargetRegisterAllocator - Create the register allocator pass for
/// this target at the current optimization level.
- void addTargetRegisterAllocator(PassManagerWrapper &PMW,
+ void addTargetRegisterAllocator(CodeGenMachineFunctionPassManager &CGMFPM,
bool Optimized) const;
/// addMachinePasses helper to create the target-selected or overriden
/// regalloc pass.
- void addRegAllocPass(PassManagerWrapper &PMW, bool Optimized) const;
+ void addRegAllocPass(CodeGenMachineFunctionPassManager &CGMFPM,
+ bool Optimized) const;
/// Add core register allocator passes which do the actual register assignment
/// and rewriting.
- Error addRegAssignmentFast(PassManagerWrapper &PMW) const;
- Error addRegAssignmentOptimized(PassManagerWrapper &PMW) const;
+ Error addRegAssignmentFast(CodeGenMachineFunctionPassManager &CGMFPM) const;
+ Error
+ addRegAssignmentOptimized(CodeGenMachineFunctionPassManager &CGMFPM) const;
/// Allow the target to disable a specific pass by default.
/// Backend can declare unwanted passes in constructor.
template <typename... PassTs> void disablePass() {
- BeforeCallbacks.emplace_back(
- [](StringRef Name) { return ((Name != PassTs::name()) && ...); });
+ (DisabledPasses.insert(PassTs::name()), ...);
}
/// Insert InsertedPass pass after TargetPass pass.
/// Only machine function passes are supported.
template <typename TargetPassT, typename InsertedPassT>
void insertPass(InsertedPassT &&Pass) const {
- AfterCallbacks.emplace_back(
- [&](StringRef Name, MachineFunctionPassManager &MFPM) mutable {
- if (Name == TargetPassT::name() &&
- runBeforeAdding(InsertedPassT::name())) {
- MFPM.addPass(std::forward<InsertedPassT>(Pass));
+ InsertPassCallbacks.emplace_back(
+ [&, Visited = false](
+ StringRef Name, CodeGenMachineFunctionPassManager &CGMFPM) mutable {
+ if (Visited)
+ return;
+ if (Name == TargetPassT::name()) {
+ Visited = true;
+ CGMFPM.addPass(std::forward<InsertedPassT>(Pass));
}
});
}
@@ -545,27 +458,19 @@ template <typename DerivedT, typename TargetMachineT> class CodeGenPassBuilder {
return static_cast<const DerivedT &>(*this);
}
- bool runBeforeAdding(StringRef Name) const {
- bool ShouldAdd = true;
- for (auto &C : BeforeCallbacks)
- ShouldAdd &= C(Name);
- return ShouldAdd;
- }
-
void setStartStopPasses(const TargetPassConfig::StartStopInfo &Info) const;
Error verifyStartStop(const TargetPassConfig::StartStopInfo &Info) const;
- mutable SmallVector<llvm::unique_function<bool(StringRef)>, 4>
- BeforeCallbacks;
- mutable SmallVector<
- llvm::unique_function<void(StringRef, MachineFunctionPassManager &)>, 4>
- AfterCallbacks;
+ StringSet<> DisabledPasses;
+ mutable SmallVector<llvm::unique_function<void(
+ StringRef, CodeGenMachineFunctionPassManager &)>,
+ 4>
+ InsertPassCallbacks;
/// Helper variable for `-start-before/-start-after/-stop-before/-stop-after`
mutable bool Started = true;
mutable bool Stopped = true;
- mutable bool AddInCGSCCOrder = false;
};
template <typename Derived, typename TargetMachineT>
@@ -580,21 +485,14 @@ Error CodeGenPassBuilder<Derived, TargetMachineT>::buildPipeline(
bool PrintAsm = TargetPassConfig::willCompleteCodeGenPipeline();
bool PrintMIR = !PrintAsm && FileType != CodeGenFileType::Null;
- PassManagerWrapper PMW(MPM);
-
- addModulePass(RequireAnalysisPass<MachineModuleAnalysis, Module>(), PMW,
- /*Force=*/true);
- addModulePass(RequireAnalysisPass<ProfileSummaryAnalysis, Module>(), PMW,
- /*Force=*/true);
- addModulePass(RequireAnalysisPass<CollectorMetadataAnalysis, Module>(), PMW,
- /*Force=*/true);
- addModulePass(RequireAnalysisPass<RuntimeLibraryAnalysis, Module>(), PMW,
- /*Force=*/true);
- addModulePass(RequireAnalysisPass<LibcallLoweringModuleAnalysis, Module>(),
- PMW,
- /*Force=*/true);
- addISelPasses(PMW);
- flushFPMsToMPM(PMW);
+ CodeGenModulePassManager CGMPM;
+ CGMPM.addPass(RequireAnalysisPass<MachineModuleAnalysis, Module>());
+ CGMPM.addPass(RequireAnalysisPass<ProfileSummaryAnalysis, Module>());
+ CGMPM.addPass(RequireAnalysisPass<Collecto...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/210473
More information about the llvm-commits
mailing list