Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NewPM][CodeGen] Add callback style codegen pass builder #108690

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

paperchalice
Copy link
Contributor

@paperchalice paperchalice commented Sep 14, 2024

In contrast to #89708, this pull request demonstrates a callback style codegen pipeline builder. Suggestions are welcome!

It supports -start/stop-after/before by adding eraseIf in pass manager and pass adaptor. To extend pass pipeline, targets can use following extension points:

  • CodeGenIREarlyEPCallbacks
  • GCLoweringEPCallbacks
  • ISelPrepareEPCallbacks
  • MachineSSAOptimizationEarlyEPCallbacks
  • MachineSSAOptimizationLastEPCallbacks
  • PreRegAllocEPCallbacks
  • PreRegBankSelectEPCallbacks
  • PreGlobalInstructionSelectEPCallbacks
  • PostGlobalInstructionSelectEPCallbacks
  • ILPOptsEPCallbacks
  • MachineLateOptimizationEPCallbacks
  • MIEmitEPCallbacks
  • PreEmitEPCallbacks
  • PostRegAllocEPCallbacks
  • PreSched2EPCallbacks
  • PostBBSectionsEPCallbacks

User can control register allocator by --regalloc-npm=regalloc-name<filter=filter1>,regalloc-name<filter=filter2>...

Most of them are from TargetPassConfig, and this should be sufficient for most targets, except AArch64 and DirectX, because AArch64 tries to insert module pass in machine function pass pipeline, DirectX builds its own codegen pass pipeline.

Register allocator part should be highly customizable, there are some ad-hoc examples in AMDGPU and NVPTX, but I couldn't find a good way to handle them, this implementation just provides addDefaultRegAllocFastPasses and addDefaultRegAllocOptimizedPasses as building blocks.

@llvmbot
Copy link
Collaborator

llvmbot commented Sep 16, 2024

@llvm/pr-subscribers-backend-amdgpu
@llvm/pr-subscribers-llvm-ir
@llvm/pr-subscribers-llvm-transforms

@llvm/pr-subscribers-backend-x86

Author: None (paperchalice)

Changes

In contrast to #89708, this pull request demonstrates a callback style codegen pipeline builder. Suggestions are welcome!

It supports -start/stop-after/before by adding eraseIf in pass manager and pass adaptor. To extend pass pipeline, targets can use following extension points:

  • CodeGenIREarlyEPCallbacks
  • GCLoweringEPCallbacks
  • ISelPrepareEPCallbacks
  • MachineSSAOptimizationEarlyEPCallbacks
  • MachineSSAOptimizationLastEPCallbacks
  • PreRegAllocEPCallbacks
  • PreRegBankSelectEPCallbacks
  • PreGlobalInstructionSelectEPCallbacks
  • PostGlobalInstructionSelectEPCallbacks
  • ILPOptsEPCallbacks
  • MachineLateOptimizationEPCallbacks
  • MIEmitEPCallbacks
  • PreEmitEPCallbacks
  • PostRegAllocEPCallbacks
  • PreSched2EPCallbacks
  • PostBBSectionsEPCallbacks

User can control register allocator by --regalloc-npm=regalloc-name&lt;filter=filter1&gt;,regalloc-name&lt;filter=filter2&gt;...

Most of them are from TargetPassConfig, and this should be sufficient for most targets, except AArch64 and DirectX, because AArch64 tries to insert module pass in machine function pass pipeline, DirectX builds its own codegen pass pipeline.

Register allocator part should be highly customizable, there are some ad-hoc examples in AMDGPU and NVPTX, but I couldn't find a good way to handle them, this implementation just provides addDefaultRegAllocFastPasses and addDefaultRegAllocOptimizedPasses as building blocks.


Patch is 71.88 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/108690.diff

23 Files Affected:

  • (modified) llvm/include/llvm/Analysis/CGSCCPassManager.h (+6)
  • (modified) llvm/include/llvm/CodeGen/MachinePassManager.h (+4)
  • (modified) llvm/include/llvm/CodeGen/TargetPassConfig.h (+1-2)
  • (modified) llvm/include/llvm/IR/PassManager.h (+19)
  • (modified) llvm/include/llvm/IR/PassManagerInternal.h (+35)
  • (modified) llvm/include/llvm/Passes/CodeGenPassBuilder.h (+1-1)
  • (modified) llvm/include/llvm/Passes/MachinePassRegistry.def (+5)
  • (modified) llvm/include/llvm/Passes/PassBuilder.h (+236)
  • (modified) llvm/include/llvm/Target/CGPassBuilderOption.h (+3)
  • (modified) llvm/include/llvm/Transforms/Scalar/LoopPassManager.h (+8)
  • (modified) llvm/lib/Analysis/CGSCCPassManager.cpp (+23)
  • (modified) llvm/lib/CodeGen/MachinePassManager.cpp (+12)
  • (modified) llvm/lib/CodeGen/TargetPassConfig.cpp (+5-4)
  • (modified) llvm/lib/IR/PassManager.cpp (+11)
  • (modified) llvm/lib/Passes/CMakeLists.txt (+1)
  • (modified) llvm/lib/Passes/PassBuilder.cpp (+17-2)
  • (added) llvm/lib/Passes/PassBuilderCodeGen.cpp (+950)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp (+29)
  • (modified) llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp (+4)
  • (modified) llvm/lib/Transforms/Scalar/LoopPassManager.cpp (+49)
  • (added) llvm/test/CodeGen/AMDGPU/regalloc-select.ll (+9)
  • (modified) llvm/test/tools/llc/new-pm/start-stop.ll (+2-2)
  • (modified) llvm/tools/llc/NewPMDriver.cpp (+9-12)
diff --git a/llvm/include/llvm/Analysis/CGSCCPassManager.h b/llvm/include/llvm/Analysis/CGSCCPassManager.h
index 15b7f226fd8283..4a49bfb283b6a2 100644
--- a/llvm/include/llvm/Analysis/CGSCCPassManager.h
+++ b/llvm/include/llvm/Analysis/CGSCCPassManager.h
@@ -346,6 +346,10 @@ class ModuleToPostOrderCGSCCPassAdaptor
 
   static bool isRequired() { return true; }
 
+  bool isEmpty() const { return Pass == nullptr; }
+
+  void eraseIf(function_ref<bool(StringRef)> Pred);
+
 private:
   std::unique_ptr<PassConceptT> Pass;
 };
@@ -488,6 +492,8 @@ class CGSCCToFunctionPassAdaptor
 
   static bool isRequired() { return true; }
 
+  void eraseIf(function_ref<bool(StringRef)> Pred);
+
 private:
   std::unique_ptr<PassConceptT> Pass;
   bool EagerlyInvalidate;
diff --git a/llvm/include/llvm/CodeGen/MachinePassManager.h b/llvm/include/llvm/CodeGen/MachinePassManager.h
index 253fabdac0019d..13a825d32fa310 100644
--- a/llvm/include/llvm/CodeGen/MachinePassManager.h
+++ b/llvm/include/llvm/CodeGen/MachinePassManager.h
@@ -207,6 +207,10 @@ class FunctionToMachineFunctionPassAdaptor
 
   static bool isRequired() { return true; }
 
+  bool isEmpty() const { return Pass == nullptr; }
+
+  void eraseIf(function_ref<bool(StringRef)> Pred);
+
 private:
   std::unique_ptr<PassConceptT> Pass;
 };
diff --git a/llvm/include/llvm/CodeGen/TargetPassConfig.h b/llvm/include/llvm/CodeGen/TargetPassConfig.h
index 2f5951e3ec3bce..ad27a5471d1a7a 100644
--- a/llvm/include/llvm/CodeGen/TargetPassConfig.h
+++ b/llvm/include/llvm/CodeGen/TargetPassConfig.h
@@ -190,8 +190,7 @@ class TargetPassConfig : public ImmutablePass {
 
   /// Returns pass name in `-stop-before` or `-stop-after`
   /// NOTE: New pass manager migration only
-  static Expected<StartStopInfo>
-  getStartStopInfo(PassInstrumentationCallbacks &PIC);
+  static Expected<StartStopInfo> getStartStopInfo();
 
   void setDisableVerify(bool Disable) { setOpt(DisableVerify, Disable); }
 
diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h
index d269221fac0701..4f28b4aceb3e66 100644
--- a/llvm/include/llvm/IR/PassManager.h
+++ b/llvm/include/llvm/IR/PassManager.h
@@ -218,6 +218,21 @@ class PassManager : public PassInfoMixin<
 
   static bool isRequired() { return true; }
 
+  /// Erase all passes that satisfy the predicate \p Pred.
+  /// For internal use only!
+  void eraseIf(function_ref<bool(StringRef)> Pred) {
+    for (auto I = Passes.begin(); I != Passes.end();) {
+      (*I)->eraseIf(Pred);
+      bool IsSpecial = (*I)->name().ends_with("PassAdaptor") ||
+                       (*I)->name().contains("PassManager");
+      bool PredResult = Pred((*I)->name());
+      if ((!IsSpecial && PredResult) || (IsSpecial && (*I)->isEmpty()))
+        I = Passes.erase(I);
+      else
+        ++I;
+    }
+  }
+
 protected:
   using PassConceptT =
       detail::PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...>;
@@ -836,6 +851,10 @@ class ModuleToFunctionPassAdaptor
 
   static bool isRequired() { return true; }
 
+  bool isEmpty() const { return Pass == nullptr; }
+
+  void eraseIf(function_ref<bool(StringRef)> Pred);
+
 private:
   std::unique_ptr<PassConceptT> Pass;
   bool EagerlyInvalidate;
diff --git a/llvm/include/llvm/IR/PassManagerInternal.h b/llvm/include/llvm/IR/PassManagerInternal.h
index 4ada6ee5dd6831..3a75c9c4e97faf 100644
--- a/llvm/include/llvm/IR/PassManagerInternal.h
+++ b/llvm/include/llvm/IR/PassManagerInternal.h
@@ -59,6 +59,13 @@ struct PassConcept {
   /// To opt-in, pass should implement `static bool isRequired()`. It's no-op
   /// to have `isRequired` always return false since that is the default.
   virtual bool isRequired() const = 0;
+
+  /// Polymorphic method to refurbish pass pipeline.
+  virtual void eraseIf(function_ref<bool(StringRef)> Pred) = 0;
+
+  /// There may be some empty PassManager after erasing,
+  /// use it to remove them.
+  virtual bool isEmpty() const = 0;
 };
 
 /// A template wrapper used to implement the polymorphic API.
@@ -114,6 +121,34 @@ struct PassModel : PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> {
 
   bool isRequired() const override { return passIsRequiredImpl<PassT>(); }
 
+  template <typename T>
+  using has_erase_if_t = decltype(std::declval<T &>().eraseIf(
+      std::declval<function_ref<bool(StringRef)>>()));
+
+  template <typename T>
+  std::enable_if_t<is_detected<has_erase_if_t, T>::value>
+  eraseIfImpl(function_ref<bool(StringRef)> Pred) {
+    Pass.eraseIf(Pred);
+  }
+
+  template <typename T>
+  std::enable_if_t<!is_detected<has_erase_if_t, T>::value>
+  eraseIfImpl(function_ref<bool(StringRef)>) {}
+
+  void eraseIf(function_ref<bool(StringRef)> Pred) override {
+    eraseIfImpl<PassT>(Pred);
+  }
+
+  template <typename T>
+  using has_is_empty_t = decltype(std::declval<T &>().isEmpty());
+
+  bool isEmpty() const override {
+    if constexpr (is_detected<has_is_empty_t, PassT>::value)
+      return Pass.isEmpty();
+    else
+      return false;
+  }
+
   PassT Pass;
 };
 
diff --git a/llvm/include/llvm/Passes/CodeGenPassBuilder.h b/llvm/include/llvm/Passes/CodeGenPassBuilder.h
index a99fed86d168d1..fc1a15b320b5c4 100644
--- a/llvm/include/llvm/Passes/CodeGenPassBuilder.h
+++ b/llvm/include/llvm/Passes/CodeGenPassBuilder.h
@@ -523,7 +523,7 @@ template <typename Derived, typename TargetMachineT>
 Error CodeGenPassBuilder<Derived, TargetMachineT>::buildPipeline(
     ModulePassManager &MPM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
     CodeGenFileType FileType) const {
-  auto StartStopInfo = TargetPassConfig::getStartStopInfo(*PIC);
+  auto StartStopInfo = TargetPassConfig::getStartStopInfo();
   if (!StartStopInfo)
     return StartStopInfo.takeError();
   setStartStopPasses(*StartStopInfo);
diff --git a/llvm/include/llvm/Passes/MachinePassRegistry.def b/llvm/include/llvm/Passes/MachinePassRegistry.def
index 4047fd0478579f..fd6aa34e498516 100644
--- a/llvm/include/llvm/Passes/MachinePassRegistry.def
+++ b/llvm/include/llvm/Passes/MachinePassRegistry.def
@@ -191,6 +191,7 @@ DUMMY_MACHINE_MODULE_PASS("mir-strip-debug", StripDebugMachineModulePass)
 #ifndef DUMMY_MACHINE_FUNCTION_PASS
 #define DUMMY_MACHINE_FUNCTION_PASS(NAME, PASS_NAME)
 #endif
+DUMMY_MACHINE_FUNCTION_PASS("bb-path-cloning", BasicBlockPathCloningPass)
 DUMMY_MACHINE_FUNCTION_PASS("bbsections-prepare", BasicBlockSectionsPass)
 DUMMY_MACHINE_FUNCTION_PASS("bbsections-profile-reader", BasicBlockSectionsProfileReaderPass)
 DUMMY_MACHINE_FUNCTION_PASS("block-placement", MachineBlockPlacementPass)
@@ -210,6 +211,8 @@ DUMMY_MACHINE_FUNCTION_PASS("fixup-statepoint-caller-saved", FixupStatepointCall
 DUMMY_MACHINE_FUNCTION_PASS("fs-profile-loader", MIRProfileLoaderNewPass)
 DUMMY_MACHINE_FUNCTION_PASS("funclet-layout", FuncletLayoutPass)
 DUMMY_MACHINE_FUNCTION_PASS("gc-empty-basic-blocks", GCEmptyBasicBlocksPass)
+DUMMY_MACHINE_FUNCTION_PASS("gc-machine-code-insersion",
+                            GCMachineCodeInsertionPass)
 DUMMY_MACHINE_FUNCTION_PASS("implicit-null-checks", ImplicitNullChecksPass)
 DUMMY_MACHINE_FUNCTION_PASS("init-undef-pass", InitUndefPass)
 DUMMY_MACHINE_FUNCTION_PASS("instruction-select", InstructionSelectPass)
@@ -261,6 +264,8 @@ DUMMY_MACHINE_FUNCTION_PASS("stack-slot-coloring", StackSlotColoringPass)
 DUMMY_MACHINE_FUNCTION_PASS("stackmap-liveness", StackMapLivenessPass)
 DUMMY_MACHINE_FUNCTION_PASS("tailduplication", TailDuplicatePass)
 DUMMY_MACHINE_FUNCTION_PASS("unpack-mi-bundles", UnpackMachineBundlesPass)
+DUMMY_MACHINE_FUNCTION_PASS("unreachable-mbb-elimination",
+                            UnreachableMachineBlockElimPass)
 DUMMY_MACHINE_FUNCTION_PASS("virtregrewriter", VirtRegRewriterPass)
 DUMMY_MACHINE_FUNCTION_PASS("xray-instrumentation", XRayInstrumentationPass)
 #undef DUMMY_MACHINE_FUNCTION_PASS
diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h
index e1d78a8685aed2..c2068610c58a66 100644
--- a/llvm/include/llvm/Passes/PassBuilder.h
+++ b/llvm/include/llvm/Passes/PassBuilder.h
@@ -15,14 +15,17 @@
 #ifndef LLVM_PASSES_PASSBUILDER_H
 #define LLVM_PASSES_PASSBUILDER_H
 
+#include "llvm/ADT/StringSet.h"
 #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/CodeGen.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/PGOOptions.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/CGPassBuilderOption.h"
 #include "llvm/Transforms/IPO/Inliner.h"
 #include "llvm/Transforms/IPO/ModuleInliner.h"
 #include "llvm/Transforms/Instrumentation.h"
@@ -35,6 +38,7 @@ class StringRef;
 class AAManager;
 class TargetMachine;
 class ModuleSummaryIndex;
+class MCContext;
 template <typename T> class IntrusiveRefCntPtr;
 namespace vfs {
 class FileSystem;
@@ -107,6 +111,7 @@ class PassBuilder {
   TargetMachine *TM;
   PipelineTuningOptions PTO;
   std::optional<PGOOptions> PGOOpt;
+  CGPassBuilderOption CGPBO;
   PassInstrumentationCallbacks *PIC;
 
 public:
@@ -307,6 +312,24 @@ class PassBuilder {
   /// TargetMachine::registerDefaultAliasAnalyses().
   AAManager buildDefaultAAPipeline();
 
+  /// Build CodeGen pass pipeline.
+  ///
+  /// {{@
+  Expected<ModulePassManager>
+  buildDefaultCodeGenPipeline(raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
+                              CodeGenFileType FileType, MCContext &Ctx);
+  Error buildDefaultCodeGenPipeline(ModulePassManager &MPM,
+                                    raw_pwrite_stream &Out,
+                                    raw_pwrite_stream *DwoOut,
+                                    CodeGenFileType FileType, MCContext &Ctx);
+  Error addRegAllocPass(MachineFunctionPassManager &MFPM,
+                        StringRef Filter = "all");
+  // TODO: Add method to build MC emission pipeline.
+  template <typename... PassTs> void disablePass() {
+    (DisabledPasses.insert(PassTs::name()), ...);
+  }
+  /// @}}
+
   /// Parse a textual pass pipeline description into a \c
   /// ModulePassManager.
   ///
@@ -519,6 +542,133 @@ class PassBuilder {
     FullLinkTimeOptimizationLastEPCallbacks.push_back(C);
   }
 
+  /// Register target specific callbacks to extend codegen pipeline.
+  /// {{@
+
+  /// If target want its own pipeline, use this callback.
+  void setCustomCodeGenPipelineBuilderCallback(
+      const std::function<Error(ModulePassManager &, raw_pwrite_stream &,
+                                raw_pwrite_stream *, CodeGenFileType,
+                                MCContext &)>
+          C) {
+    CustomCodeGenPipelineBuilderCallback = C;
+  }
+
+  void registerCodeGenIREarlyEPCallback(
+      const std::function<void(ModulePassManager &)> C) {
+    CodeGenIREarlyEPCallbacks.push_back(C);
+  }
+
+  void registerGCLoweringEPCallback(
+      const std::function<void(FunctionPassManager &)> C) {
+    GCLoweringEPCallbacks.push_back(C);
+  }
+
+  void registerISelPrepareEPCallback(
+      const std::function<void(ModulePassManager &)> &C) {
+    ISelPrepareEPCallbacks.push_back(C);
+  }
+
+  void registerMachineSSAOptimizationEarlyEPCallback(
+      const std::function<void(MachineFunctionPassManager &)> &C) {
+    MachineSSAOptimizationEarlyEPCallbacks.push_back(C);
+  }
+
+  void registerILPOptsEPCallback(
+      const std::function<void(MachineFunctionPassManager &)> &C) {
+    ILPOptsEPCallbacks.push_back(C);
+  }
+
+  void registerMachineSSAOptimizationLastEPCallback(
+      const std::function<void(MachineFunctionPassManager &)> &C) {
+    MachineSSAOptimizationLastEPCallbacks.push_back(C);
+  }
+
+  void registerPreRegAllocEPCallback(
+      const std::function<void(MachineFunctionPassManager &)> &C) {
+    PreRegAllocEPCallbacks.push_back(C);
+  }
+
+  void registerPostRegAllocEPCallback(
+      const std::function<void(MachineFunctionPassManager &)> &C) {
+    PostRegAllocEPCallbacks.push_back(C);
+  }
+
+  void registerPreRegBankSelectEPCallback(
+      const std::function<void(MachineFunctionPassManager &)> &C) {
+    PreRegBankSelectEPCallbacks.push_back(C);
+  }
+
+  void registerPreGlobalInstructionSelectEPCallback(
+      const std::function<void(MachineFunctionPassManager &)> &C) {
+    PreGlobalInstructionSelectEPCallbacks.push_back(C);
+  }
+
+  void registerPostGlobalInstructionSelectEPCallback(
+      const std::function<void(MachineFunctionPassManager &)> &C) {
+    PostGlobalInstructionSelectEPCallbacks.push_back(C);
+  }
+
+  void registerMachineLateOptimizationEPCallback(
+      const std::function<void(MachineFunctionPassManager &)> &C) {
+    MachineLateOptimizationEPCallbacks.push_back(C);
+  }
+
+  void registerPreSched2EPCallback(
+      const std::function<void(MachineFunctionPassManager &)> &C) {
+    PreSched2EPCallbacks.push_back(C);
+  }
+
+  void registerPostRewriteEPCallback(
+      const std::function<void(MachineFunctionPassManager &)> &C) {
+    PostRewriteEPCallbacks.push_back(C);
+  }
+
+  void registerPreEmitEPCallback(
+      const std::function<void(MachineFunctionPassManager &)> &C) {
+    PreEmitEPCallbacks.push_back(C);
+  }
+
+  void registerPostBBSectionsEPCallback(
+      const std::function<void(MachineFunctionPassManager &)> &C) {
+    PostBBSectionsEPCallbacks.push_back(C);
+  }
+
+  void registerMIEmitEPCallback(
+      const std::function<void(MachineFunctionPassManager &)> &C) {
+    MIEmitEPCallbacks.push_back(C);
+  }
+
+  void setAddInstSelectorCallback(
+      const std::function<void(MachineFunctionPassManager &)> &C) {
+    AddInstSelectorCallback = C;
+  }
+
+  void setCodeGenPreparePassesCallback(
+      const std::function<void(ModulePassManager &)> C) {
+    AddCodeGenPreparePassesCallback = C;
+  }
+
+  void setRegAllocFastCallback(
+      const std::function<Error(MachineFunctionPassManager &)> &C) {
+    AddRegAllocFastCallback = C;
+  }
+
+  void setRegAllocOptimizedCallback(
+      const std::function<Error(MachineFunctionPassManager &)> &C) {
+    AddRegAllocOptimizedCallback = C;
+  }
+  ///@}}
+
+  /// Building block callbacks for codegen pipeline.
+  void addDefaultCodeGenPreparePasses(ModulePassManager &MPM);
+  Error addDefaultRegAllocFastPasses(MachineFunctionPassManager &MFPM);
+  Error addDefaultRegAllocOptimizedPasses(MachineFunctionPassManager &MFPM);
+
+  // New pass manager migration methods, don't use them
+  // outside llvm!
+  CGPassBuilderOption &getCGPBO() { return CGPBO; }
+
   /// Register a callback for parsing an AliasAnalysis Name to populate
   /// the given AAManager \p AA
   void registerParseAACallback(
@@ -640,6 +790,28 @@ class PassBuilder {
   void invokePipelineEarlySimplificationEPCallbacks(ModulePassManager &MPM,
                                                     OptimizationLevel Level);
 
+  void invokeCodeGenIREarlyEPCallbacks(ModulePassManager &MPM);
+  void invokeGCLoweringEPCallbacks(FunctionPassManager &FPM);
+  void invokeISelPrepareEPCallbacks(ModulePassManager &MPM);
+  void invokeMachineSSAOptimizationEarlyEPCallbacks(
+      MachineFunctionPassManager &MFPM);
+  void
+  invokeMachineSSAOptimizationLastEPCallbacks(MachineFunctionPassManager &MFPM);
+  void invokePreRegAllocEPCallbacks(MachineFunctionPassManager &MFPM);
+  void invokePostRegAllocEPCallbacks(MachineFunctionPassManager &MFPM);
+  void invokePreRegBankSelectEPCallbacks(MachineFunctionPassManager &MFPM);
+  void
+  invokePreGlobalInstructionSelectEPCallbacks(MachineFunctionPassManager &MFPM);
+  void invokePostGlobalInstructionSelectEPCallbacks(
+      MachineFunctionPassManager &MFPM);
+  void invokeILPOptsEPCallbacks(MachineFunctionPassManager &MFPM);
+  void
+  invokeMachineLateOptimizationEPCallbacks(MachineFunctionPassManager &MFPM);
+  void invokePreEmitEPCallbacks(MachineFunctionPassManager &MFPM);
+  void invokePostBBSectionsEPCallbacks(MachineFunctionPassManager &MFPM);
+  void invokeMIEmitEPCallbacks(MachineFunctionPassManager &MFPM);
+  void invokePreSched2EPCallbacks(MachineFunctionPassManager &MFPM);
+
   static bool checkParametrizedPassName(StringRef Name, StringRef PassName) {
     if (!Name.consume_front(PassName))
       return false;
@@ -704,6 +876,21 @@ class PassBuilder {
   void addVectorPasses(OptimizationLevel Level, FunctionPassManager &FPM,
                        bool IsFullLTO);
 
+  Error addExceptionHandlingPasses(FunctionPassManager &FPM);
+
+  Error addInstructionSelectorPasses(MachineFunctionPassManager &MFPM);
+
+  void addMachineSSAOptimizationPasses(MachineFunctionPassManager &MFPM);
+
+  Error addMachinePasses(ModulePassManager &MPM, FunctionPassManager &FPM,
+                         MachineFunctionPassManager &MFPM);
+
+  Error addRegisterAllocatorPasses(MachineFunctionPassManager &MFPM);
+
+  Error parseRegAllocOption(StringRef Text);
+
+  bool isOptimizedRegAlloc() const;
+
   static std::optional<std::vector<PipelineElement>>
   parsePipelineText(StringRef Text);
 
@@ -766,6 +953,55 @@ class PassBuilder {
   SmallVector<std::function<void(ModulePassManager &, OptimizationLevel)>, 2>
       PipelineEarlySimplificationEPCallbacks;
 
+  // CodeGen extension point callbacks
+  std::function<Error(ModulePassManager &, raw_pwrite_stream &,
+                      raw_pwrite_stream *, CodeGenFileType, MCContext &)>
+      CustomCodeGenPipelineBuilderCallback;
+
+  SmallVector<std::function<void(ModulePassManager &)>, 2>
+      CodeGenIREarlyEPCallbacks;
+  SmallVector<std::function<void(FunctionPassManager &)>, 2>
+      GCLoweringEPCallbacks;
+  SmallVector<std::function<void(ModulePassManager &)>, 2>
+      ISelPrepareEPCallbacks;
+  SmallVector<std::function<void(MachineFunctionPassManager &)>, 2>
+      MachineSSAOptimizationEarlyEPCallbacks;
+  SmallVector<std::function<void(MachineFunctionPassManager &)>, 2>
+      MachineSSAOptimizationLastEPCallbacks;
+  SmallVector<std::function<void(MachineFunctionPassManager &)>, 2>
+      PreRegAllocEPCallbacks;
+  SmallVector<std::function<void(MachineFunctionPassManager &)>, 2>
+      PostRegAllocEPCallbacks;
+  SmallVector<std::function<void(MachineFunctionPassManager &)>, 2>
+      PreRegBankSelectEPCallbacks;
+  SmallVector<std::function<void(MachineFunctionPassManager &)>, 2>
+      PreGlobalInstructionSelectEPCallbacks;
+  SmallVector<std::function<void(MachineFunctionPassManager &)>, 2>
+      PostGlobalInstructionSelectEPCallbacks;
+  SmallVector<std::function<void(MachineFunctionPassManager &)>, 2>
+      ILPOptsEPCallbacks;
+  SmallVector<std::function<void(MachineFunctionPassManager &)>, 2>
+      MachineLateOptimizationEPCallbacks;
+  SmallVector<std::function<void(MachineFunctionPassManager &)>, 2>
+      PreSched2EPCallbacks;
+  SmallVector<std::function<void(MachineFunctionPassManager &)>, 2>
+      PostRewriteEPCallbacks;
+  SmallVector<std::function<void(MachineFunctionPassManager &)>, 2>
+      PreEmitEPCallbacks;
+  SmallVector<std::function<void(MachineFunctionPassManager &)>, 2>
+      PostBBSectionsEPCallbacks;
+  SmallVector<std::function<void(MachineFunctionPassManager &)>, 2>
+      MIEmitEPCallbacks;
+
+  std::function<void(ModulePassManager &)> AddCodeGenPreparePassesCallback;
+  std::function<void(MachineFunctionPassManager &)> AddInstSelectorCallback;
+  std::function<Error(MachineFunctionPassManager &)> AddRegAllocFastCallback;
+  std::function<Error(MachineFunctionPassManager &)>
+      AddRegAllocOptimizedCallback;
+  StringSet<> DisabledPasses;
+  StringMap<MachineFunctionPassManager> RegAllocPasses;
+  // TODO: Add methods in LLVMTargetMachine so we can get rid of it.
+
   SmallVector<std::function<void(ModuleAnalysisManager &)>, 2>
       ModuleAnalysisRegistrationCallbacks;
   SmallVector<std::function<bool(StringRef, ModulePassManager &,
diff --git a/llvm/include/llvm/Target/CGPassBuilderOption.h b/llvm/include/llvm/Target/CGPassBuilderOption.h
index 8ab6d63a00056a..51eeaec51b3ff9 100644
--- a/llvm/include/llvm/Target/CGPassBuilderOption.h
+++ b/llvm/include/llvm/Target/CGPassBuilderOption.h
@@ -41,6 +41,9 @@ struct CGPassBuilderOption {
   bool PrintLSR = false;
   bool DisableMergeICmps = false;
   bool DisablePartialLibcallInlining = false;
+  bool DisableReplaceWithVecLib = false;
+  bool DisableLayoutFSProfileLoader = false;
+  bool DisablePrologEpilogInserterPass = false;
   bool DisableConstantHoisting = false;
   bool DisableSelectOptimize = true;
   bool DisableAtExitBasedGlobalDtorLowering = false;
diff --git a/llvm/include/llvm/Transforms/Scalar/LoopPas...
[truncated]


using namespace llvm;

void PassBuilder::invokeCodeGenIREarlyEPCallbacks(ModulePassManager &MPM) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a template method to avoid all these EPCallbacks() functions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Template is better but I don't know why the IR pipeline extension points use normal method😕.

@cdevadas
Copy link
Collaborator

@paperchalice are you planning to port Greedy allocator?
If you haven't started, let us know, we're planning for it.

@paperchalice
Copy link
Contributor Author

@paperchalice are you planning to port Greedy allocator? If you haven't started, let us know, we're planning for it.

Currently my plan is to ensure that minimum codegen pipeline (incomplete O0 pipeline) can work and refactoring the pass builder (this pr), so I haven't touched greedy allocator part. Thanks for planning to port greedy allocator part!

@paperchalice
Copy link
Contributor Author

Ping @aeubanks @arsenm

bool isEmpty() const override {
if constexpr (is_detected<has_is_empty_t, PassT>::value)
return Pass.isEmpty();
else
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No else after return

Comment on lines +149 to +157
StringRef PassName = Pass->name();
if (PassName.contains("PassManager") || PassName.ends_with("PassAdaptor")) {
Pass->eraseIf(Pred);
if (Pass->isEmpty())
Pass.reset();
} else if (Pred(PassName)) {
Pass.reset();
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why this is necessary, it feels clumsy

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It uses eraseIf to support --start/stop-before/after, this may introduce some empty pass managers or adaptors, the code here ensures we can remove empty adaptors in eraseIf.

@paperchalice
Copy link
Contributor Author

Ping @aeubanks

/// For internal use only!
void eraseIf(function_ref<bool(StringRef)> Pred) {
for (auto I = Passes.begin(); I != Passes.end();) {
(*I)->eraseIf(Pred);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable instead of repeating (*I) so many times

@aeubanks
Copy link
Contributor

aeubanks commented Oct 9, 2024

sorry for the very slow review, will take a closer look soon

at a first glance, I'd really like to avoid eraseIf and either just don't add the passes in the first place or have the pass manager skip passes before/after ones we specify. and we shouldn't need it for the LLVM IR pass managers? LLVM IR passes can always be run individually so we shouldn't need to support start/stop-before/after on those.

still looking at the callbacks portion but in general I do think that is the direction to go

if (!CGPBO.DisableVerify)
FPM.addPass(VerifierPass());

if (PrintMIR) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If possible, I'd move start/stop part to llc and place here an extension point. Currently these options are coupled with TargetPassConfig.

@paperchalice
Copy link
Contributor Author

Ping? @aeubanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants