[llvm] [CodeGen][Pass] Add `TargetPassBuilder` (PR #137290)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 12 01:37:36 PDT 2026
https://github.com/paperchalice updated https://github.com/llvm/llvm-project/pull/137290
>From ede28db17af4e2e5d9030cab09985a3678360507 Mon Sep 17 00:00:00 2001
From: PaperChalice <liujunchang97 at outlook.com>
Date: Mon, 24 Mar 2025 19:34:01 +0800
Subject: [PATCH 1/2] Add `TargetPassBuilder`.
---
.../llvm/Passes/MachinePassRegistry.def | 1 +
llvm/include/llvm/Passes/PassBuilder.h | 2 +
llvm/include/llvm/Passes/TargetPassBuilder.h | 321 +++++++
.../include/llvm/Target/CGPassBuilderOption.h | 4 +-
llvm/lib/CodeGen/TargetPassConfig.cpp | 3 +
llvm/lib/Passes/CMakeLists.txt | 1 +
llvm/lib/Passes/TargetPassBuilder.cpp | 864 ++++++++++++++++++
llvm/unittests/CodeGen/CMakeLists.txt | 1 +
.../CodeGen/TargetPassBuilderTest.cpp | 175 ++++
9 files changed, 1371 insertions(+), 1 deletion(-)
create mode 100644 llvm/include/llvm/Passes/TargetPassBuilder.h
create mode 100644 llvm/lib/Passes/TargetPassBuilder.cpp
create mode 100644 llvm/unittests/CodeGen/TargetPassBuilderTest.cpp
diff --git a/llvm/include/llvm/Passes/MachinePassRegistry.def b/llvm/include/llvm/Passes/MachinePassRegistry.def
index a297c08fac1b2..1be7ca3bfe480 100644
--- a/llvm/include/llvm/Passes/MachinePassRegistry.def
+++ b/llvm/include/llvm/Passes/MachinePassRegistry.def
@@ -272,6 +272,7 @@ DUMMY_MACHINE_MODULE_PASS("mir-check-debugify", CheckDebugMachineModulePass)
#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("cfguard-longjmp", CFGuardLongjmpPass)
diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h
index 90f7c87ed0eb8..3870fb0bf0086 100644
--- a/llvm/include/llvm/Passes/PassBuilder.h
+++ b/llvm/include/llvm/Passes/PassBuilder.h
@@ -118,6 +118,8 @@ class PassBuilder {
PassInstrumentationCallbacks *PIC;
IntrusiveRefCntPtr<vfs::FileSystem> FS;
+ friend class TargetPassBuilder;
+
public:
/// A struct to capture parsed pass pipeline names.
///
diff --git a/llvm/include/llvm/Passes/TargetPassBuilder.h b/llvm/include/llvm/Passes/TargetPassBuilder.h
new file mode 100644
index 0000000000000..efd25db53208e
--- /dev/null
+++ b/llvm/include/llvm/Passes/TargetPassBuilder.h
@@ -0,0 +1,321 @@
+//===- Parsing, selection, and construction of pass pipelines --*- C++ -*--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// Interfaces for registering analysis passes, producing common pass manager
+/// configurations, and parsing of pass pipelines.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_PASSES_TARGETPASSBUILDER_H
+#define LLVM_PASSES_TARGETPASSBUILDER_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/identity.h"
+#include "llvm/Analysis/CGSCCPassManager.h"
+#include "llvm/CodeGen/MachinePassManager.h"
+#include "llvm/Target/CGPassBuilderOption.h"
+#include "llvm/Transforms/Scalar/LoopPassManager.h"
+#include <list>
+#include <type_traits>
+#include <unordered_set>
+#include <utility>
+#include <variant>
+#include <vector>
+
+namespace llvm {
+
+class PassBuilder;
+class TargetMachine;
+class SelectionDAGISel;
+
+/// @brief Build CodeGen pipeline
+///
+class TargetPassBuilder {
+public:
+ TargetPassBuilder(PassBuilder &PB);
+
+ virtual ~TargetPassBuilder() = default;
+
+ // TODO: Add necessary parameters once AsmPrinter is ported to new pass
+ // manager.
+ llvm::ModulePassManager buildPipeline(raw_pwrite_stream &Out,
+ raw_pwrite_stream *DwoOut,
+ CodeGenFileType FileType,
+ MCContext &Ctx);
+
+private:
+ struct PassWrapper {
+ StringRef Name;
+ std::variant<llvm::ModulePassManager, llvm::FunctionPassManager,
+ llvm::LoopPassManager, llvm::MachineFunctionPassManager>
+ InternalPass;
+ bool InCGSCC = false;
+
+ template <typename PassManagerT>
+ PassWrapper(StringRef Name, PassManagerT &&PM)
+ : Name(Name), InternalPass(std::forward<PassManagerT>(PM)) {}
+
+ template <typename PassT> PassWrapper(PassT &&P) : Name(PassT::name()) {
+ // FIXME: This can't handle the case when `run` is template.
+ if constexpr (isModulePass<PassT>) {
+ llvm::ModulePassManager MPM;
+ MPM.addPass(std::forward<PassT>(P));
+ InternalPass.emplace<llvm::ModulePassManager>(std::move(MPM));
+ } else if constexpr (isFunctionPass<PassT>) {
+ llvm::FunctionPassManager FPM;
+ FPM.addPass(std::forward<PassT>(P));
+ InternalPass.emplace<llvm::FunctionPassManager>(std::move(FPM));
+ } else {
+ static_assert(isMachineFunctionPass<PassT>, "Invalid pass type!");
+ llvm::MachineFunctionPassManager MFPM;
+ MFPM.addPass(std::forward<PassT>(P));
+ InternalPass.emplace<llvm::MachineFunctionPassManager>(std::move(MFPM));
+ }
+ }
+ };
+
+public:
+ using PassList = std::list<PassWrapper>;
+
+private:
+ template <typename InternalPassT> struct AdaptorWrapper : InternalPassT {
+ using InternalPassT::Passes;
+ };
+
+ template <typename PassManagerT, typename InternalPassT = void>
+ class PassManagerWrapper {
+ friend class TargetPassBuilder;
+
+ public:
+ bool isEmpty() const { return Passes.empty(); }
+
+ template <typename PassT> void addPass(PassT &&P) {
+ PassManagerT PM;
+ PM.addPass(std::forward<PassT>(P));
+ // Injection point doesn't add real pass.
+ if constexpr (std::is_base_of_v<InjectionPointMixin, PassT>)
+ PM = PassManagerT();
+ PassWrapper PW(PassT::name(), std::move(PM));
+ Passes.push_back(std::move(PW));
+ }
+
+ void addPass(PassManagerWrapper &&PM) {
+ for (auto &P : PM.Passes)
+ Passes.push_back(std::move(P));
+ }
+
+ void addPass(AdaptorWrapper<InternalPassT> &&Adaptor) {
+ for (auto &P : Adaptor.Passes)
+ Passes.push_back(std::move(P));
+ }
+
+ void addPass(llvm::ModulePassManager &&) = delete;
+ void addPass(llvm::FunctionPassManager &&) = delete;
+ void addPass(llvm::LoopPassManager &&) = delete;
+ void addPass(llvm::MachineFunctionPassManager &&) = delete;
+
+ private:
+ PassList Passes;
+ };
+
+ template <typename NestedPassManagerT, typename PassT>
+ AdaptorWrapper<NestedPassManagerT> createPassAdaptor(PassT &&P) {
+ AdaptorWrapper<NestedPassManagerT> Adaptor;
+ Adaptor.addPass(std::forward<PassT>(P));
+ return Adaptor;
+ }
+
+private:
+ template <typename PassT, typename IRUnitT>
+ using HasRunOnIRUnit = decltype(std::declval<PassT>().run(
+ std::declval<IRUnitT &>(), std::declval<AnalysisManager<IRUnitT> &>()));
+ template <typename PassT>
+ static constexpr bool isModulePass =
+ is_detected<HasRunOnIRUnit, PassT, Module>::value;
+ template <typename PassT>
+ static constexpr bool isFunctionPass =
+ is_detected<HasRunOnIRUnit, PassT, Function>::value;
+ template <typename PassT>
+ static constexpr bool isMachineFunctionPass =
+ is_detected<HasRunOnIRUnit, PassT, MachineFunction>::value;
+
+protected:
+ // Hijack real pass managers intentionally.
+ using MachineFunctionPassManager =
+ PassManagerWrapper<llvm::MachineFunctionPassManager>;
+ using FunctionPassManager =
+ PassManagerWrapper<llvm::FunctionPassManager, MachineFunctionPassManager>;
+ using ModulePassManager =
+ PassManagerWrapper<llvm::ModulePassManager, FunctionPassManager>;
+
+ struct CGSCCAdaptorWrapper : AdaptorWrapper<FunctionPassManager> {};
+
+protected:
+ template <typename FunctionPassT>
+ AdaptorWrapper<FunctionPassManager>
+ createModuleToFunctionPassAdaptor(FunctionPassT &&P) {
+ return createPassAdaptor<FunctionPassManager>(
+ std::forward<FunctionPassT>(P));
+ }
+
+ AdaptorWrapper<FunctionPassManager>
+ createModuleToPostOrderCGSCCPassAdaptor(CGSCCAdaptorWrapper &&PM) {
+ AdaptorWrapper<FunctionPassManager> AW;
+ AW.Passes = std::move(PM.Passes);
+ return AW;
+ }
+
+ template <typename FunctionPassT>
+ CGSCCAdaptorWrapper createCGSCCToFunctionPassAdaptor(FunctionPassT &&PM) {
+ for (auto &P : PM.Passes)
+ P.InCGSCC = true;
+ CGSCCAdaptorWrapper AW;
+ AW.Passes = std::move(PM.Passes);
+ return AW;
+ }
+
+ template <typename MachineFunctionPassT>
+ AdaptorWrapper<MachineFunctionPassManager>
+ createFunctionToMachineFunctionPassAdaptor(MachineFunctionPassT &&P) {
+ return createPassAdaptor<MachineFunctionPassManager>(
+ std::forward<MachineFunctionPassT>(P));
+ }
+
+ struct InjectionPointMixin {};
+ // When run is template, injectBefore can't recognize pass type correctly.
+ struct DummyFunctionPassBase : InjectionPointMixin {
+ PreservedAnalyses run(Function &, FunctionAnalysisManager &) {
+ return PreservedAnalyses();
+ }
+ };
+ struct DummyMachineFunctionPassBase : InjectionPointMixin {
+ PreservedAnalyses run(MachineFunction &, MachineFunctionAnalysisManager &) {
+ return PreservedAnalyses();
+ }
+ };
+ struct PreISel : PassInfoMixin<PreISel>, DummyFunctionPassBase {};
+ struct PostBBSections : PassInfoMixin<PostBBSections>,
+ DummyMachineFunctionPassBase {};
+ struct PreEmit : PassInfoMixin<PreEmit>, DummyMachineFunctionPassBase {};
+
+protected:
+ PassBuilder &PB;
+ TargetMachine *TM;
+ CodeGenOptLevel OptLevel;
+ CGPassBuilderOption CGPBO = getCGPassBuilderOption();
+
+ /// @brief The only method to extend pipeline
+ /// @tparam PassT The injection point
+ /// @tparam PassManagerT Returned pass manager, by default it depends on the
+ /// injection point.
+ /// @param F Callback to build the pipeline.
+ template <typename PassT,
+ typename PassManagerT = std::conditional_t<
+ isModulePass<PassT>, ModulePassManager,
+ std::conditional_t<isFunctionPass<PassT>, FunctionPassManager,
+ MachineFunctionPassManager>>>
+ void injectBefore(
+ typename llvm::identity<std::function<PassManagerT()>>::argument_type F) {
+ InjectionCallbacks.push_back(
+ [Accessed = false, F](PassList &Passes, PassList::iterator I) mutable {
+ if (Accessed)
+ return I;
+ if (PassT::name() != I->Name)
+ return I;
+ Accessed = true;
+ auto PMPasses = F().Passes;
+ return Passes.insert(I, std::make_move_iterator(PMPasses.begin()),
+ std::make_move_iterator(PMPasses.end()));
+ });
+ }
+
+ /// @brief Register selection dag isel pass
+ /// @tparam BuilderFuncT
+ /// @param F A function returns a selection dag isel pass.
+ template <typename BuilderFuncT>
+ void registerSelectionDAGISelPass(BuilderFuncT F) {
+ AddSelectionDAGISelPass = [=](MachineFunctionPassManager &MFPM) {
+ using ResultT = std::invoke_result_t<BuilderFuncT>;
+ static_assert(isMachineFunctionPass<ResultT> &&
+ !std::is_same_v<MachineFunctionPassManager, ResultT>,
+ "Please add only SelectionDAGISelPass!");
+ MFPM.addPass(F());
+ };
+ }
+
+ template <typename PassTs> void disablePass() {
+ DisabedPasses.insert(PassTs::name());
+ }
+
+ void disablePass(StringRef Name) { DisabedPasses.insert(Name); }
+
+ template <typename PassT> bool isPassDisabled() const {
+ return DisabedPasses.contains(PassT::name());
+ }
+
+ bool isPassDisabled(StringRef Name) const {
+ return DisabedPasses.contains(Name);
+ }
+
+ template <typename PassT> bool isPassEnabled() const {
+ return !isPassDisabled<PassT>();
+ }
+
+ bool isPassEnabled(StringRef Name) const { return !isPassDisabled(Name); }
+
+private:
+ void buildCoreCodeGenPipeline(ModulePassManager &MPM);
+
+ ModulePassManager buildCodeGenIRPipeline();
+
+ /// Add passes that optimize machine instructions in SSA form.
+ void addISelPasses(MachineFunctionPassManager &MFPM);
+ void addMachineSSAOptimizationPasses(MachineFunctionPassManager &MFPM);
+ void addRegAllocPipeline(MachineFunctionPassManager &MFPM);
+ void addRegAllocPass(MachineFunctionPassManager &MFPM, bool Optimized);
+ ModulePassManager buildCodeGenMIRPipeline();
+
+ void addExceptionHandlingPasses(FunctionPassManager &FPM);
+
+ void filtPassList(ModulePassManager &MPM) const;
+
+ void addPrinterPassesAndFreeMachineFunction(ModulePassManager &MPM,
+ raw_pwrite_stream &Out,
+ raw_pwrite_stream *DwoOut,
+ CodeGenFileType FileType,
+ MCContext &Ctx);
+
+ llvm::ModulePassManager constructRealPassManager(ModulePassManager &&MPMW);
+
+private:
+ virtual void anchor();
+
+ StringSet<> DisabedPasses;
+ std::vector<std::function<PassList::iterator(PassList &, PassList::iterator)>>
+ InjectionCallbacks;
+ std::function<void(MachineFunctionPassManager &)> AddSelectionDAGISelPass;
+
+ void invokeInjectionCallbacks(ModulePassManager &MPM) const;
+
+ // Only Loop Strength Reduction need this, shadow LoopPassManager
+ // in future if it is necessary.
+ template <typename PassT>
+ void addLoopPass(FunctionPassManager &FPM, PassT &&P) {
+ LoopPassManager LPM;
+ LPM.addPass(std::forward<PassT>(P));
+ FPM.Passes.push_back(PassWrapper(PassT::name(), std::move(LPM)));
+ }
+};
+
+template <> struct TargetPassBuilder::AdaptorWrapper<void> {};
+
+} // namespace llvm
+
+#endif
diff --git a/llvm/include/llvm/Target/CGPassBuilderOption.h b/llvm/include/llvm/Target/CGPassBuilderOption.h
index 22b62e841dbc3..ae12508ab722a 100644
--- a/llvm/include/llvm/Target/CGPassBuilderOption.h
+++ b/llvm/include/llvm/Target/CGPassBuilderOption.h
@@ -63,7 +63,6 @@ struct CGPassBuilderOption {
bool MISchedPostRA = false;
bool EarlyLiveIntervals = false;
bool EnableGCEmptyBlocks = false;
-
bool DisableLSR = false;
bool DisableCGP = false;
bool DisablePartialLibcallInlining = false;
@@ -73,6 +72,9 @@ struct CGPassBuilderOption {
bool DisableExpandReductions = false;
bool DisableRAFSProfileLoader = false;
bool DisableCFIFixup = false;
+ bool DisableReplaceWithVecLib = false;
+ bool DisableLayoutFSProfileLoader = false;
+ bool DisablePrologEpilogInserterPass = false;
bool PrintAfterISel = false;
bool PrintISelInput = false;
bool PrintRegUsage = false;
diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp
index 6231ab1ba0734..e4309e920265e 100644
--- a/llvm/lib/CodeGen/TargetPassConfig.cpp
+++ b/llvm/lib/CodeGen/TargetPassConfig.cpp
@@ -528,6 +528,8 @@ CGPassBuilderOption llvm::getCGPassBuilderOption() {
SET_BOOLEAN_OPTION(DisableCGP)
SET_BOOLEAN_OPTION(DisablePartialLibcallInlining)
SET_BOOLEAN_OPTION(DisableSelectOptimize)
+ SET_BOOLEAN_OPTION(DisableReplaceWithVecLib)
+ SET_BOOLEAN_OPTION(DisableLayoutFSProfileLoader)
SET_BOOLEAN_OPTION(PrintISelInput)
SET_BOOLEAN_OPTION(PrintRegUsage)
SET_BOOLEAN_OPTION(DebugifyAndStripAll)
@@ -535,6 +537,7 @@ CGPassBuilderOption llvm::getCGPassBuilderOption() {
SET_BOOLEAN_OPTION(DisableRAFSProfileLoader)
SET_BOOLEAN_OPTION(DisableCFIFixup)
SET_BOOLEAN_OPTION(EnableMachineFunctionSplitter)
+ SET_BOOLEAN_OPTION(SplitStaticData)
return Opt;
}
diff --git a/llvm/lib/Passes/CMakeLists.txt b/llvm/lib/Passes/CMakeLists.txt
index 5d7cd3689f3ff..281e38b26f630 100644
--- a/llvm/lib/Passes/CMakeLists.txt
+++ b/llvm/lib/Passes/CMakeLists.txt
@@ -5,6 +5,7 @@ add_llvm_component_library(LLVMPasses
PassBuilderBindings.cpp
PassBuilderPipelines.cpp
StandardInstrumentations.cpp
+ TargetPassBuilder.cpp
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm
diff --git a/llvm/lib/Passes/TargetPassBuilder.cpp b/llvm/lib/Passes/TargetPassBuilder.cpp
new file mode 100644
index 0000000000000..863b7a1cd6d7a
--- /dev/null
+++ b/llvm/lib/Passes/TargetPassBuilder.cpp
@@ -0,0 +1,864 @@
+//===- Construction of CodeGen pass pipelines -----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Passes/TargetPassBuilder.h"
+#include "llvm/CodeGen/CallBrPrepare.h"
+#include "llvm/CodeGen/CodeGenPrepare.h"
+#include "llvm/CodeGen/DwarfEHPrepare.h"
+#include "llvm/CodeGen/ExpandFp.h"
+#include "llvm/CodeGen/ExpandLargeDivRem.h"
+#include "llvm/CodeGen/ExpandMemCmp.h"
+#include "llvm/CodeGen/ExpandReductions.h"
+#include "llvm/CodeGen/FinalizeISel.h"
+#include "llvm/CodeGen/GCMetadata.h"
+#include "llvm/CodeGen/GlobalMergeFunctions.h"
+#include "llvm/CodeGen/LiveVariables.h"
+#include "llvm/CodeGen/LocalStackSlotAllocation.h"
+#include "llvm/CodeGen/LowerEmuTLS.h"
+#include "llvm/CodeGen/MachineFunctionAnalysis.h"
+#include "llvm/CodeGen/MachineLoopInfo.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachinePassManager.h"
+#include "llvm/CodeGen/PreISelIntrinsicLowering.h"
+#include "llvm/CodeGen/ReplaceWithVeclib.h"
+#include "llvm/CodeGen/SafeStack.h"
+#include "llvm/CodeGen/SelectOptimize.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
+#include "llvm/CodeGen/ShadowStackGCLowering.h"
+#include "llvm/CodeGen/SjLjEHPrepare.h"
+#include "llvm/CodeGen/StackProtector.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
+#include "llvm/CodeGen/UnreachableBlockElim.h"
+#include "llvm/CodeGen/WasmEHPrepare.h"
+#include "llvm/CodeGen/WinEHPrepare.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Passes/CodeGenPassBuilder.h" // Dummy passes only!
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Transforms/ObjCARC.h"
+#include "llvm/Transforms/Scalar/ConstantHoisting.h"
+#include "llvm/Transforms/Scalar/LoopStrengthReduce.h"
+#include "llvm/Transforms/Scalar/LoopTermFold.h"
+#include "llvm/Transforms/Scalar/MergeICmps.h"
+#include "llvm/Transforms/Scalar/PartiallyInlineLibCalls.h"
+#include "llvm/Transforms/Scalar/ScalarizeMaskedMemIntrin.h"
+#include "llvm/Transforms/Utils/CanonicalizeFreezeInLoops.h"
+#include "llvm/Transforms/Utils/LowerGlobalDtors.h"
+#include "llvm/Transforms/Utils/LowerInvoke.h"
+#include <stack>
+
+using namespace llvm;
+
+TargetPassBuilder::TargetPassBuilder(PassBuilder &PB)
+ : PB(PB), TM(PB.TM), OptLevel(TM->getOptLevel()) {}
+
+ModulePassManager TargetPassBuilder::buildPipeline(raw_pwrite_stream &Out,
+ raw_pwrite_stream *DwoOut,
+ CodeGenFileType FileType,
+ MCContext &Ctx) {
+ ModulePassManager MPM;
+ buildCoreCodeGenPipeline(MPM);
+ invokeInjectionCallbacks(MPM);
+ filtPassList(MPM);
+ addPrinterPassesAndFreeMachineFunction(MPM, Out, DwoOut, FileType, Ctx);
+ return constructRealPassManager(std::move(MPM));
+}
+
+void TargetPassBuilder::buildCoreCodeGenPipeline(ModulePassManager &MPM) {
+ MPM.addPass(buildCodeGenIRPipeline());
+ MachineFunctionPassManager MFPM;
+ addISelPasses(MFPM);
+ MPM.addPass(createModuleToFunctionPassAdaptor(
+ createFunctionToMachineFunctionPassAdaptor(std::move(MFPM))));
+ MPM.addPass(buildCodeGenMIRPipeline());
+}
+
+TargetPassBuilder::ModulePassManager
+TargetPassBuilder::buildCodeGenIRPipeline() {
+ ModulePassManager MPM;
+ if (TM->useEmulatedTLS())
+ MPM.addPass(LowerEmuTLSPass());
+ MPM.addPass(PreISelIntrinsicLoweringPass(TM));
+ FunctionPassManager FPM;
+ FPM.addPass(ExpandLargeDivRemPass(TM));
+ FPM.addPass(ExpandFpPass(TM));
+
+ // Run loop strength reduction before anything else.
+ if (TM->getOptLevel() == CodeGenOptLevel::None) {
+ // Basic AliasAnalysis support.
+ // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that
+ // BasicAliasAnalysis wins if they disagree. This is intended to help
+ // support "obvious" type-punning idioms.
+ FPM.addPass(RequireAnalysisPass<TypeBasedAA, Function>());
+ FPM.addPass(RequireAnalysisPass<ScopedNoAliasAA, Function>());
+ FPM.addPass(RequireAnalysisPass<BasicAA, Function>());
+
+ if (!CGPBO.DisableLSR) {
+ addLoopPass(FPM, CanonicalizeFreezeInLoopsPass());
+ addLoopPass(FPM, LoopStrengthReducePass());
+ if (CGPBO.EnableLoopTermFold)
+ addLoopPass(FPM, LoopTermFoldPass());
+ }
+
+ // The MergeICmpsPass tries to create memcmp calls by grouping sequences
+ // of loads and compares. ExpandMemCmpPass then tries to expand those
+ // calls into optimally-sized loads and compares. The transforms are
+ // enabled by a target lowering hook.
+ if (!CGPBO.DisableMergeICmps)
+ FPM.addPass(MergeICmpsPass());
+ FPM.addPass(ExpandMemCmpPass(TM));
+ }
+
+ // Run GC lowering passes for builtin collectors
+ FPM.addPass(GCLoweringPass());
+ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ FPM = FunctionPassManager();
+ MPM.addPass(ShadowStackGCLoweringPass());
+ // PB.invokeGCLoweringEPCallbacks();
+
+ if (TM->getTargetTriple().isOSBinFormatMachO() &&
+ !CGPBO.DisableAtExitBasedGlobalDtorLowering) {
+ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ FPM = FunctionPassManager();
+ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ MPM.addPass(LowerGlobalDtorsPass());
+ }
+
+ // Make sure that no unreachable blocks are instruction selected.
+ FPM.addPass(UnreachableBlockElimPass());
+
+ if (OptLevel != CodeGenOptLevel::None) {
+ if (!CGPBO.DisableConstantHoisting)
+ FPM.addPass(ConstantHoistingPass());
+ if (!CGPBO.DisableReplaceWithVecLib)
+ FPM.addPass(ReplaceWithVeclib());
+ if (!CGPBO.DisablePartialLibcallInlining)
+ FPM.addPass(PartiallyInlineLibCallsPass());
+ }
+
+ // Instrument function entry after all inlining.
+ FPM.addPass(EntryExitInstrumenterPass(/*PostInlining=*/true));
+
+ // Add scalarization of target's unsupported masked memory intrinsics pass.
+ // the unsupported intrinsic will be replaced with a chain of basic blocks,
+ // that stores/loads element one-by-one if the appropriate mask bit is set.
+ FPM.addPass(ScalarizeMaskedMemIntrinPass());
+
+ // Expand reduction intrinsics into shuffle sequences if the target wants
+ // to. Allow disabling it for testing purposes.
+ if (!CGPBO.DisableExpandReductions)
+ FPM.addPass(ExpandReductionsPass());
+
+ // Convert conditional moves to conditional jumps when profitable.
+ if (OptLevel != CodeGenOptLevel::None && !CGPBO.DisableSelectOptimize)
+ FPM.addPass(SelectOptimizePass(TM));
+
+ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ if (CGPBO.EnableGlobalMergeFunc)
+ MPM.addPass(GlobalMergeFuncPass());
+
+ if (OptLevel != CodeGenOptLevel::None && !CGPBO.DisableCGP)
+ FPM.addPass(CodeGenPreparePass(PB.TM));
+ addExceptionHandlingPasses(FPM);
+
+ // Add common passes that perform LLVM IR to IR transforms in preparation for
+ // instruction selection.
+ if (CGPBO.RequiresCodeGenSCCOrder) {
+ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ FPM = FunctionPassManager();
+ }
+
+ // Now we need to force codegen to run according to the callgraph if target
+ // requires it.
+ FPM.addPass(PreISel());
+ if (OptLevel != CodeGenOptLevel::None)
+ FPM.addPass(ObjCARCContractPass());
+
+ FPM.addPass(CallBrPreparePass());
+
+ // Add both the safe stack and the stack protection passes: each of them will
+ // only protect functions that have corresponding attributes.
+ FPM.addPass(SafeStackPass(TM));
+ FPM.addPass(StackProtectorPass(TM));
+
+ // All passes which modify the LLVM IR are now complete; run the verifier
+ // to ensure that the IR is valid.
+ if (!CGPBO.DisableVerify)
+ FPM.addPass(VerifierPass());
+ if (CGPBO.RequiresCodeGenSCCOrder)
+ MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
+ createCGSCCToFunctionPassAdaptor(std::move(FPM))));
+ else
+ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ return MPM;
+}
+
+void TargetPassBuilder::addISelPasses(MachineFunctionPassManager &MFPM) {
+ // Add core instruction selection passes.
+ // Enable FastISel with -fast-isel, but allow that to be overridden.
+ TM->setO0WantsFastISel(CGPBO.EnableFastISelOption.value_or(true));
+
+ // Determine an instruction selector.
+ enum class SelectorType { SelectionDAG, FastISel, GlobalISel };
+ SelectorType Selector;
+
+ if (CGPBO.EnableFastISelOption.value_or(false))
+ Selector = SelectorType::FastISel;
+ else if (CGPBO.EnableGlobalISelOption.value_or(false) ||
+ (TM->Options.EnableGlobalISel &&
+ CGPBO.EnableGlobalISelOption.value_or(true)))
+ Selector = SelectorType::GlobalISel;
+ else if (TM->getOptLevel() == CodeGenOptLevel::None &&
+ TM->getO0WantsFastISel())
+ Selector = SelectorType::FastISel;
+ else
+ Selector = SelectorType::SelectionDAG;
+
+ // Set consistently TM->Options.EnableFastISel and EnableGlobalISel.
+ if (Selector == SelectorType::FastISel) {
+ TM->setFastISel(true);
+ TM->setGlobalISel(false);
+ } else if (Selector == SelectorType::GlobalISel) {
+ TM->setFastISel(false);
+ TM->setGlobalISel(true);
+ }
+
+ // FIXME: Currently debugify is not support in new pass manager,
+ // because it inserts module passes between each pass.
+
+ // Add instruction selector passes for global isel if enabled.
+ if (Selector == SelectorType::GlobalISel) {
+ MFPM.addPass(IRTranslatorPass());
+ MFPM.addPass(RegBankSelectPass());
+ MFPM.addPass(InstructionSelectPass(OptLevel));
+ }
+
+ // Pass to reset the MachineFunction if the ISel failed. Outside of the
+ // above if so that the verifier is not added to it.
+ MFPM.addPass(ResetMachineFunctionPass());
+
+ // Run the SDAG InstSelector, providing a fallback path when we do not want
+ // to abort on not-yet-supported input.
+ if (Selector != SelectorType::GlobalISel ||
+ TM->Options.GlobalISelAbort != GlobalISelAbortMode::Enable) {
+ AddSelectionDAGISelPass(MFPM);
+ }
+
+ // Expand pseudo-instructions emitted by ISel. Don't run the verifier
+ // before FinalizeISel.
+ MFPM.addPass(FinalizeISelPass());
+}
+
+void TargetPassBuilder::addRegAllocPipeline(MachineFunctionPassManager &MFPM) {
+ if (CGPBO.OptimizeRegAlloc.value_or(OptLevel != CodeGenOptLevel::None)) {
+ MFPM.addPass(DetectDeadLanesPass());
+
+ MFPM.addPass(InitUndefPass());
+
+ MFPM.addPass(ProcessImplicitDefsPass());
+
+ // LiveVariables currently requires pure SSA form.
+ //
+ // FIXME: Once TwoAddressInstruction pass no longer uses kill flags,
+ // LiveVariables can be removed completely, and LiveIntervals can be
+ // directly computed. (We still either need to regenerate kill flags after
+ // regalloc, or preferably fix the scavenger to not depend on them).
+ // FIXME: UnreachableMachineBlockElim is a dependant pass of LiveVariables.
+ // When LiveVariables is removed this has to be removed/moved either.
+ // Explicit addition of UnreachableMachineBlockElim allows stopping before
+ // or after it with -stop-before/-stop-after.
+ MFPM.addPass(UnreachableMachineBlockElimPass());
+ MFPM.addPass(RequireAnalysisPass<LiveVariablesAnalysis, MachineFunction>());
+
+ // Edge splitting is smarter with machine loop info.
+ MFPM.addPass(RequireAnalysisPass<MachineLoopAnalysis, MachineFunction>());
+ MFPM.addPass(PHIEliminationPass());
+
+ // Eventually, we want to run LiveIntervals before PHI elimination.
+ if (CGPBO.EarlyLiveIntervals)
+ MFPM.addPass(
+ RequireAnalysisPass<LiveIntervalsAnalysis, MachineFunction>());
+
+ MFPM.addPass(TwoAddressInstructionPass());
+ MFPM.addPass(RegisterCoalescerPass());
+
+ // The machine scheduler may accidentally create disconnected components
+ // when moving subregister definitions around, avoid this by splitting them
+ // to separate vregs before. Splitting can also improve reg. allocation
+ // quality.
+ MFPM.addPass(RenameIndependentSubregsPass());
+
+ // PreRA instruction scheduling.
+ MFPM.addPass(MachineSchedulerPass(TM));
+
+ /// Add register assign and rewrite passes.
+ // Add the selected register allocation pass.
+ addRegAllocPass(MFPM, true);
+
+ // Finally rewrite virtual registers.
+ MFPM.addPass(VirtRegRewriterPass());
+
+ // Regalloc scoring for ML-driven eviction - noop except when learning a new
+ // eviction policy.
+ MFPM.addPass(RegAllocScoringPass());
+
+ // Perform stack slot coloring and post-ra machine LICM.
+ MFPM.addPass(StackSlotColoringPass());
+
+ // Allow targets to expand pseudo instructions depending on the choice of
+ // registers before MachineCopyPropagation.
+
+ // Copy propagate to forward register uses and try to eliminate COPYs that
+ // were not coalesced.
+ MFPM.addPass(MachineCopyPropagationPass());
+
+ // Run post-ra machine LICM to hoist reloads / remats.
+ //
+ // FIXME: can this move into MachineLateOptimization?
+ MFPM.addPass(MachineLICMPass());
+ } else {
+ MFPM.addPass(PHIEliminationPass());
+ MFPM.addPass(TwoAddressInstructionPass());
+
+ /// Add register assign and rewrite passes.
+ if (CGPBO.RegAlloc != RegAllocType::Default &&
+ CGPBO.RegAlloc != RegAllocType::Fast)
+ report_fatal_error("Must use fast (default) register allocator for "
+ "unoptimized regalloc.");
+
+ addRegAllocPass(MFPM, false);
+ }
+}
+
+void TargetPassBuilder::addRegAllocPass(MachineFunctionPassManager &MFPM,
+ bool Optimized) {
+ // TODO: Handle register allocator
+}
+
+void TargetPassBuilder::addMachineSSAOptimizationPasses(
+ MachineFunctionPassManager &MFPM) {
+ // Pre-ra tail duplication.
+ MFPM.addPass(EarlyTailDuplicatePass());
+
+ // Optimize PHIs before DCE: removing dead PHI cycles may make more
+ // instructions dead.
+ MFPM.addPass(OptimizePHIsPass());
+
+ // This pass merges large allocas. StackSlotColoring is a different pass
+ // which merges spill slots.
+ MFPM.addPass(StackColoringPass());
+
+ // If the target requests it, assign local variables to stack slots relative
+ // to one another and simplify frame index references where possible.
+ MFPM.addPass(LocalStackSlotAllocationPass());
+
+ // With optimization, dead code should already be eliminated. However
+ // there is one known exception: lowered code for arguments that are only
+ // used by tail calls, where the tail calls reuse the incoming stack
+ // arguments directly (see t11 in test/CodeGen/X86/sibcall.ll).
+ MFPM.addPass(DeadMachineInstructionElimPass());
+
+ // Target can insert passes here that improve instruction level parallelism,
+ // like if-conversion. Such passes will typically need dominator trees and
+ // loop info, just like LICM and CSE below.
+ // Just use injectBefore<EarlyMachineLICMPass>([](){ Your pass builder... });
+
+ MFPM.addPass(EarlyMachineLICMPass());
+ MFPM.addPass(MachineCSEPass());
+
+ MFPM.addPass(MachineSinkingPass(CGPBO.EnableSinkAndFold));
+
+ MFPM.addPass(PeepholeOptimizerPass());
+ // Clean-up the dead code that may have been generated by peephole
+ // rewriting.
+ MFPM.addPass(DeadMachineInstructionElimPass());
+}
+
+// Find the FSProfile file name. The internal option takes the precedence
+// before getting from TargetMachine.
+static std::string getFSProfileFile(const CGPassBuilderOption &CGPBO,
+ const TargetMachine *TM) {
+ if (!CGPBO.FSProfileFile.empty())
+ return CGPBO.FSProfileFile;
+ const std::optional<PGOOptions> &PGOOpt = TM->getPGOOption();
+ if (!PGOOpt || PGOOpt->Action != PGOOptions::SampleUse)
+ return std::string();
+ return PGOOpt->ProfileFile;
+}
+
+// Find the Profile remapping file name. The internal option takes the
+// precedence before getting from TargetMachine.
+static std::string getFSRemappingFile(const CGPassBuilderOption &CGPBO,
+ const TargetMachine *TM) {
+ if (!CGPBO.FSRemappingFile.empty())
+ return CGPBO.FSRemappingFile;
+ const std::optional<PGOOptions> &PGOOpt = TM->getPGOOption();
+ if (!PGOOpt || PGOOpt->Action != PGOOptions::SampleUse)
+ return std::string();
+ return PGOOpt->ProfileRemappingFile;
+}
+
+TargetPassBuilder::ModulePassManager
+TargetPassBuilder::buildCodeGenMIRPipeline() {
+ ModulePassManager MPM;
+ MachineFunctionPassManager MFPM;
+ if (OptLevel != CodeGenOptLevel::None) {
+ addMachineSSAOptimizationPasses(MFPM);
+ } else {
+ // If the target requests it, assign local variables to stack slots relative
+ // to one another and simplify frame index references where possible.
+ MFPM.addPass(LocalStackSlotAllocationPass());
+ }
+
+ if (TM->Options.EnableIPRA)
+ MFPM.addPass(RegUsageInfoPropagationPass());
+
+ // Add a FSDiscriminator pass right before RA, so that we could get
+ // more precise SampleFDO profile for RA.
+
+ if (EnableFSDiscriminator) {
+ MFPM.addPass(
+ MIRAddFSDiscriminatorsPass(sampleprof::FSDiscriminatorPass::Pass1));
+ const std::string ProfileFile = getFSProfileFile(CGPBO, TM);
+ if (!ProfileFile.empty() && !CGPBO.DisableRAFSProfileLoader)
+ MFPM.addPass(MIRProfileLoaderNewPass(
+ ProfileFile, getFSRemappingFile(CGPBO, TM),
+ sampleprof::FSDiscriminatorPass::Pass1, nullptr));
+ }
+
+ // Run register allocation and passes that are tightly coupled with it,
+ // including phi elimination and scheduling.
+ addRegAllocPipeline(MFPM);
+
+ MFPM.addPass(RemoveRedundantDebugValuesPass());
+
+ MFPM.addPass(FixupStatepointCallerSavedPass());
+
+ // Insert prolog/epilog code. Eliminate abstract frame index references...
+ if (OptLevel != CodeGenOptLevel::None) {
+ MFPM.addPass(PostRAMachineSinkingPass());
+ MFPM.addPass(ShrinkWrapPass());
+ }
+
+ // Prolog/Epilog inserter needs a TargetMachine to instantiate. But only
+ // do so if it hasn't been disabled, substituted, or overridden.
+ if (!CGPBO.DisablePrologEpilogInserterPass)
+ MFPM.addPass(PrologEpilogCodeInserterPass());
+
+ /// Add passes that optimize machine instructions after register
+ /// allocation.
+ if (OptLevel != CodeGenOptLevel::None) {
+ // Cleanup of redundant immediate/address loads.
+ MFPM.addPass(MachineLateInstrsCleanupPass());
+
+ // Branch folding must be run after regalloc and prolog/epilog insertion.
+ MFPM.addPass(BranchFolderPass(CGPBO.EnableTailMerge));
+
+ // Tail duplication.
+ // Note that duplicating tail just increases code size and degrades
+ // performance for targets that require Structured Control Flow.
+ // In addition it can also make CFG irreducible. Thus we disable it.
+ if (!TM->requiresStructuredCFG())
+ MFPM.addPass(TailDuplicatePass());
+
+ // Copy propagation.
+ MFPM.addPass(MachineCopyPropagationPass());
+ }
+
+ // Expand pseudo instructions before second scheduling pass.
+ MFPM.addPass(ExpandPostRAPseudosPass());
+
+ if (CGPBO.EnableImplicitNullChecks)
+ MFPM.addPass(ImplicitNullChecksPass());
+
+ // Second pass scheduler.
+ // Let Target optionally insert this pass by itself at some other
+ // point.
+ if (OptLevel != CodeGenOptLevel::None &&
+ !TM->targetSchedulesPostRAScheduling()) {
+ if (CGPBO.MISchedPostRA)
+ MFPM.addPass(PostMachineSchedulerPass(TM));
+ else
+ MFPM.addPass(PostRASchedulerPass(TM));
+ }
+
+ // GC
+ // MFPM.addPass(GCMachineCodeAnalysis());
+
+ // Basic block placement.
+ if (OptLevel != CodeGenOptLevel::None) {
+ if (EnableFSDiscriminator) {
+ MFPM.addPass(
+ MIRAddFSDiscriminatorsPass(sampleprof::FSDiscriminatorPass::Pass2));
+ const std::string ProfileFile = getFSProfileFile(CGPBO, TM);
+ if (!ProfileFile.empty() && !CGPBO.DisableLayoutFSProfileLoader)
+ MFPM.addPass(MIRProfileLoaderNewPass(
+ ProfileFile, getFSRemappingFile(CGPBO, TM),
+ sampleprof::FSDiscriminatorPass::Pass2, nullptr));
+ MFPM.addPass(MachineBlockPlacementPass(CGPBO.EnableTailMerge));
+ // Run a separate pass to collect block placement statistics.
+ if (CGPBO.EnableBlockPlacementStats)
+ MFPM.addPass(MachineBlockPlacementStatsPass());
+ }
+ }
+
+ // Insert before XRay Instrumentation.
+ MFPM.addPass(FEntryInserterPass());
+
+ MFPM.addPass(XRayInstrumentationPass());
+ MFPM.addPass(PatchableFunctionPass());
+
+ if (TM->Options.EnableIPRA)
+ // Collect register usage information and produce a register mask of
+ // clobbered registers, to be used to optimize call sites.
+ MFPM.addPass(RegUsageInfoCollectorPass());
+
+ // FIXME: Some backends are incompatible with running the verifier after
+ // addPreEmitPass. Maybe only pass "false" here for those targets?
+ MFPM.addPass(FuncletLayoutPass());
+
+ MFPM.addPass(RemoveLoadsIntoFakeUsesPass());
+ MFPM.addPass(StackMapLivenessPass());
+ MFPM.addPass(LiveDebugValuesPass(TM->Options.ShouldEmitDebugEntryValues()));
+ MFPM.addPass(MachineSanitizerBinaryMetadataPass());
+
+ if (TM->Options.EnableMachineOutliner && OptLevel != CodeGenOptLevel::None &&
+ CGPBO.EnableMachineOutliner != RunOutliner::NeverOutline) {
+ bool RunOnAllFunctions =
+ (CGPBO.EnableMachineOutliner == RunOutliner::AlwaysOutline);
+ bool AddOutliner =
+ RunOnAllFunctions || TM->Options.SupportsDefaultOutlining;
+ if (AddOutliner) {
+ if (CGPBO.RequiresCodeGenSCCOrder)
+ MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
+ createCGSCCToFunctionPassAdaptor(
+ createFunctionToMachineFunctionPassAdaptor(std::move(MFPM)))));
+ else
+ MPM.addPass(createModuleToFunctionPassAdaptor(
+ createFunctionToMachineFunctionPassAdaptor(std::move(MFPM))));
+ MPM.addPass(MachineOutlinerPass(RunOnAllFunctions));
+ MFPM = MachineFunctionPassManager();
+ }
+ }
+
+ if (CGPBO.GCEmptyBlocks)
+ MFPM.addPass(GCEmptyBasicBlocksPass());
+
+ if (EnableFSDiscriminator)
+ MFPM.addPass(
+ MIRAddFSDiscriminatorsPass(sampleprof::FSDiscriminatorPass::PassLast));
+
+ // Machine function splitter uses the basic block sections feature.
+ // When used along with `-basic-block-sections=`, the basic-block-sections
+ // feature takes precedence. This means functions eligible for
+ // basic-block-sections optimizations (`=all`, or `=list=` with function
+ // included in the list profile) will get that optimization instead.
+ if (TM->Options.EnableMachineFunctionSplitter ||
+ CGPBO.EnableMachineFunctionSplitter) {
+ const std::string ProfileFile = getFSProfileFile(CGPBO, TM);
+ if (!ProfileFile.empty()) {
+ if (EnableFSDiscriminator) {
+ MFPM.addPass(MIRProfileLoaderNewPass(
+ ProfileFile, getFSRemappingFile(CGPBO, TM),
+ sampleprof::FSDiscriminatorPass::PassLast, nullptr));
+ } else {
+ // Sample profile is given, but FSDiscriminator is not
+ // enabled, this may result in performance regression.
+ WithColor::warning()
+ << "Using AutoFDO without FSDiscriminator for MFS may regress "
+ "performance.\n";
+ }
+ }
+ MFPM.addPass(MachineFunctionSplitterPass());
+ if (CGPBO.SplitStaticData || TM->Options.EnableStaticDataPartitioning) {
+ // The static data splitter pass is a machine function pass. and
+ // static data annotator pass is a module-wide pass. See the file comment
+ // in StaticDataAnnotator.cpp for the motivation.
+ MFPM.addPass(StaticDataSplitterPass());
+ if (CGPBO.RequiresCodeGenSCCOrder)
+ MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
+ createCGSCCToFunctionPassAdaptor(
+ createFunctionToMachineFunctionPassAdaptor(std::move(MFPM)))));
+ else
+ MPM.addPass(createModuleToFunctionPassAdaptor(
+ createFunctionToMachineFunctionPassAdaptor(std::move(MFPM))));
+ MFPM = MachineFunctionPassManager();
+ MPM.addPass(StaticDataAnnotatorPass());
+ }
+ }
+ // We run the BasicBlockSections pass if either we need BB sections or BB
+ // address map (or both).
+ if (TM->getBBSectionsType() != llvm::BasicBlockSection::None ||
+ TM->Options.BBAddrMap) {
+ if (TM->getBBSectionsType() == llvm::BasicBlockSection::List) {
+ MFPM.addPass(
+ BasicBlockSectionsProfileReaderPass(TM->getBBSectionsFuncListBuf()));
+ MFPM.addPass(BasicBlockPathCloningPass());
+ }
+ MFPM.addPass(BasicBlockSectionsPass());
+ }
+
+ MFPM.addPass(PostBBSections());
+
+ if (!CGPBO.DisableCFIFixup && TM->Options.EnableCFIFixup)
+ MFPM.addPass(CFIFixupPass());
+
+ MFPM.addPass(StackFrameLayoutAnalysisPass());
+ MFPM.addPass(PreEmit());
+ if (CGPBO.RequiresCodeGenSCCOrder)
+ MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
+ createCGSCCToFunctionPassAdaptor(
+ createFunctionToMachineFunctionPassAdaptor(std::move(MFPM)))));
+ else
+ MPM.addPass(createModuleToFunctionPassAdaptor(
+ createFunctionToMachineFunctionPassAdaptor(std::move(MFPM))));
+ return MPM;
+}
+
+void TargetPassBuilder::addExceptionHandlingPasses(FunctionPassManager &FPM) {
+ const MCAsmInfo *MCAI = TM->getMCAsmInfo();
+
+ switch (MCAI->getExceptionHandlingType()) {
+ case ExceptionHandling::SjLj:
+ // SjLj piggy-backs on dwarf for this bit. The cleanups done apply to both
+ // Dwarf EH prepare needs to be run after SjLj prepare. Otherwise,
+ // catch info can get misplaced when a selector ends up more than one block
+ // removed from the parent invoke(s). This could happen when a landing
+ // pad is shared by multiple invokes and is also a target of a normal
+ // edge from elsewhere.
+ FPM.addPass(SjLjEHPreparePass(TM));
+ [[fallthrough]];
+ case ExceptionHandling::DwarfCFI:
+ case ExceptionHandling::ARM:
+ case ExceptionHandling::AIX:
+ case ExceptionHandling::ZOS:
+ FPM.addPass(DwarfEHPreparePass(TM));
+ break;
+ case ExceptionHandling::WinEH:
+ // We support using both GCC-style and MSVC-style exceptions on Windows, so
+ // add both preparation passes. Each pass will only actually run if it
+ // recognizes the personality function.
+ FPM.addPass(WinEHPreparePass());
+ FPM.addPass(DwarfEHPreparePass(TM));
+ break;
+ case ExceptionHandling::Wasm:
+ // Wasm EH uses Windows EH instructions, but it does not need to demote PHIs
+ // on catchpads and cleanuppads because it does not outline them into
+ // funclets. Catchswitch blocks are not lowered in SelectionDAG, so we
+ // should remove PHIs there.
+ FPM.addPass(WinEHPreparePass(/*DemoteCatchSwitchPHIOnly=*/true));
+ FPM.addPass(WasmEHPreparePass());
+ break;
+ case ExceptionHandling::None:
+ FPM.addPass(LowerInvokePass());
+ // The lower invoke pass may create unreachable code. Remove it.
+ FPM.addPass(UnreachableBlockElimPass());
+ break;
+ }
+}
+
+void TargetPassBuilder::filtPassList(ModulePassManager &MPM) const {
+ PassList &Passes = MPM.Passes;
+ auto *PIC = PB.getPassInstrumentationCallbacks();
+ auto ESSI = TargetPassConfig::getStartStopInfo(*PIC);
+ if (!ESSI)
+ report_fatal_error(ESSI.takeError(), "invalid start stop flag!");
+ auto SSI = *ESSI;
+ size_t StartCnt = 0, StopCnt = 0;
+ bool HandledStartAfter = !SSI.StartAfter, HandledStopAfter = !SSI.StopAfter;
+ bool ShouldRemove = !SSI.StartPass.empty();
+ for (auto I = Passes.begin(), E = Passes.end(); I != E;) {
+ // Handle disabled pass firstly.
+ if (isPassDisabled(I->Name)) {
+ I = Passes.erase(I);
+ continue;
+ }
+
+ auto PassName = PIC->getPassNameForClassName(I->Name);
+ if (!SSI.StartPass.empty() && PassName == SSI.StartPass) {
+ ++StartCnt;
+ if (StartCnt == SSI.StartInstanceNum)
+ ShouldRemove = SSI.StartAfter;
+ }
+ if (!SSI.StopPass.empty() && PassName == SSI.StopPass) {
+ ++StopCnt;
+ if (StopCnt == SSI.StopInstanceNum)
+ ShouldRemove = !SSI.StopAfter;
+ }
+ bool Inc = true;
+ if (ShouldRemove && !PassName.starts_with("RequireAnalysisPass")) {
+ Inc = false;
+ I = Passes.erase(I);
+ }
+ if (!HandledStartAfter && !SSI.StartPass.empty() &&
+ PassName == SSI.StartPass && SSI.StartAfter &&
+ StartCnt == SSI.StartInstanceNum) {
+ HandledStartAfter = true;
+ ShouldRemove = false;
+ }
+ if (!HandledStopAfter && !SSI.StopPass.empty() &&
+ PassName == SSI.StopPass && SSI.StopAfter &&
+ StopCnt == SSI.StopInstanceNum) {
+ HandledStopAfter = true;
+ ShouldRemove = true;
+ }
+ if (Inc)
+ ++I;
+ }
+}
+
+void TargetPassBuilder::addPrinterPassesAndFreeMachineFunction(
+ ModulePassManager &MPM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
+ CodeGenFileType FileType, MCContext &Ctx) {
+
+ PassList &Passes = MPM.Passes;
+ PassList::iterator LastModulePassInsertPoint =
+ llvm::find_if(llvm::reverse(Passes), [](PassWrapper &PW) {
+ return PW.InternalPass.index() == 0; // The last module pass
+ }).base();
+
+ // FIXME: CodeGenFileType here is not enough, we need an output type for MC
+ if (TargetPassConfig::willCompleteCodeGenPipeline()) {
+ ModulePassManager AsmPrinterPM;
+ FunctionPassManager FPM;
+ // MachineFunctionPassManager MFPM;
+ // TODO: Insert asm printer initialization pass at LastModulePassInsertPoint
+ // TODO: Insert asm printer
+ FPM.addPass(InvalidateAnalysisPass<MachineFunctionAnalysis>());
+ // TODO: Add asm printer finalization pass.
+ if (CGPBO.RequiresCodeGenSCCOrder)
+ AsmPrinterPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
+ createCGSCCToFunctionPassAdaptor(std::move(FPM))));
+ else
+ AsmPrinterPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ MPM.addPass(std::move(AsmPrinterPM));
+ } else {
+ Passes.insert(LastModulePassInsertPoint,
+ PassWrapper(PrintMIRPreparePass(Out)));
+ FunctionPassManager FPM;
+ MachineFunctionPassManager MFPM;
+ MFPM.addPass(PrintMIRPass(Out));
+ FPM.addPass(createFunctionToMachineFunctionPassAdaptor(std::move(MFPM)));
+ FPM.addPass(InvalidateAnalysisPass<MachineFunctionAnalysis>());
+ if (CGPBO.RequiresCodeGenSCCOrder)
+ MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
+ createCGSCCToFunctionPassAdaptor(std::move(FPM))));
+ else
+ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ }
+}
+
+llvm::ModulePassManager
+TargetPassBuilder::constructRealPassManager(ModulePassManager &&MPMW) {
+ llvm::ModulePassManager MPM;
+ llvm::FunctionPassManager FPM;
+ llvm::LoopPassManager LPM;
+ llvm::MachineFunctionPassManager MFPM;
+
+ std::stack<size_t> S({0});
+ bool InCGSCC = false, LastInCGSCC = false;
+ for (auto &P : MPMW.Passes) {
+ auto &PMVar = P.InternalPass;
+ std::visit(
+ [&](auto &&PM) {
+ if (P.InCGSCC)
+ InCGSCC = true;
+ size_t VarIdx = PMVar.index();
+ while (VarIdx < S.top()) {
+ switch (S.top()) {
+ case 3:
+ if (!MFPM.isEmpty())
+ FPM.addPass(llvm::createFunctionToMachineFunctionPassAdaptor(
+ std::move(MFPM)));
+ MFPM = llvm::MachineFunctionPassManager();
+ S.pop();
+ break;
+ case 2:
+ if (!LPM.isEmpty())
+ FPM.addPass(llvm::createFunctionToLoopPassAdaptor(
+ std::move(LPM), /*UseMemorySSA=*/true));
+ LPM = llvm::LoopPassManager();
+ S.pop();
+ break;
+ case 1:
+ if (!FPM.isEmpty()) {
+ if (CGPBO.RequiresCodeGenSCCOrder && LastInCGSCC) {
+ InCGSCC = false;
+ MPM.addPass(llvm::createModuleToPostOrderCGSCCPassAdaptor(
+ llvm::createCGSCCToFunctionPassAdaptor(std::move(FPM))));
+ } else {
+ MPM.addPass(
+ llvm::createModuleToFunctionPassAdaptor(std::move(FPM)));
+ }
+ }
+ FPM = llvm::FunctionPassManager();
+ S.pop();
+ break;
+ case 0:
+ break;
+ default:
+ llvm_unreachable("Invalid pass manager type!");
+ }
+ }
+ while (VarIdx > S.top())
+ S.push(S.top() + 1);
+
+ if constexpr (std::is_same_v<std::remove_reference_t<decltype(PM)>,
+ llvm::ModulePassManager>)
+ MPM.addPass(std::move(PM));
+ if constexpr (std::is_same_v<std::remove_reference_t<decltype(PM)>,
+ llvm::FunctionPassManager>) {
+ if (!LastInCGSCC && P.InCGSCC) {
+ MPM.addPass(
+ llvm::createModuleToFunctionPassAdaptor(std::move(FPM)));
+ FPM = llvm::FunctionPassManager();
+ }
+ FPM.addPass(std::move(PM));
+ }
+ if constexpr (std::is_same_v<std::remove_reference_t<decltype(PM)>,
+ llvm::LoopPassManager>)
+ LPM.addPass(std::move(PM));
+ if constexpr (std::is_same_v<std::remove_reference_t<decltype(PM)>,
+ llvm::MachineFunctionPassManager>)
+ MFPM.addPass(std::move(PM));
+
+ LastInCGSCC = P.InCGSCC;
+ },
+ PMVar);
+ }
+
+ if (!MFPM.isEmpty())
+ FPM.addPass(
+ llvm::createFunctionToMachineFunctionPassAdaptor(std::move(MFPM)));
+ if (!LPM.isEmpty())
+ FPM.addPass(llvm::createFunctionToLoopPassAdaptor(std::move(LPM),
+ /*UseMemorySSA=*/true));
+ if (!FPM.isEmpty()) {
+ if (CGPBO.RequiresCodeGenSCCOrder)
+ MPM.addPass(llvm::createModuleToPostOrderCGSCCPassAdaptor(
+ llvm::createCGSCCToFunctionPassAdaptor(std::move(FPM))));
+ else
+ MPM.addPass(llvm::createModuleToFunctionPassAdaptor(std::move(FPM)));
+ }
+
+ return MPM;
+}
+
+void TargetPassBuilder::invokeInjectionCallbacks(ModulePassManager &MPM) const {
+ PassList &Passes = MPM.Passes;
+ for (auto I = Passes.begin(), E = Passes.end(); I != E; ++I)
+ for (auto &C : InjectionCallbacks)
+ I = C(Passes, I);
+}
+
+void TargetPassBuilder::anchor() {}
diff --git a/llvm/unittests/CodeGen/CMakeLists.txt b/llvm/unittests/CodeGen/CMakeLists.txt
index 709017380fa4e..dc1ffe5b26121 100644
--- a/llvm/unittests/CodeGen/CMakeLists.txt
+++ b/llvm/unittests/CodeGen/CMakeLists.txt
@@ -50,6 +50,7 @@ add_llvm_unittest(CodeGenTests
SelectionDAGPatternMatchTest.cpp
TypeTraitsTest.cpp
TargetOptionsTest.cpp
+ TargetPassBuilderTest.cpp
TestAsmPrinter.cpp
X86MCInstLowerTest.cpp
)
diff --git a/llvm/unittests/CodeGen/TargetPassBuilderTest.cpp b/llvm/unittests/CodeGen/TargetPassBuilderTest.cpp
new file mode 100644
index 0000000000000..75353c66e7fc6
--- /dev/null
+++ b/llvm/unittests/CodeGen/TargetPassBuilderTest.cpp
@@ -0,0 +1,175 @@
+//===- TargetPassBuilderTest.cpp ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Passes/TargetPassBuilder.h"
+#include "llvm/CodeGen/CodeGenTargetMachineImpl.h"
+#include "llvm/CodeGen/ExpandFp.h"
+#include "llvm/CodeGen/ExpandLargeDivRem.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachinePassManager.h"
+#include "llvm/CodeGen/PreISelIntrinsicLowering.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
+#include "llvm/CodeGen/TargetFrameLowering.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/CodeGen/TargetLowering.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
+#include "llvm/CodeGen/TargetRegisterInfo.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Target/TargetMachine.h"
+#include "gtest/gtest.h"
+#include <cassert>
+
+using namespace llvm;
+
+namespace {
+
+class TestTargetMachine : public CodeGenTargetMachineImpl {
+public:
+ TestTargetMachine()
+ : CodeGenTargetMachineImpl(Target(), "", Triple(""), "", "",
+ TargetOptions(), Reloc::Static,
+ CodeModel::Small, CodeGenOptLevel::Default) {
+ AsmInfo.reset(new MCAsmInfo());
+ }
+
+ ~TestTargetMachine() override = default;
+};
+
+TestTargetMachine *createTargetMachine() {
+ static TestTargetMachine TestTM;
+ return &TestTM;
+}
+
+template <size_t Tag, typename MemberPtrT> struct PrivateVisitor {
+ inline static MemberPtrT Ptr;
+};
+template <size_t Tag, auto MemberPtrV> struct PrivateVisitorHelper {
+ struct Assigner {
+ Assigner() { PrivateVisitor<Tag, decltype(MemberPtrV)>::Ptr = MemberPtrV; }
+ };
+ inline static Assigner A;
+};
+
+template <size_t Tag, typename MemberPtrT>
+MemberPtrT PrivatePtr = PrivateVisitor<Tag, MemberPtrT>::Ptr;
+
+struct TestDAGISelPass : public PassInfoMixin<TestDAGISelPass> {
+ PreservedAnalyses run(MachineFunction &, MachineFunctionAnalysisManager &) {
+ return PreservedAnalyses::all();
+ }
+};
+
+class TestPassBuilder : public TargetPassBuilder {
+public:
+ using TargetPassBuilder::ModulePassManager;
+
+ TestPassBuilder(PassBuilder &PB) : TargetPassBuilder(PB) {
+
+ registerSelectionDAGISelPass([]() { return TestDAGISelPass(); });
+ CGPBO.RequiresCodeGenSCCOrder = true;
+
+ injectBefore<PreISelIntrinsicLoweringPass>([]() {
+ ModulePassManager MPM;
+ MPM.addPass(NoOpModulePass());
+ return MPM;
+ });
+
+ injectBefore<ExpandFpPass, ModulePassManager>([] {
+ ModulePassManager MPM;
+ MPM.addPass(NoOpModulePass());
+ return MPM;
+ });
+ }
+};
+
+template struct PrivateVisitorHelper<
+ 0, &TargetPassBuilder::buildCodeGenIRPipeline>;
+template struct PrivateVisitorHelper<
+ 0, &TargetPassBuilder::invokeInjectionCallbacks>;
+template struct PrivateVisitorHelper<
+ 0, &TargetPassBuilder::ModulePassManager::Passes>;
+
+TEST(TargetPassBuilder, Basic) {
+ TargetMachine *TM = createTargetMachine();
+ PassInstrumentationCallbacks PIC;
+ PassBuilder PB(TM, PipelineTuningOptions(), std::nullopt, &PIC);
+ ModulePassManager PM;
+ LoopAnalysisManager LAM;
+ FunctionAnalysisManager FAM;
+ CGSCCAnalysisManager CGAM;
+ ModuleAnalysisManager AM;
+
+ /// Register builtin analyses and cross-register the analysis proxies
+ PB.registerModuleAnalyses(AM);
+ PB.registerCGSCCAnalyses(CGAM);
+ PB.registerFunctionAnalyses(FAM);
+ PB.registerLoopAnalyses(LAM);
+ PB.crossRegisterProxies(LAM, FAM, CGAM, AM);
+
+ TestPassBuilder TPB(PB);
+ using PassList = TargetPassBuilder::PassList;
+ auto MPM = (TPB.*PrivatePtr<0, TestPassBuilder::ModulePassManager (
+ TargetPassBuilder::*)()>)();
+ auto &Passes =
+ MPM.*PrivatePtr<0, PassList TestPassBuilder::ModulePassManager::*>;
+ (TPB.*PrivatePtr<0, void (TargetPassBuilder::*)(
+ TestPassBuilder::ModulePassManager &)
+ const>)(MPM); // invokeInjectionCallbacks
+ auto B = Passes.begin();
+ EXPECT_EQ(B->Name, NoOpModulePass::name());
+ ++B, ++B, ++B;
+ EXPECT_EQ(B->Name, NoOpModulePass::name());
+}
+
+template struct PrivateVisitorHelper<1, &TargetPassBuilder::filtPassList>;
+
+TEST(TargetPassBuilder, StartStop) {
+ const char *Argv[] = {"CodeGenTests",
+ "--start-after=pre-isel-intrinsic-lowering",
+ "--stop-before=no-op-module,2"};
+ cl::ParseCommandLineOptions(std::size(Argv), Argv);
+
+ TargetMachine *TM = createTargetMachine();
+ PassInstrumentationCallbacks PIC;
+ PassBuilder PB(TM, PipelineTuningOptions(), std::nullopt, &PIC);
+ ModulePassManager PM;
+ LoopAnalysisManager LAM;
+ FunctionAnalysisManager FAM;
+ CGSCCAnalysisManager CGAM;
+ ModuleAnalysisManager AM;
+
+ /// Register builtin analyses and cross-register the analysis proxies
+ PB.registerModuleAnalyses(AM);
+ PB.registerCGSCCAnalyses(CGAM);
+ PB.registerFunctionAnalyses(FAM);
+ PB.registerLoopAnalyses(LAM);
+ PB.crossRegisterProxies(LAM, FAM, CGAM, AM);
+
+ using PassList = TargetPassBuilder::PassList;
+
+ TestPassBuilder TPB(PB);
+ auto MPM = (TPB.*PrivatePtr<0, TestPassBuilder::ModulePassManager (
+ TargetPassBuilder::*)()>)();
+ auto &Passes =
+ MPM.*PrivatePtr<0, PassList TestPassBuilder::ModulePassManager::*>;
+ (TPB.*PrivatePtr<0, void (TargetPassBuilder::*)(
+ TestPassBuilder::ModulePassManager &)
+ const>)(MPM); // invokeInjectionCallbacks
+ (TPB.*PrivatePtr<1, void (TargetPassBuilder::*)(
+ TestPassBuilder::ModulePassManager &)
+ const>)(MPM); // filtPassList
+ EXPECT_EQ(Passes.size(), 1u);
+ EXPECT_EQ(Passes.begin()->Name, ExpandLargeDivRemPass::name());
+}
+} // namespace
>From 751ce82fc7ec2287142938c0902f8186276bfe5c Mon Sep 17 00:00:00 2001
From: PaperChalice <liujunchang97 at outlook.com>
Date: Thu, 13 Nov 2025 18:50:24 +0800
Subject: [PATCH 2/2] Use Target prefix rather than shadowing, also provide
---
llvm/include/llvm/Passes/TargetPassBuilder.h | 556 +++++++++++++-----
llvm/lib/Passes/TargetPassBuilder.cpp | 268 +++++----
.../CodeGen/TargetPassBuilderTest.cpp | 60 +-
3 files changed, 569 insertions(+), 315 deletions(-)
diff --git a/llvm/include/llvm/Passes/TargetPassBuilder.h b/llvm/include/llvm/Passes/TargetPassBuilder.h
index efd25db53208e..9763e71c366bb 100644
--- a/llvm/include/llvm/Passes/TargetPassBuilder.h
+++ b/llvm/include/llvm/Passes/TargetPassBuilder.h
@@ -15,9 +15,9 @@
#ifndef LLVM_PASSES_TARGETPASSBUILDER_H
#define LLVM_PASSES_TARGETPASSBUILDER_H
+#include "llvm/ADT/STLForwardCompat.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSet.h"
-#include "llvm/ADT/identity.h"
#include "llvm/Analysis/CGSCCPassManager.h"
#include "llvm/CodeGen/MachinePassManager.h"
#include "llvm/Target/CGPassBuilderOption.h"
@@ -35,102 +35,321 @@ class PassBuilder;
class TargetMachine;
class SelectionDAGISel;
-/// @brief Build CodeGen pipeline
-///
-class TargetPassBuilder {
+namespace detail {
+
+struct InjectionPointMixin {};
+
+template <typename PassT, typename IRUnitT>
+using HasRunOnIRUnit = decltype(std::declval<PassT>().run(
+ std::declval<IRUnitT &>(), std::declval<AnalysisManager<IRUnitT> &>()));
+template <typename PassT>
+using HasRunOnLoop = decltype(std::declval<PassT>().run(
+ std::declval<Loop &>(), std::declval<LoopAnalysisManager &>(),
+ std::declval<LoopStandardAnalysisResults &>(),
+ std::declval<LPMUpdater &>()));
+template <typename PassT>
+static constexpr bool isModulePass =
+ is_detected<HasRunOnIRUnit, PassT, Module>::value;
+template <typename PassT>
+static constexpr bool isFunctionPass =
+ is_detected<HasRunOnIRUnit, PassT, Function>::value;
+template <typename PassT>
+static constexpr bool isLoopPass = is_detected<HasRunOnLoop, PassT>::value;
+template <typename PassT>
+static constexpr bool isMachineFunctionPass =
+ is_detected<HasRunOnIRUnit, PassT, MachineFunction>::value;
+
+struct PassWrapper {
+ StringRef Name;
+ bool InCGSCC;
+ bool IsInjectionPoint;
+
+ template <typename PassT,
+ typename = std::enable_if_t<
+ isModulePass<PassT> || isFunctionPass<PassT> ||
+ isLoopPass<PassT> || isMachineFunctionPass<PassT>>>
+ PassWrapper(PassT &&P, bool InCGSCC = false)
+ : Name(std::remove_reference_t<PassT>::name()), InCGSCC(InCGSCC) {
+ if constexpr (isModulePass<PassT>) {
+ Ctor.emplace<llvm::unique_function<void(ModulePassManager &)>>(
+ [P = std::forward<PassT>(P)](ModulePassManager &PM) mutable {
+ PM.addPass(std::move(P));
+ });
+ } else if constexpr (isFunctionPass<PassT>) {
+ Ctor.emplace<llvm::unique_function<void(FunctionPassManager &)>>(
+ [P = std::forward<PassT>(P)](FunctionPassManager &PM) mutable {
+ PM.addPass(std::move(P));
+ });
+ } else if constexpr (isLoopPass<PassT>) {
+ Ctor.emplace<llvm::unique_function<void(LoopPassManager &)>>(
+ [P = std::forward<PassT>(P)](LoopPassManager &PM) mutable {
+ PM.addPass(std::move(P));
+ });
+ } else if constexpr (isMachineFunctionPass<PassT>) {
+ Ctor.emplace<llvm::unique_function<void(MachineFunctionPassManager &)>>(
+ [P = std::forward<PassT>(P)](MachineFunctionPassManager &PM) mutable {
+ PM.addPass(std::move(P));
+ });
+ }
+ IsInjectionPoint =
+ std::is_base_of_v<InjectionPointMixin, std::remove_reference_t<PassT>>;
+ }
+
+ std::variant<llvm::unique_function<void(ModulePassManager &)>,
+ llvm::unique_function<void(FunctionPassManager &)>,
+ llvm::unique_function<void(LoopPassManager &)>,
+ llvm::unique_function<void(MachineFunctionPassManager &)>>
+ Ctor;
+};
+} // namespace detail
+
+class TargetMachineFunctionPassManager {
+ friend class TargetFunctionPassManager;
+ friend class TargetPassBuilder;
+
public:
- TargetPassBuilder(PassBuilder &PB);
+ template <typename PassT>
+ TargetMachineFunctionPassManager &addPass(PassT &&P) & {
+ static_assert(detail::isMachineFunctionPass<PassT>,
+ "Not a machine function pass!");
+ Passes.emplace_back(std::forward<PassT>(P));
+ return *this;
+ }
- virtual ~TargetPassBuilder() = default;
+ template <typename PassT>
+ TargetMachineFunctionPassManager &&addPass(PassT &&P) && {
+ static_assert(detail::isMachineFunctionPass<PassT>,
+ "Not a machine function pass!");
+ Passes.emplace_back(std::forward<PassT>(P));
+ return std::move(*this);
+ }
- // TODO: Add necessary parameters once AsmPrinter is ported to new pass
- // manager.
- llvm::ModulePassManager buildPipeline(raw_pwrite_stream &Out,
- raw_pwrite_stream *DwoOut,
- CodeGenFileType FileType,
- MCContext &Ctx);
+ TargetMachineFunctionPassManager &
+ addPass(TargetMachineFunctionPassManager &&PM) & {
+ for (auto &P : PM.Passes)
+ Passes.push_back(std::move(P));
+ PM.Passes.clear();
+ return *this;
+ }
+
+ TargetMachineFunctionPassManager &&
+ addPass(TargetMachineFunctionPassManager &&PM) && {
+ for (auto &P : PM.Passes)
+ Passes.push_back(std::move(P));
+ PM.Passes.clear();
+ return std::move(*this);
+ }
private:
- struct PassWrapper {
- StringRef Name;
- std::variant<llvm::ModulePassManager, llvm::FunctionPassManager,
- llvm::LoopPassManager, llvm::MachineFunctionPassManager>
- InternalPass;
- bool InCGSCC = false;
-
- template <typename PassManagerT>
- PassWrapper(StringRef Name, PassManagerT &&PM)
- : Name(Name), InternalPass(std::forward<PassManagerT>(PM)) {}
-
- template <typename PassT> PassWrapper(PassT &&P) : Name(PassT::name()) {
- // FIXME: This can't handle the case when `run` is template.
- if constexpr (isModulePass<PassT>) {
- llvm::ModulePassManager MPM;
- MPM.addPass(std::forward<PassT>(P));
- InternalPass.emplace<llvm::ModulePassManager>(std::move(MPM));
- } else if constexpr (isFunctionPass<PassT>) {
- llvm::FunctionPassManager FPM;
- FPM.addPass(std::forward<PassT>(P));
- InternalPass.emplace<llvm::FunctionPassManager>(std::move(FPM));
- } else {
- static_assert(isMachineFunctionPass<PassT>, "Invalid pass type!");
- llvm::MachineFunctionPassManager MFPM;
- MFPM.addPass(std::forward<PassT>(P));
- InternalPass.emplace<llvm::MachineFunctionPassManager>(std::move(MFPM));
- }
- }
- };
+ std::list<detail::PassWrapper> Passes;
+};
+
+class TargetLoopPassManager {
+ friend class TargetFunctionPassManager;
+ friend class TargetPassBuilder;
public:
- using PassList = std::list<PassWrapper>;
+ template <typename PassT> TargetLoopPassManager &addPass(PassT &&P) & {
+ static_assert(detail::isLoopPass<PassT>, "Not a loop pass!");
+ Passes.emplace_back(std::forward<PassT>(P));
+ return *this;
+ }
+
+ template <typename PassT> TargetLoopPassManager &&addPass(PassT &&P) && {
+ static_assert(detail::isLoopPass<PassT>, "Not a loop pass!");
+ Passes.emplace_back(std::forward<PassT>(P));
+ return std::move(*this);
+ }
+
+ TargetLoopPassManager &addPass(TargetLoopPassManager &&PM) & {
+ for (auto &P : PM.Passes)
+ Passes.push_back(std::move(P));
+ PM.Passes.clear();
+ return *this;
+ }
+
+ TargetLoopPassManager &&addPass(TargetLoopPassManager &&PM) && {
+ for (auto &P : PM.Passes)
+ Passes.push_back(std::move(P));
+ PM.Passes.clear();
+ return std::move(*this);
+ }
private:
- template <typename InternalPassT> struct AdaptorWrapper : InternalPassT {
- using InternalPassT::Passes;
- };
+ std::list<detail::PassWrapper> Passes;
+};
- template <typename PassManagerT, typename InternalPassT = void>
- class PassManagerWrapper {
- friend class TargetPassBuilder;
-
- public:
- bool isEmpty() const { return Passes.empty(); }
-
- template <typename PassT> void addPass(PassT &&P) {
- PassManagerT PM;
- PM.addPass(std::forward<PassT>(P));
- // Injection point doesn't add real pass.
- if constexpr (std::is_base_of_v<InjectionPointMixin, PassT>)
- PM = PassManagerT();
- PassWrapper PW(PassT::name(), std::move(PM));
- Passes.push_back(std::move(PW));
- }
+class TargetFunctionPassManager {
+ friend class TargetModulePassManager;
+ friend class TargetPassBuilder;
+
+public:
+ template <typename PassT> TargetFunctionPassManager &addPass(PassT &&P) & {
+ static_assert(detail::isFunctionPass<PassT>, "Not a function pass!");
+ Passes.emplace_back(std::forward<PassT>(P));
+ return *this;
+ }
+
+ template <typename PassT> TargetFunctionPassManager &addPass(PassT &&P) && {
+ static_assert(detail::isFunctionPass<PassT>, "Not a function pass!");
+ Passes.emplace_back(std::forward<PassT>(P));
+ return *this;
+ }
+
+ TargetFunctionPassManager &addPass(TargetFunctionPassManager &&PM) & {
+ for (auto &P : PM.Passes)
+ Passes.push_back(std::move(P));
+ PM.Passes.clear();
+ return *this;
+ }
+
+ TargetFunctionPassManager &&addPass(TargetFunctionPassManager &&PM) && {
+ for (auto &P : PM.Passes)
+ Passes.push_back(std::move(P));
+ PM.Passes.clear();
+ return std::move(*this);
+ }
+
+ template <typename PassT>
+ TargetFunctionPassManager &addLoopPass(PassT &&P) & {
+ static_assert(detail::isLoopPass<PassT>, "Not a loop pass!");
+ Passes.emplace_back(std::forward<PassT>(P));
+ return *this;
+ }
+
+ template <typename PassT>
+ TargetFunctionPassManager &&addLoopPass(PassT &&P) && {
+ static_assert(detail::isLoopPass<PassT>, "Not a loop pass!");
+ Passes.emplace_back(std::forward<PassT>(P));
+ return std::move(*this);
+ }
+
+ TargetFunctionPassManager &addLoopPass(TargetLoopPassManager &&PM) & {
+ for (auto &P : PM.Passes)
+ Passes.push_back(std::move(P));
+ PM.Passes.clear();
+ return *this;
+ }
+
+ TargetFunctionPassManager &&addLoopPass(TargetLoopPassManager &&PM) && {
+ for (auto &P : PM.Passes)
+ Passes.push_back(std::move(P));
+ PM.Passes.clear();
+ return std::move(*this);
+ }
+
+ template <typename PassT>
+ TargetFunctionPassManager &addMachineFunctionPass(PassT &&P) & {
+ static_assert(detail::isMachineFunctionPass<PassT>,
+ "Not a machine function pass!");
+ Passes.emplace_back(std::forward<PassT>(P));
+ return *this;
+ }
+
+ template <typename PassT>
+ TargetFunctionPassManager &&addMachineFunctionPass(PassT &&P) && {
+ static_assert(detail::isMachineFunctionPass<PassT>,
+ "Not a machine function pass!");
+ Passes.emplace_back(std::forward<PassT>(P));
+ return std::move(*this);
+ }
+
+ TargetFunctionPassManager &
+ addMachineFunctionPass(TargetMachineFunctionPassManager &&PM) & {
+ for (auto &P : PM.Passes)
+ Passes.push_back(std::move(P));
+ PM.Passes.clear();
+ return *this;
+ }
+
+ TargetFunctionPassManager &&
+ addMachineFunctionPass(TargetMachineFunctionPassManager &&PM) && {
+ for (auto &P : PM.Passes)
+ Passes.push_back(std::move(P));
+ PM.Passes.clear();
+ return std::move(*this);
+ }
+
+private:
+ std::list<detail::PassWrapper> Passes;
+};
+
+class TargetModulePassManager {
+ friend class TargetPassBuilder;
+
+public:
+ template <typename PassT> TargetModulePassManager &addPass(PassT &&P) {
+ static_assert(detail::isModulePass<PassT>, "Not a module pass!");
+ Passes.emplace_back(std::forward<PassT>(P));
+ return *this;
+ }
+
+ TargetModulePassManager &addPass(TargetModulePassManager &&PM) {
+ for (auto &P : PM.Passes)
+ Passes.push_back(std::move(P));
+ PM.Passes.clear();
+ return *this;
+ }
+
+ template <typename PassT>
+ TargetModulePassManager &addFunctionPass(PassT &&P) {
+ static_assert(detail::isFunctionPass<PassT>, "Not a function pass!");
+ Passes.emplace_back(std::forward<PassT>(P));
+ return *this;
+ }
+
+ TargetModulePassManager &addFunctionPass(TargetFunctionPassManager &&PM) {
+ for (auto &P : PM.Passes)
+ Passes.push_back(std::move(P));
+ PM.Passes.clear();
+ return *this;
+ }
- void addPass(PassManagerWrapper &&PM) {
- for (auto &P : PM.Passes)
- Passes.push_back(std::move(P));
+ template <typename PassT>
+ TargetModulePassManager &addFunctionPassWithPostOrderCGSCC(PassT &&P) {
+ static_assert(detail::isFunctionPass<PassT>, "Not a function pass!");
+ Passes.emplace_back(std::forward<PassT>(P), /*InCGSCC=*/true);
+ return *this;
+ }
+
+ TargetModulePassManager &
+ addFunctionPassWithPostOrderCGSCC(TargetFunctionPassManager &&PM) & {
+ for (auto &P : PM.Passes) {
+ P.InCGSCC = true;
+ Passes.push_back(std::move(P));
}
+ PM.Passes.clear();
+ return *this;
+ }
- void addPass(AdaptorWrapper<InternalPassT> &&Adaptor) {
- for (auto &P : Adaptor.Passes)
- Passes.push_back(std::move(P));
+ TargetModulePassManager &&
+ addFunctionPassWithPostOrderCGSCC(TargetFunctionPassManager &&PM) && {
+ for (auto &P : PM.Passes) {
+ P.InCGSCC = true;
+ Passes.push_back(std::move(P));
}
+ PM.Passes.clear();
+ return std::move(*this);
+ }
- void addPass(llvm::ModulePassManager &&) = delete;
- void addPass(llvm::FunctionPassManager &&) = delete;
- void addPass(llvm::LoopPassManager &&) = delete;
- void addPass(llvm::MachineFunctionPassManager &&) = delete;
+private:
+ std::list<detail::PassWrapper> Passes;
+};
- private:
- PassList Passes;
- };
+/// @brief Build CodeGen pipeline
+///
+class TargetPassBuilder {
+public:
+ TargetPassBuilder(PassBuilder &PB);
- template <typename NestedPassManagerT, typename PassT>
- AdaptorWrapper<NestedPassManagerT> createPassAdaptor(PassT &&P) {
- AdaptorWrapper<NestedPassManagerT> Adaptor;
- Adaptor.addPass(std::forward<PassT>(P));
- return Adaptor;
- }
+ virtual ~TargetPassBuilder() = default;
+
+ // TODO: Add necessary parameters once AsmPrinter is ported to new pass
+ // manager.
+ llvm::ModulePassManager buildPipeline(raw_pwrite_stream &Out,
+ raw_pwrite_stream *DwoOut,
+ CodeGenFileType FileType,
+ MCContext &Ctx);
private:
template <typename PassT, typename IRUnitT>
@@ -146,83 +365,77 @@ class TargetPassBuilder {
static constexpr bool isMachineFunctionPass =
is_detected<HasRunOnIRUnit, PassT, MachineFunction>::value;
-protected:
- // Hijack real pass managers intentionally.
- using MachineFunctionPassManager =
- PassManagerWrapper<llvm::MachineFunctionPassManager>;
- using FunctionPassManager =
- PassManagerWrapper<llvm::FunctionPassManager, MachineFunctionPassManager>;
- using ModulePassManager =
- PassManagerWrapper<llvm::ModulePassManager, FunctionPassManager>;
-
- struct CGSCCAdaptorWrapper : AdaptorWrapper<FunctionPassManager> {};
+ using PassList = std::list<detail::PassWrapper>;
protected:
- template <typename FunctionPassT>
- AdaptorWrapper<FunctionPassManager>
- createModuleToFunctionPassAdaptor(FunctionPassT &&P) {
- return createPassAdaptor<FunctionPassManager>(
- std::forward<FunctionPassT>(P));
- }
-
- AdaptorWrapper<FunctionPassManager>
- createModuleToPostOrderCGSCCPassAdaptor(CGSCCAdaptorWrapper &&PM) {
- AdaptorWrapper<FunctionPassManager> AW;
- AW.Passes = std::move(PM.Passes);
- return AW;
- }
-
- template <typename FunctionPassT>
- CGSCCAdaptorWrapper createCGSCCToFunctionPassAdaptor(FunctionPassT &&PM) {
- for (auto &P : PM.Passes)
- P.InCGSCC = true;
- CGSCCAdaptorWrapper AW;
- AW.Passes = std::move(PM.Passes);
- return AW;
- }
-
- template <typename MachineFunctionPassT>
- AdaptorWrapper<MachineFunctionPassManager>
- createFunctionToMachineFunctionPassAdaptor(MachineFunctionPassT &&P) {
- return createPassAdaptor<MachineFunctionPassManager>(
- std::forward<MachineFunctionPassT>(P));
- }
+ virtual void registerCallbacks() = 0;
- struct InjectionPointMixin {};
- // When run is template, injectBefore can't recognize pass type correctly.
- struct DummyFunctionPassBase : InjectionPointMixin {
+ struct DummyFunctionPassMixin {
PreservedAnalyses run(Function &, FunctionAnalysisManager &) {
- return PreservedAnalyses();
+ return PreservedAnalyses::all();
}
};
- struct DummyMachineFunctionPassBase : InjectionPointMixin {
+ struct DummyMachineFunctionPassMixin {
PreservedAnalyses run(MachineFunction &, MachineFunctionAnalysisManager &) {
- return PreservedAnalyses();
+ return PreservedAnalyses::all();
}
};
- struct PreISel : PassInfoMixin<PreISel>, DummyFunctionPassBase {};
- struct PostBBSections : PassInfoMixin<PostBBSections>,
- DummyMachineFunctionPassBase {};
- struct PreEmit : PassInfoMixin<PreEmit>, DummyMachineFunctionPassBase {};
-protected:
+ struct PreISelInjectionPoint : PassInfoMixin<PreISelInjectionPoint>,
+ DummyFunctionPassMixin,
+ detail::InjectionPointMixin {};
+
+ struct PostBBSectionsInjectionPoint
+ : PassInfoMixin<PostBBSectionsInjectionPoint>,
+ DummyMachineFunctionPassMixin,
+ detail::InjectionPointMixin {};
+
+ struct PreEmitInjectionPoint : PassInfoMixin<PreEmitInjectionPoint>,
+ DummyMachineFunctionPassMixin,
+ detail::InjectionPointMixin {};
+
+ struct ILPOptsInjectionPoint : PassInfoMixin<ILPOptsInjectionPoint>,
+ DummyMachineFunctionPassMixin,
+ detail::InjectionPointMixin {};
+
PassBuilder &PB;
TargetMachine *TM;
CodeGenOptLevel OptLevel;
CGPassBuilderOption CGPBO = getCGPassBuilderOption();
- /// @brief The only method to extend pipeline
+ /// @brief Add custom passes at injection point PassT
+ /// @tparam PassT The injection point
+ /// @tparam This is the recommended approach to extend the pass pipeline.
+ /// PassManagerT Returned pass manager, by default it depends on the injection
+ /// point.
+ /// @param F Callback to build the pipeline.
+ template <
+ typename PassT,
+ typename PassManagerT = std::conditional_t<
+ isModulePass<PassT>, TargetModulePassManager,
+ std::conditional_t<isFunctionPass<PassT>, TargetFunctionPassManager,
+ TargetMachineFunctionPassManager>>>
+ void injectAt(
+ typename llvm::type_identity<std::function<PassManagerT()>>::type F) {
+ static_assert(std::is_base_of_v<detail::InjectionPointMixin, PassT>,
+ "Only injection points are supported!");
+ injectBefore<PassT, PassManagerT>(F);
+ }
+
+ /// @brief Add custom passes before PassT
/// @tparam PassT The injection point
/// @tparam PassManagerT Returned pass manager, by default it depends on the
+ /// injection point. Use this method only when there is no appropriate
/// injection point.
/// @param F Callback to build the pipeline.
- template <typename PassT,
- typename PassManagerT = std::conditional_t<
- isModulePass<PassT>, ModulePassManager,
- std::conditional_t<isFunctionPass<PassT>, FunctionPassManager,
- MachineFunctionPassManager>>>
+ template <
+ typename PassT,
+ typename PassManagerT = std::conditional_t<
+ isModulePass<PassT>, TargetModulePassManager,
+ std::conditional_t<isFunctionPass<PassT>, TargetFunctionPassManager,
+ TargetMachineFunctionPassManager>>>
void injectBefore(
- typename llvm::identity<std::function<PassManagerT()>>::argument_type F) {
+ typename llvm::type_identity<std::function<PassManagerT()>>::type F) {
InjectionCallbacks.push_back(
[Accessed = false, F](PassList &Passes, PassList::iterator I) mutable {
if (Accessed)
@@ -236,12 +449,40 @@ class TargetPassBuilder {
});
}
+ /// @brief Add custom passes after PassT
+ /// @tparam PassT The injection point
+ /// @tparam PassManagerT Returned pass manager, by default it depends on the
+ /// injection point. Use this method only when there is no appropriate
+ /// injection point.
+ /// @param F Callback to build the pipeline.
+ template <
+ typename PassT,
+ typename PassManagerT = std::conditional_t<
+ isModulePass<PassT>, TargetModulePassManager,
+ std::conditional_t<isFunctionPass<PassT>, TargetFunctionPassManager,
+ TargetMachineFunctionPassManager>>>
+ void injectAfter(
+ typename llvm::type_identity<std::function<PassManagerT()>>::type F) {
+ InjectionCallbacks.push_back(
+ [Accessed = false, F](PassList &Passes, PassList::iterator I) mutable {
+ if (Accessed)
+ return I;
+ if (PassT::name() != I->Name)
+ return I;
+ Accessed = true;
+ auto PMPasses = F().Passes;
+ auto NextI = std::next(I);
+ return Passes.insert(NextI, std::make_move_iterator(PMPasses.begin()),
+ std::make_move_iterator(PMPasses.end()));
+ });
+ }
+
/// @brief Register selection dag isel pass
/// @tparam BuilderFuncT
/// @param F A function returns a selection dag isel pass.
template <typename BuilderFuncT>
void registerSelectionDAGISelPass(BuilderFuncT F) {
- AddSelectionDAGISelPass = [=](MachineFunctionPassManager &MFPM) {
+ AddSelectionDAGISelPass = [=](TargetMachineFunctionPassManager &MFPM) {
using ResultT = std::invoke_result_t<BuilderFuncT>;
static_assert(isMachineFunctionPass<ResultT> &&
!std::is_same_v<MachineFunctionPassManager, ResultT>,
@@ -271,28 +512,29 @@ class TargetPassBuilder {
bool isPassEnabled(StringRef Name) const { return !isPassDisabled(Name); }
private:
- void buildCoreCodeGenPipeline(ModulePassManager &MPM);
+ void buildCoreCodeGenPipeline(TargetModulePassManager &MPM);
- ModulePassManager buildCodeGenIRPipeline();
+ TargetModulePassManager buildCodeGenIRPipeline();
/// Add passes that optimize machine instructions in SSA form.
- void addISelPasses(MachineFunctionPassManager &MFPM);
- void addMachineSSAOptimizationPasses(MachineFunctionPassManager &MFPM);
- void addRegAllocPipeline(MachineFunctionPassManager &MFPM);
- void addRegAllocPass(MachineFunctionPassManager &MFPM, bool Optimized);
- ModulePassManager buildCodeGenMIRPipeline();
+ void addISelPasses(TargetMachineFunctionPassManager &MFPM);
+ void addMachineSSAOptimizationPasses(TargetMachineFunctionPassManager &MFPM);
+ void addRegAllocPipeline(TargetMachineFunctionPassManager &MFPM);
+ void addRegAllocPass(TargetMachineFunctionPassManager &MFPM, bool Optimized);
+ TargetModulePassManager buildCodeGenMIRPipeline();
- void addExceptionHandlingPasses(FunctionPassManager &FPM);
+ void addExceptionHandlingPasses(TargetFunctionPassManager &FPM);
- void filtPassList(ModulePassManager &MPM) const;
+ void filterPassList(TargetModulePassManager &MPM) const;
- void addPrinterPassesAndFreeMachineFunction(ModulePassManager &MPM,
+ void addPrinterPassesAndFreeMachineFunction(TargetModulePassManager &MPM,
raw_pwrite_stream &Out,
raw_pwrite_stream *DwoOut,
CodeGenFileType FileType,
MCContext &Ctx);
- llvm::ModulePassManager constructRealPassManager(ModulePassManager &&MPMW);
+ ModulePassManager
+ constructRealPassManager(TargetModulePassManager &MPMW) const;
private:
virtual void anchor();
@@ -300,22 +542,12 @@ class TargetPassBuilder {
StringSet<> DisabedPasses;
std::vector<std::function<PassList::iterator(PassList &, PassList::iterator)>>
InjectionCallbacks;
- std::function<void(MachineFunctionPassManager &)> AddSelectionDAGISelPass;
-
- void invokeInjectionCallbacks(ModulePassManager &MPM) const;
+ std::function<void(TargetMachineFunctionPassManager &)>
+ AddSelectionDAGISelPass;
- // Only Loop Strength Reduction need this, shadow LoopPassManager
- // in future if it is necessary.
- template <typename PassT>
- void addLoopPass(FunctionPassManager &FPM, PassT &&P) {
- LoopPassManager LPM;
- LPM.addPass(std::forward<PassT>(P));
- FPM.Passes.push_back(PassWrapper(PassT::name(), std::move(LPM)));
- }
+ void invokeInjectionCallbacks(TargetModulePassManager &MPM) const;
};
-template <> struct TargetPassBuilder::AdaptorWrapper<void> {};
-
} // namespace llvm
#endif
diff --git a/llvm/lib/Passes/TargetPassBuilder.cpp b/llvm/lib/Passes/TargetPassBuilder.cpp
index 863b7a1cd6d7a..086c388eaa952 100644
--- a/llvm/lib/Passes/TargetPassBuilder.cpp
+++ b/llvm/lib/Passes/TargetPassBuilder.cpp
@@ -66,32 +66,32 @@ ModulePassManager TargetPassBuilder::buildPipeline(raw_pwrite_stream &Out,
raw_pwrite_stream *DwoOut,
CodeGenFileType FileType,
MCContext &Ctx) {
- ModulePassManager MPM;
+ TargetModulePassManager MPM;
buildCoreCodeGenPipeline(MPM);
invokeInjectionCallbacks(MPM);
- filtPassList(MPM);
+ filterPassList(MPM);
addPrinterPassesAndFreeMachineFunction(MPM, Out, DwoOut, FileType, Ctx);
- return constructRealPassManager(std::move(MPM));
+ return constructRealPassManager(MPM);
}
-void TargetPassBuilder::buildCoreCodeGenPipeline(ModulePassManager &MPM) {
+void TargetPassBuilder::buildCoreCodeGenPipeline(TargetModulePassManager &MPM) {
MPM.addPass(buildCodeGenIRPipeline());
- MachineFunctionPassManager MFPM;
+ TargetMachineFunctionPassManager MFPM;
+ TargetFunctionPassManager FPM;
addISelPasses(MFPM);
- MPM.addPass(createModuleToFunctionPassAdaptor(
- createFunctionToMachineFunctionPassAdaptor(std::move(MFPM))));
+ FPM.addMachineFunctionPass(std::move(MFPM));
+ MPM.addFunctionPass(std::move(FPM));
MPM.addPass(buildCodeGenMIRPipeline());
}
-TargetPassBuilder::ModulePassManager
-TargetPassBuilder::buildCodeGenIRPipeline() {
- ModulePassManager MPM;
+TargetModulePassManager TargetPassBuilder::buildCodeGenIRPipeline() {
+ TargetModulePassManager MPM;
if (TM->useEmulatedTLS())
MPM.addPass(LowerEmuTLSPass());
MPM.addPass(PreISelIntrinsicLoweringPass(TM));
- FunctionPassManager FPM;
- FPM.addPass(ExpandLargeDivRemPass(TM));
- FPM.addPass(ExpandFpPass(TM));
+ TargetFunctionPassManager FPM;
+ FPM.addPass(ExpandLargeDivRemPass(*TM));
+ FPM.addPass(ExpandFpPass(*TM, TM->getOptLevel()));
// Run loop strength reduction before anything else.
if (TM->getOptLevel() == CodeGenOptLevel::None) {
@@ -104,10 +104,12 @@ TargetPassBuilder::buildCodeGenIRPipeline() {
FPM.addPass(RequireAnalysisPass<BasicAA, Function>());
if (!CGPBO.DisableLSR) {
- addLoopPass(FPM, CanonicalizeFreezeInLoopsPass());
- addLoopPass(FPM, LoopStrengthReducePass());
+ TargetLoopPassManager LPM;
+ LPM.addPass(CanonicalizeFreezeInLoopsPass());
+ LPM.addPass(LoopStrengthReducePass());
if (CGPBO.EnableLoopTermFold)
- addLoopPass(FPM, LoopTermFoldPass());
+ LPM.addPass(LoopTermFoldPass());
+ FPM.addLoopPass(std::move(LPM));
}
// The MergeICmpsPass tries to create memcmp calls by grouping sequences
@@ -116,21 +118,21 @@ TargetPassBuilder::buildCodeGenIRPipeline() {
// enabled by a target lowering hook.
if (!CGPBO.DisableMergeICmps)
FPM.addPass(MergeICmpsPass());
- FPM.addPass(ExpandMemCmpPass(TM));
+ FPM.addPass(ExpandMemCmpPass(*TM));
}
// Run GC lowering passes for builtin collectors
FPM.addPass(GCLoweringPass());
- MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
- FPM = FunctionPassManager();
+ MPM.addFunctionPass(std::move(FPM));
+ FPM = TargetFunctionPassManager();
MPM.addPass(ShadowStackGCLoweringPass());
// PB.invokeGCLoweringEPCallbacks();
if (TM->getTargetTriple().isOSBinFormatMachO() &&
!CGPBO.DisableAtExitBasedGlobalDtorLowering) {
- MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
- FPM = FunctionPassManager();
- MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ MPM.addFunctionPass(std::move(FPM));
+ FPM = TargetFunctionPassManager();
+ MPM.addFunctionPass(std::move(FPM));
MPM.addPass(LowerGlobalDtorsPass());
}
@@ -161,26 +163,27 @@ TargetPassBuilder::buildCodeGenIRPipeline() {
// Convert conditional moves to conditional jumps when profitable.
if (OptLevel != CodeGenOptLevel::None && !CGPBO.DisableSelectOptimize)
- FPM.addPass(SelectOptimizePass(TM));
+ FPM.addPass(SelectOptimizePass(*TM));
- MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ MPM.addFunctionPass(std::move(FPM));
+ FPM = TargetFunctionPassManager();
if (CGPBO.EnableGlobalMergeFunc)
MPM.addPass(GlobalMergeFuncPass());
if (OptLevel != CodeGenOptLevel::None && !CGPBO.DisableCGP)
- FPM.addPass(CodeGenPreparePass(PB.TM));
+ FPM.addPass(CodeGenPreparePass(*TM));
addExceptionHandlingPasses(FPM);
// Add common passes that perform LLVM IR to IR transforms in preparation for
// instruction selection.
if (CGPBO.RequiresCodeGenSCCOrder) {
- MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
- FPM = FunctionPassManager();
+ MPM.addFunctionPass(std::move(FPM));
+ FPM = TargetFunctionPassManager();
}
// Now we need to force codegen to run according to the callgraph if target
// requires it.
- FPM.addPass(PreISel());
+ FPM.addPass(PreISelInjectionPoint());
if (OptLevel != CodeGenOptLevel::None)
FPM.addPass(ObjCARCContractPass());
@@ -188,22 +191,22 @@ TargetPassBuilder::buildCodeGenIRPipeline() {
// Add both the safe stack and the stack protection passes: each of them will
// only protect functions that have corresponding attributes.
- FPM.addPass(SafeStackPass(TM));
- FPM.addPass(StackProtectorPass(TM));
+ FPM.addPass(SafeStackPass(*TM));
+ FPM.addPass(StackProtectorPass(*TM));
// All passes which modify the LLVM IR are now complete; run the verifier
// to ensure that the IR is valid.
if (!CGPBO.DisableVerify)
FPM.addPass(VerifierPass());
if (CGPBO.RequiresCodeGenSCCOrder)
- MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
- createCGSCCToFunctionPassAdaptor(std::move(FPM))));
+ MPM.addFunctionPassWithPostOrderCGSCC(std::move(FPM));
else
- MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ MPM.addFunctionPass(std::move(FPM));
+
return MPM;
}
-void TargetPassBuilder::addISelPasses(MachineFunctionPassManager &MFPM) {
+void TargetPassBuilder::addISelPasses(TargetMachineFunctionPassManager &MFPM) {
// Add core instruction selection passes.
// Enable FastISel with -fast-isel, but allow that to be overridden.
TM->setO0WantsFastISel(CGPBO.EnableFastISelOption.value_or(true));
@@ -259,7 +262,8 @@ void TargetPassBuilder::addISelPasses(MachineFunctionPassManager &MFPM) {
MFPM.addPass(FinalizeISelPass());
}
-void TargetPassBuilder::addRegAllocPipeline(MachineFunctionPassManager &MFPM) {
+void TargetPassBuilder::addRegAllocPipeline(
+ TargetMachineFunctionPassManager &MFPM) {
if (CGPBO.OptimizeRegAlloc.value_or(OptLevel != CodeGenOptLevel::None)) {
MFPM.addPass(DetectDeadLanesPass());
@@ -340,13 +344,13 @@ void TargetPassBuilder::addRegAllocPipeline(MachineFunctionPassManager &MFPM) {
}
}
-void TargetPassBuilder::addRegAllocPass(MachineFunctionPassManager &MFPM,
+void TargetPassBuilder::addRegAllocPass(TargetMachineFunctionPassManager &MFPM,
bool Optimized) {
// TODO: Handle register allocator
}
void TargetPassBuilder::addMachineSSAOptimizationPasses(
- MachineFunctionPassManager &MFPM) {
+ TargetMachineFunctionPassManager &MFPM) {
// Pre-ra tail duplication.
MFPM.addPass(EarlyTailDuplicatePass());
@@ -368,6 +372,11 @@ void TargetPassBuilder::addMachineSSAOptimizationPasses(
// arguments directly (see t11 in test/CodeGen/X86/sibcall.ll).
MFPM.addPass(DeadMachineInstructionElimPass());
+ // Allow targets to insert passes that improve instruction level parallelism,
+ // like if-conversion. Such passes will typically need dominator trees and
+ // loop info, just like LICM and CSE below.
+ MFPM.addPass(ILPOptsInjectionPoint());
+
// Target can insert passes here that improve instruction level parallelism,
// like if-conversion. Such passes will typically need dominator trees and
// loop info, just like LICM and CSE below.
@@ -408,10 +417,9 @@ static std::string getFSRemappingFile(const CGPassBuilderOption &CGPBO,
return PGOOpt->ProfileRemappingFile;
}
-TargetPassBuilder::ModulePassManager
-TargetPassBuilder::buildCodeGenMIRPipeline() {
- ModulePassManager MPM;
- MachineFunctionPassManager MFPM;
+TargetModulePassManager TargetPassBuilder::buildCodeGenMIRPipeline() {
+ TargetModulePassManager MPM;
+ TargetMachineFunctionPassManager MFPM;
if (OptLevel != CodeGenOptLevel::None) {
addMachineSSAOptimizationPasses(MFPM);
} else {
@@ -539,15 +547,17 @@ TargetPassBuilder::buildCodeGenMIRPipeline() {
bool AddOutliner =
RunOnAllFunctions || TM->Options.SupportsDefaultOutlining;
if (AddOutliner) {
- if (CGPBO.RequiresCodeGenSCCOrder)
- MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
- createCGSCCToFunctionPassAdaptor(
- createFunctionToMachineFunctionPassAdaptor(std::move(MFPM)))));
- else
- MPM.addPass(createModuleToFunctionPassAdaptor(
- createFunctionToMachineFunctionPassAdaptor(std::move(MFPM))));
+ if (CGPBO.RequiresCodeGenSCCOrder) {
+ MPM.addFunctionPassWithPostOrderCGSCC(
+ TargetFunctionPassManager().addMachineFunctionPass(
+ std::move(MFPM)));
+ } else {
+ MPM.addFunctionPass(TargetFunctionPassManager().addMachineFunctionPass(
+ std::move(MFPM)));
+ }
+
MPM.addPass(MachineOutlinerPass(RunOnAllFunctions));
- MFPM = MachineFunctionPassManager();
+ MFPM = TargetMachineFunctionPassManager();
}
}
@@ -585,14 +595,15 @@ TargetPassBuilder::buildCodeGenMIRPipeline() {
// static data annotator pass is a module-wide pass. See the file comment
// in StaticDataAnnotator.cpp for the motivation.
MFPM.addPass(StaticDataSplitterPass());
- if (CGPBO.RequiresCodeGenSCCOrder)
- MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
- createCGSCCToFunctionPassAdaptor(
- createFunctionToMachineFunctionPassAdaptor(std::move(MFPM)))));
- else
- MPM.addPass(createModuleToFunctionPassAdaptor(
- createFunctionToMachineFunctionPassAdaptor(std::move(MFPM))));
- MFPM = MachineFunctionPassManager();
+ if (CGPBO.RequiresCodeGenSCCOrder) {
+ MPM.addFunctionPassWithPostOrderCGSCC(
+ TargetFunctionPassManager().addMachineFunctionPass(
+ std::move(MFPM)));
+ } else {
+ MPM.addFunctionPass(TargetFunctionPassManager().addMachineFunctionPass(
+ std::move(MFPM)));
+ }
+ MFPM = TargetMachineFunctionPassManager();
MPM.addPass(StaticDataAnnotatorPass());
}
}
@@ -608,24 +619,24 @@ TargetPassBuilder::buildCodeGenMIRPipeline() {
MFPM.addPass(BasicBlockSectionsPass());
}
- MFPM.addPass(PostBBSections());
+ MFPM.addPass(PostBBSectionsInjectionPoint());
if (!CGPBO.DisableCFIFixup && TM->Options.EnableCFIFixup)
MFPM.addPass(CFIFixupPass());
MFPM.addPass(StackFrameLayoutAnalysisPass());
- MFPM.addPass(PreEmit());
+ MFPM.addPass(PreEmitInjectionPoint());
if (CGPBO.RequiresCodeGenSCCOrder)
- MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
- createCGSCCToFunctionPassAdaptor(
- createFunctionToMachineFunctionPassAdaptor(std::move(MFPM)))));
+ MPM.addFunctionPassWithPostOrderCGSCC(
+ TargetFunctionPassManager().addMachineFunctionPass(std::move(MFPM)));
else
- MPM.addPass(createModuleToFunctionPassAdaptor(
- createFunctionToMachineFunctionPassAdaptor(std::move(MFPM))));
+ MPM.addFunctionPass(
+ TargetFunctionPassManager().addMachineFunctionPass(std::move(MFPM)));
return MPM;
}
-void TargetPassBuilder::addExceptionHandlingPasses(FunctionPassManager &FPM) {
+void TargetPassBuilder::addExceptionHandlingPasses(
+ TargetFunctionPassManager &FPM) {
const MCAsmInfo *MCAI = TM->getMCAsmInfo();
switch (MCAI->getExceptionHandlingType()) {
@@ -642,14 +653,14 @@ void TargetPassBuilder::addExceptionHandlingPasses(FunctionPassManager &FPM) {
case ExceptionHandling::ARM:
case ExceptionHandling::AIX:
case ExceptionHandling::ZOS:
- FPM.addPass(DwarfEHPreparePass(TM));
+ FPM.addPass(DwarfEHPreparePass(*TM));
break;
case ExceptionHandling::WinEH:
// We support using both GCC-style and MSVC-style exceptions on Windows, so
// add both preparation passes. Each pass will only actually run if it
// recognizes the personality function.
FPM.addPass(WinEHPreparePass());
- FPM.addPass(DwarfEHPreparePass(TM));
+ FPM.addPass(DwarfEHPreparePass(*TM));
break;
case ExceptionHandling::Wasm:
// Wasm EH uses Windows EH instructions, but it does not need to demote PHIs
@@ -667,19 +678,19 @@ void TargetPassBuilder::addExceptionHandlingPasses(FunctionPassManager &FPM) {
}
}
-void TargetPassBuilder::filtPassList(ModulePassManager &MPM) const {
+void TargetPassBuilder::filterPassList(TargetModulePassManager &MPM) const {
PassList &Passes = MPM.Passes;
auto *PIC = PB.getPassInstrumentationCallbacks();
auto ESSI = TargetPassConfig::getStartStopInfo(*PIC);
if (!ESSI)
- report_fatal_error(ESSI.takeError(), "invalid start stop flag!");
+ report_fatal_error(ESSI.takeError());
auto SSI = *ESSI;
size_t StartCnt = 0, StopCnt = 0;
bool HandledStartAfter = !SSI.StartAfter, HandledStopAfter = !SSI.StopAfter;
bool ShouldRemove = !SSI.StartPass.empty();
for (auto I = Passes.begin(), E = Passes.end(); I != E;) {
// Handle disabled pass firstly.
- if (isPassDisabled(I->Name)) {
+ if (isPassDisabled(I->Name) || I->IsInjectionPoint) {
I = Passes.erase(I);
continue;
}
@@ -718,90 +729,87 @@ void TargetPassBuilder::filtPassList(ModulePassManager &MPM) const {
}
void TargetPassBuilder::addPrinterPassesAndFreeMachineFunction(
- ModulePassManager &MPM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
- CodeGenFileType FileType, MCContext &Ctx) {
+ TargetModulePassManager &MPM, raw_pwrite_stream &Out,
+ raw_pwrite_stream *DwoOut, CodeGenFileType FileType, MCContext &Ctx) {
PassList &Passes = MPM.Passes;
PassList::iterator LastModulePassInsertPoint =
- llvm::find_if(llvm::reverse(Passes), [](PassWrapper &PW) {
- return PW.InternalPass.index() == 0; // The last module pass
+ llvm::find_if(llvm::reverse(Passes), [](detail::PassWrapper &PW) {
+ return PW.Ctor.index() == 0; // The last module pass
}).base();
// FIXME: CodeGenFileType here is not enough, we need an output type for MC
if (TargetPassConfig::willCompleteCodeGenPipeline()) {
- ModulePassManager AsmPrinterPM;
- FunctionPassManager FPM;
+ TargetModulePassManager AsmPrinterPM;
+ TargetFunctionPassManager FPM;
// MachineFunctionPassManager MFPM;
// TODO: Insert asm printer initialization pass at LastModulePassInsertPoint
// TODO: Insert asm printer
FPM.addPass(InvalidateAnalysisPass<MachineFunctionAnalysis>());
// TODO: Add asm printer finalization pass.
if (CGPBO.RequiresCodeGenSCCOrder)
- AsmPrinterPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
- createCGSCCToFunctionPassAdaptor(std::move(FPM))));
+ AsmPrinterPM.addFunctionPassWithPostOrderCGSCC((std::move(FPM)));
else
- AsmPrinterPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ AsmPrinterPM.addFunctionPass(std::move(FPM));
MPM.addPass(std::move(AsmPrinterPM));
} else {
Passes.insert(LastModulePassInsertPoint,
- PassWrapper(PrintMIRPreparePass(Out)));
- FunctionPassManager FPM;
- MachineFunctionPassManager MFPM;
+ detail::PassWrapper(PrintMIRPreparePass(Out)));
+ TargetFunctionPassManager FPM;
+ TargetMachineFunctionPassManager MFPM;
MFPM.addPass(PrintMIRPass(Out));
- FPM.addPass(createFunctionToMachineFunctionPassAdaptor(std::move(MFPM)));
+ FPM.addMachineFunctionPass(std::move(MFPM));
FPM.addPass(InvalidateAnalysisPass<MachineFunctionAnalysis>());
if (CGPBO.RequiresCodeGenSCCOrder)
- MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
- createCGSCCToFunctionPassAdaptor(std::move(FPM))));
+ MPM.addFunctionPassWithPostOrderCGSCC(std::move(FPM));
else
- MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ MPM.addFunctionPass(std::move(FPM));
}
}
-llvm::ModulePassManager
-TargetPassBuilder::constructRealPassManager(ModulePassManager &&MPMW) {
- llvm::ModulePassManager MPM;
- llvm::FunctionPassManager FPM;
- llvm::LoopPassManager LPM;
- llvm::MachineFunctionPassManager MFPM;
+ModulePassManager TargetPassBuilder::constructRealPassManager(
+ TargetModulePassManager &TMPM) const {
+ ModulePassManager MPM;
+ FunctionPassManager FPM;
+ LoopPassManager LPM;
+ MachineFunctionPassManager MFPM;
std::stack<size_t> S({0});
bool InCGSCC = false, LastInCGSCC = false;
- for (auto &P : MPMW.Passes) {
- auto &PMVar = P.InternalPass;
+ for (auto &P : TMPM.Passes) {
std::visit(
- [&](auto &&PM) {
+ [&](auto &Ctor) {
if (P.InCGSCC)
InCGSCC = true;
- size_t VarIdx = PMVar.index();
+ size_t VarIdx = P.Ctor.index();
while (VarIdx < S.top()) {
switch (S.top()) {
case 3:
if (!MFPM.isEmpty())
- FPM.addPass(llvm::createFunctionToMachineFunctionPassAdaptor(
+ FPM.addPass(createFunctionToMachineFunctionPassAdaptor(
std::move(MFPM)));
- MFPM = llvm::MachineFunctionPassManager();
+ MFPM = MachineFunctionPassManager();
S.pop();
break;
case 2:
if (!LPM.isEmpty())
FPM.addPass(llvm::createFunctionToLoopPassAdaptor(
std::move(LPM), /*UseMemorySSA=*/true));
- LPM = llvm::LoopPassManager();
+ LPM = LoopPassManager();
S.pop();
break;
case 1:
if (!FPM.isEmpty()) {
if (CGPBO.RequiresCodeGenSCCOrder && LastInCGSCC) {
InCGSCC = false;
- MPM.addPass(llvm::createModuleToPostOrderCGSCCPassAdaptor(
- llvm::createCGSCCToFunctionPassAdaptor(std::move(FPM))));
+ MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
+ createCGSCCToFunctionPassAdaptor(std::move(FPM))));
} else {
MPM.addPass(
- llvm::createModuleToFunctionPassAdaptor(std::move(FPM)));
+ createModuleToFunctionPassAdaptor(std::move(FPM)));
}
}
- FPM = llvm::FunctionPassManager();
+ FPM = FunctionPassManager();
S.pop();
break;
case 0:
@@ -813,48 +821,54 @@ TargetPassBuilder::constructRealPassManager(ModulePassManager &&MPMW) {
while (VarIdx > S.top())
S.push(S.top() + 1);
- if constexpr (std::is_same_v<std::remove_reference_t<decltype(PM)>,
- llvm::ModulePassManager>)
- MPM.addPass(std::move(PM));
- if constexpr (std::is_same_v<std::remove_reference_t<decltype(PM)>,
- llvm::FunctionPassManager>) {
+ if constexpr (std::is_same_v<
+ std::remove_reference_t<decltype(Ctor)>,
+ llvm::unique_function<void(ModulePassManager &)>>) {
+ Ctor(MPM);
+ } else if constexpr (std::is_same_v<
+ std::remove_reference_t<decltype(Ctor)>,
+ llvm::unique_function<void(
+ FunctionPassManager &)>>) {
if (!LastInCGSCC && P.InCGSCC) {
- MPM.addPass(
- llvm::createModuleToFunctionPassAdaptor(std::move(FPM)));
- FPM = llvm::FunctionPassManager();
+ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ FPM = FunctionPassManager();
}
- FPM.addPass(std::move(PM));
+ Ctor(FPM);
+ } else if constexpr (std::is_same_v<
+ std::remove_reference_t<decltype(Ctor)>,
+ llvm::unique_function<void(
+ LoopPassManager &)>>) {
+ Ctor(LPM);
+ } else if constexpr (std::is_same_v<
+ decltype(Ctor),
+ llvm::unique_function<void(
+ MachineFunctionPassManager &)>>) {
+ Ctor(MFPM);
}
- if constexpr (std::is_same_v<std::remove_reference_t<decltype(PM)>,
- llvm::LoopPassManager>)
- LPM.addPass(std::move(PM));
- if constexpr (std::is_same_v<std::remove_reference_t<decltype(PM)>,
- llvm::MachineFunctionPassManager>)
- MFPM.addPass(std::move(PM));
LastInCGSCC = P.InCGSCC;
},
- PMVar);
+ P.Ctor);
}
if (!MFPM.isEmpty())
- FPM.addPass(
- llvm::createFunctionToMachineFunctionPassAdaptor(std::move(MFPM)));
+ FPM.addPass(createFunctionToMachineFunctionPassAdaptor(std::move(MFPM)));
if (!LPM.isEmpty())
- FPM.addPass(llvm::createFunctionToLoopPassAdaptor(std::move(LPM),
- /*UseMemorySSA=*/true));
+ FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM),
+ /*UseMemorySSA=*/true));
if (!FPM.isEmpty()) {
if (CGPBO.RequiresCodeGenSCCOrder)
- MPM.addPass(llvm::createModuleToPostOrderCGSCCPassAdaptor(
- llvm::createCGSCCToFunctionPassAdaptor(std::move(FPM))));
+ MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
+ createCGSCCToFunctionPassAdaptor(std::move(FPM))));
else
- MPM.addPass(llvm::createModuleToFunctionPassAdaptor(std::move(FPM)));
+ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
}
return MPM;
}
-void TargetPassBuilder::invokeInjectionCallbacks(ModulePassManager &MPM) const {
+void TargetPassBuilder::invokeInjectionCallbacks(
+ TargetModulePassManager &MPM) const {
PassList &Passes = MPM.Passes;
for (auto I = Passes.begin(), E = Passes.end(); I != E; ++I)
for (auto &C : InjectionCallbacks)
diff --git a/llvm/unittests/CodeGen/TargetPassBuilderTest.cpp b/llvm/unittests/CodeGen/TargetPassBuilderTest.cpp
index 75353c66e7fc6..929e8d5470387 100644
--- a/llvm/unittests/CodeGen/TargetPassBuilderTest.cpp
+++ b/llvm/unittests/CodeGen/TargetPassBuilderTest.cpp
@@ -72,21 +72,20 @@ struct TestDAGISelPass : public PassInfoMixin<TestDAGISelPass> {
class TestPassBuilder : public TargetPassBuilder {
public:
- using TargetPassBuilder::ModulePassManager;
-
- TestPassBuilder(PassBuilder &PB) : TargetPassBuilder(PB) {
+ TestPassBuilder(PassBuilder &PB) : TargetPassBuilder(PB) {}
+ void registerCallbacks() override {
registerSelectionDAGISelPass([]() { return TestDAGISelPass(); });
CGPBO.RequiresCodeGenSCCOrder = true;
injectBefore<PreISelIntrinsicLoweringPass>([]() {
- ModulePassManager MPM;
+ TargetModulePassManager MPM;
MPM.addPass(NoOpModulePass());
return MPM;
});
- injectBefore<ExpandFpPass, ModulePassManager>([] {
- ModulePassManager MPM;
+ injectBefore<ExpandFpPass, TargetModulePassManager>([] {
+ TargetModulePassManager MPM;
MPM.addPass(NoOpModulePass());
return MPM;
});
@@ -98,7 +97,8 @@ template struct PrivateVisitorHelper<
template struct PrivateVisitorHelper<
0, &TargetPassBuilder::invokeInjectionCallbacks>;
template struct PrivateVisitorHelper<
- 0, &TargetPassBuilder::ModulePassManager::Passes>;
+ 0, &TargetPassBuilder::constructRealPassManager>;
+template struct PrivateVisitorHelper<0, &TargetModulePassManager::Passes>;
TEST(TargetPassBuilder, Basic) {
TargetMachine *TM = createTargetMachine();
@@ -118,21 +118,31 @@ TEST(TargetPassBuilder, Basic) {
PB.crossRegisterProxies(LAM, FAM, CGAM, AM);
TestPassBuilder TPB(PB);
- using PassList = TargetPassBuilder::PassList;
- auto MPM = (TPB.*PrivatePtr<0, TestPassBuilder::ModulePassManager (
- TargetPassBuilder::*)()>)();
- auto &Passes =
- MPM.*PrivatePtr<0, PassList TestPassBuilder::ModulePassManager::*>;
- (TPB.*PrivatePtr<0, void (TargetPassBuilder::*)(
- TestPassBuilder::ModulePassManager &)
- const>)(MPM); // invokeInjectionCallbacks
+ TPB.registerCallbacks();
+ using PassList = std::list<detail::PassWrapper>;
+ TargetModulePassManager TMPM =
+ (TPB.*
+ PrivatePtr<0, TargetModulePassManager (
+ TargetPassBuilder::*)()>)(); // buildCodeGenIRPipeline
+ auto &Passes = TMPM.*PrivatePtr<0, PassList TargetModulePassManager::*>;
+ (TPB.*PrivatePtr<0, void (TargetPassBuilder::*)(TargetModulePassManager &)
+ const>)(TMPM); // invokeInjectionCallbacks
auto B = Passes.begin();
EXPECT_EQ(B->Name, NoOpModulePass::name());
- ++B, ++B, ++B;
+ B = std::next(B, 3);
EXPECT_EQ(B->Name, NoOpModulePass::name());
+
+ ModulePassManager MPM =
+ (TPB.*PrivatePtr<0, ModulePassManager (TargetPassBuilder::*)(
+ TargetModulePassManager &) const>)(TMPM);
+ std::string PipelineString;
+ llvm::raw_string_ostream OS(PipelineString);
+ MPM.printPipeline(OS, [](StringRef Name) { return Name; });
+ StringRef PipelineStringRef(PipelineString);
+ EXPECT_TRUE(PipelineStringRef.ends_with("VerifierPass"));
}
-template struct PrivateVisitorHelper<1, &TargetPassBuilder::filtPassList>;
+template struct PrivateVisitorHelper<1, &TargetPassBuilder::filterPassList>;
TEST(TargetPassBuilder, StartStop) {
const char *Argv[] = {"CodeGenTests",
@@ -156,18 +166,16 @@ TEST(TargetPassBuilder, StartStop) {
PB.registerLoopAnalyses(LAM);
PB.crossRegisterProxies(LAM, FAM, CGAM, AM);
- using PassList = TargetPassBuilder::PassList;
+ using PassList = std::list<detail::PassWrapper>;
TestPassBuilder TPB(PB);
- auto MPM = (TPB.*PrivatePtr<0, TestPassBuilder::ModulePassManager (
- TargetPassBuilder::*)()>)();
- auto &Passes =
- MPM.*PrivatePtr<0, PassList TestPassBuilder::ModulePassManager::*>;
- (TPB.*PrivatePtr<0, void (TargetPassBuilder::*)(
- TestPassBuilder::ModulePassManager &)
+ TPB.registerCallbacks();
+ TargetModulePassManager MPM =
+ (TPB.*PrivatePtr<0, TargetModulePassManager (TargetPassBuilder::*)()>)();
+ PassList &Passes = MPM.*PrivatePtr<0, PassList TargetModulePassManager::*>;
+ (TPB.*PrivatePtr<0, void (TargetPassBuilder::*)(TargetModulePassManager &)
const>)(MPM); // invokeInjectionCallbacks
- (TPB.*PrivatePtr<1, void (TargetPassBuilder::*)(
- TestPassBuilder::ModulePassManager &)
+ (TPB.*PrivatePtr<1, void (TargetPassBuilder::*)(TargetModulePassManager &)
const>)(MPM); // filtPassList
EXPECT_EQ(Passes.size(), 1u);
EXPECT_EQ(Passes.begin()->Name, ExpandLargeDivRemPass::name());
More information about the llvm-commits
mailing list