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

Reply via email to