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. _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
