[llvm] [CodeGen][Pass] Add `TargetPassBuilder` (PR #137290)
Stefan Gränitz via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 5 01:44:17 PST 2025
================
@@ -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;
----------------
weliveindetail wrote:
Then we could get rid of the type detection here (which btw doesn't work out-of-the-box on current main anymore)
https://github.com/llvm/llvm-project/pull/137290
More information about the llvm-commits
mailing list