[llvm-branch-commits] [llvm] b6a1c18 - Revert "[IR][NFC] Drop vtable from PassConcept/PassModel (#208168)"
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Jul 9 00:38:35 PDT 2026
Author: Alexis Engelke
Date: 2026-07-09T09:38:30+02:00
New Revision: b6a1c182fe10957e50efcf9216c9b05ab988ac5b
URL: https://github.com/llvm/llvm-project/commit/b6a1c182fe10957e50efcf9216c9b05ab988ac5b
DIFF: https://github.com/llvm/llvm-project/commit/b6a1c182fe10957e50efcf9216c9b05ab988ac5b.diff
LOG: Revert "[IR][NFC] Drop vtable from PassConcept/PassModel (#208168)"
This reverts commit c12df55e9a5ee84178c5d30c753a4799b63fec80.
Added:
Modified:
llvm/include/llvm/IR/PassManagerInternal.h
Removed:
################################################################################
diff --git a/llvm/include/llvm/IR/PassManagerInternal.h b/llvm/include/llvm/IR/PassManagerInternal.h
index 15521aa5ac5fc..f894f91cf1783 100644
--- a/llvm/include/llvm/IR/PassManagerInternal.h
+++ b/llvm/include/llvm/IR/PassManagerInternal.h
@@ -34,104 +34,68 @@ class PreservedAnalyses;
// Implementation details of the pass manager interfaces.
namespace detail {
-/// Template for the abstract base class used to dispatch over pass objects.
-/// This doesn't use virtual functions to avoid vtables, which cost a fair
-/// amount of storage that needs to be relocated in PIC builds and add an extra
-/// indirection on dispatch.
+/// Template for the abstract base class used to dispatch
+/// polymorphically over pass objects.
template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
-class PassConcept {
-private:
- using DestructorTy = void (*)(PassConcept &);
- using RunTy = PreservedAnalyses (*)(PassConcept &, IRUnitT &,
- AnalysisManagerT &, ExtraArgTs...);
- using PrintPipelineTy =
- void (*)(PassConcept &, raw_ostream &,
- function_ref<StringRef(StringRef)> MapClassName2PassName);
-
- StringRef Name;
- bool IsRequired;
-
- DestructorTy Destructor;
- RunTy Run;
- PrintPipelineTy PrintPipeline;
-
-protected:
- PassConcept(StringRef Name, bool IsRequired, DestructorTy Destructor,
- RunTy Run, PrintPipelineTy PrintPipeline)
- : Name(Name), IsRequired(IsRequired), Destructor(Destructor), Run(Run),
- PrintPipeline(PrintPipeline) {}
+struct PassConcept {
+ PassConcept() = default;
-public:
// Boiler plate necessary for the container of derived classes.
- ~PassConcept() { Destructor(*this); }
+ virtual ~PassConcept() = default;
// Passes are immovable.
PassConcept(const PassConcept &) = delete;
PassConcept &operator=(const PassConcept &) = delete;
- /// Run the pass.
- PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
- ExtraArgTs... ExtraArgs) {
- return Run(*this, IR, AM, std::forward<ExtraArgTs>(ExtraArgs)...);
- }
-
- void printPipeline(raw_ostream &OS,
- function_ref<StringRef(StringRef)> MapClassName2PassName) {
- PrintPipeline(*this, OS, MapClassName2PassName);
- }
-
- /// Get name of a pass.
- StringRef name() const { return Name; }
+ /// The polymorphic API which runs the pass over a given IR entity.
+ ///
+ /// Note that actual pass object can omit the analysis manager argument if
+ /// desired. Also that the analysis manager may be null if there is no
+ /// analysis manager in the pass pipeline.
+ virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
+ ExtraArgTs... ExtraArgs) = 0;
+
+ virtual void
+ printPipeline(raw_ostream &OS,
+ function_ref<StringRef(StringRef)> MapClassName2PassName) = 0;
+ /// Polymorphic method to access the name of a pass.
+ virtual StringRef name() const = 0;
- /// Indicate whether a pass can optionally be exempted from skipping by
+ /// Polymorphic method to let a pass optionally exempted from skipping by
/// PassInstrumentation.
/// To opt-in, pass should implement `static bool isRequired()`, or inherit
/// from `RequiredPassInfoMixin` or `OptionalPassInfoMixin`.
/// It's no-op to have `isRequired` always return false since that is the
/// default.
- bool isRequired() const { return IsRequired; }
+ virtual bool isRequired() const = 0;
};
-/// A template wrapper used to implement PassConcept.
+/// A template wrapper used to implement the polymorphic API.
///
/// Can be instantiated for any object which provides a \c run method accepting
-/// an \c IRUnitT& and an \c AnalysisManager<IRUnit>&.
+/// an \c IRUnitT& and an \c AnalysisManager<IRUnit>&. It requires the pass to
+/// be a copyable object.
template <typename IRUnitT, typename PassT, typename AnalysisManagerT,
typename... ExtraArgTs>
-class PassModel final
- : public PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> {
-private:
- using PassConceptT = PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...>;
-
- /// Storage for PassT. We don't use a PassT here, because the destructor of
- /// PassModel will not be called -- the PassT instance has to be destructed
- /// in destructorImpl.
- alignas(PassT) char PassBytes[sizeof(PassT)];
-
- static PassT &getPass(PassConceptT &Self) {
- return *reinterpret_cast<PassT *>(static_cast<PassModel &>(Self).PassBytes);
- }
-
- static void destructorImpl(PassConceptT &Self) { getPass(Self).~PassT(); }
+struct PassModel final : PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> {
+ explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
- static PreservedAnalyses runImpl(PassConceptT &Self, IRUnitT &IR,
- AnalysisManagerT &AM,
- ExtraArgTs... ExtraArgs) {
- return getPass(Self).run(IR, AM, ExtraArgs...);
+ PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
+ ExtraArgTs... ExtraArgs) override {
+ return Pass.run(IR, AM, ExtraArgs...);
}
- static void
- printPipelineImpl(PassConceptT &Self, raw_ostream &OS,
- function_ref<StringRef(StringRef)> MapClassName2PassName) {
- getPass(Self).printPipeline(OS, MapClassName2PassName);
+ void printPipeline(
+ raw_ostream &OS,
+ function_ref<StringRef(StringRef)> MapClassName2PassName) override {
+ Pass.printPipeline(OS, MapClassName2PassName);
}
-public:
- explicit PassModel(PassT Pass)
- : PassConceptT(PassT::name(), PassT::isRequired(), destructorImpl,
- runImpl, printPipelineImpl) {
- new (PassBytes) PassT(std::move(Pass));
- }
+ StringRef name() const override { return PassT::name(); }
+
+ bool isRequired() const override { return PassT::isRequired(); }
+
+ PassT Pass;
};
/// Abstract concept of an analysis result.
More information about the llvm-branch-commits
mailing list