[llvm] Reapply "[IR][NFC] Drop vtable from PassConcept/PassModel" (#208168) (PR #209414)
Alexis Engelke via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 14 04:24:35 PDT 2026
https://github.com/aengelke updated https://github.com/llvm/llvm-project/pull/209414
>From 272e691aab08c945f5cbdd459d4b60ca8e4e9825 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <engelke at in.tum.de>
Date: Tue, 14 Jul 2026 09:31:54 +0000
Subject: [PATCH 1/2] [spr] initial version
Created using spr 1.3.8-wip
---
llvm/include/llvm/Analysis/CGSCCPassManager.h | 18 +--
.../include/llvm/CodeGen/MachinePassManager.h | 7 +-
llvm/include/llvm/IR/PassManager.h | 10 +-
llvm/include/llvm/IR/PassManagerInternal.h | 115 ++++++++++++------
.../llvm/Transforms/Scalar/LoopPassManager.h | 18 +--
5 files changed, 105 insertions(+), 63 deletions(-)
diff --git a/llvm/include/llvm/Analysis/CGSCCPassManager.h b/llvm/include/llvm/Analysis/CGSCCPassManager.h
index e85c1ef9a90d2..1cfe68ee6fa59 100644
--- a/llvm/include/llvm/Analysis/CGSCCPassManager.h
+++ b/llvm/include/llvm/Analysis/CGSCCPassManager.h
@@ -319,7 +319,7 @@ class ModuleToPostOrderCGSCCPassAdaptor
detail::PassConcept<LazyCallGraph::SCC, CGSCCAnalysisManager,
LazyCallGraph &, CGSCCUpdateResult &>;
- explicit ModuleToPostOrderCGSCCPassAdaptor(std::unique_ptr<PassConceptT> Pass)
+ explicit ModuleToPostOrderCGSCCPassAdaptor(PassConceptT::unique_ptr Pass)
: Pass(std::move(Pass)) {}
ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor &&Arg)
@@ -347,7 +347,7 @@ class ModuleToPostOrderCGSCCPassAdaptor
}
private:
- std::unique_ptr<PassConceptT> Pass;
+ PassConceptT::unique_ptr Pass;
};
/// A function to deduce a function pass type and wrap it in the
@@ -361,7 +361,7 @@ createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT &&Pass) {
// Do not use make_unique, it causes too many template instantiations,
// causing terrible compile times.
return ModuleToPostOrderCGSCCPassAdaptor(
- std::unique_ptr<ModuleToPostOrderCGSCCPassAdaptor::PassConceptT>(
+ ModuleToPostOrderCGSCCPassAdaptor::PassConceptT::unique_ptr(
new PassModelT(std::forward<CGSCCPassT>(Pass))));
}
@@ -447,7 +447,7 @@ class CGSCCToFunctionPassAdaptor
public:
using PassConceptT = detail::PassConcept<Function, FunctionAnalysisManager>;
- explicit CGSCCToFunctionPassAdaptor(std::unique_ptr<PassConceptT> Pass,
+ explicit CGSCCToFunctionPassAdaptor(typename PassConceptT::unique_ptr Pass,
bool EagerlyInvalidate, bool NoRerun)
: Pass(std::move(Pass)), EagerlyInvalidate(EagerlyInvalidate),
NoRerun(NoRerun) {}
@@ -490,7 +490,7 @@ class CGSCCToFunctionPassAdaptor
}
private:
- std::unique_ptr<PassConceptT> Pass;
+ PassConceptT::unique_ptr Pass;
bool EagerlyInvalidate;
bool NoRerun;
};
@@ -507,7 +507,7 @@ createCGSCCToFunctionPassAdaptor(FunctionPassT &&Pass,
// Do not use make_unique, it causes too many template instantiations,
// causing terrible compile times.
return CGSCCToFunctionPassAdaptor(
- std::unique_ptr<CGSCCToFunctionPassAdaptor::PassConceptT>(
+ CGSCCToFunctionPassAdaptor::PassConceptT::unique_ptr(
new PassModelT(std::forward<FunctionPassT>(Pass))),
EagerlyInvalidate, NoRerun);
}
@@ -547,7 +547,7 @@ class DevirtSCCRepeatedPass
detail::PassConcept<LazyCallGraph::SCC, CGSCCAnalysisManager,
LazyCallGraph &, CGSCCUpdateResult &>;
- explicit DevirtSCCRepeatedPass(std::unique_ptr<PassConceptT> Pass,
+ explicit DevirtSCCRepeatedPass(PassConceptT::unique_ptr Pass,
int MaxIterations)
: Pass(std::move(Pass)), MaxIterations(MaxIterations) {}
@@ -565,7 +565,7 @@ class DevirtSCCRepeatedPass
}
private:
- std::unique_ptr<PassConceptT> Pass;
+ PassConceptT::unique_ptr Pass;
int MaxIterations;
};
@@ -580,7 +580,7 @@ DevirtSCCRepeatedPass createDevirtSCCRepeatedPass(CGSCCPassT &&Pass,
// Do not use make_unique, it causes too many template instantiations,
// causing terrible compile times.
return DevirtSCCRepeatedPass(
- std::unique_ptr<DevirtSCCRepeatedPass::PassConceptT>(
+ DevirtSCCRepeatedPass::PassConceptT::unique_ptr(
new PassModelT(std::forward<CGSCCPassT>(Pass))),
MaxIterations);
}
diff --git a/llvm/include/llvm/CodeGen/MachinePassManager.h b/llvm/include/llvm/CodeGen/MachinePassManager.h
index 936e80e88192c..5de520fa550f8 100644
--- a/llvm/include/llvm/CodeGen/MachinePassManager.h
+++ b/llvm/include/llvm/CodeGen/MachinePassManager.h
@@ -194,8 +194,7 @@ class FunctionToMachineFunctionPassAdaptor
using PassConceptT =
detail::PassConcept<MachineFunction, MachineFunctionAnalysisManager>;
- explicit FunctionToMachineFunctionPassAdaptor(
- std::unique_ptr<PassConceptT> Pass)
+ explicit FunctionToMachineFunctionPassAdaptor(PassConceptT::unique_ptr Pass)
: Pass(std::move(Pass)) {}
/// Runs the function pass across every function in the function.
@@ -205,7 +204,7 @@ class FunctionToMachineFunctionPassAdaptor
function_ref<StringRef(StringRef)> MapClassName2PassName);
private:
- std::unique_ptr<PassConceptT> Pass;
+ PassConceptT::unique_ptr Pass;
};
template <typename MachineFunctionPassT>
@@ -216,7 +215,7 @@ createFunctionToMachineFunctionPassAdaptor(MachineFunctionPassT &&Pass) {
// Do not use make_unique, it causes too many template instantiations,
// causing terrible compile times.
return FunctionToMachineFunctionPassAdaptor(
- std::unique_ptr<FunctionToMachineFunctionPassAdaptor::PassConceptT>(
+ FunctionToMachineFunctionPassAdaptor::PassConceptT::unique_ptr(
new PassModelT(std::forward<MachineFunctionPassT>(Pass))));
}
diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h
index 22e02853bc567..0c6dac6be8d31 100644
--- a/llvm/include/llvm/IR/PassManager.h
+++ b/llvm/include/llvm/IR/PassManager.h
@@ -222,7 +222,7 @@ class PassManager : public RequiredPassInfoMixin<
detail::PassModel<IRUnitT, PassT, AnalysisManagerT, ExtraArgTs...>;
// Do not use make_unique or emplace_back, they cause too many template
// instantiations, causing terrible compile times.
- Passes.push_back(std::unique_ptr<PassConceptT>(
+ Passes.push_back(typename PassConceptT::unique_ptr(
new PassModelT(std::forward<PassT>(Pass))));
}
@@ -245,7 +245,7 @@ class PassManager : public RequiredPassInfoMixin<
using PassConceptT =
detail::PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...>;
- std::vector<std::unique_ptr<PassConceptT>> Passes;
+ std::vector<typename PassConceptT::unique_ptr> Passes;
};
template <typename IRUnitT>
@@ -875,7 +875,7 @@ class ModuleToFunctionPassAdaptor
public:
using PassConceptT = detail::PassConcept<Function, FunctionAnalysisManager>;
- explicit ModuleToFunctionPassAdaptor(std::unique_ptr<PassConceptT> Pass,
+ explicit ModuleToFunctionPassAdaptor(PassConceptT::unique_ptr Pass,
bool EagerlyInvalidate)
: Pass(std::move(Pass)), EagerlyInvalidate(EagerlyInvalidate) {}
@@ -886,7 +886,7 @@ class ModuleToFunctionPassAdaptor
function_ref<StringRef(StringRef)> MapClassName2PassName);
private:
- std::unique_ptr<PassConceptT> Pass;
+ PassConceptT::unique_ptr Pass;
bool EagerlyInvalidate;
};
@@ -901,7 +901,7 @@ createModuleToFunctionPassAdaptor(FunctionPassT &&Pass,
// Do not use make_unique, it causes too many template instantiations,
// causing terrible compile times.
return ModuleToFunctionPassAdaptor(
- std::unique_ptr<ModuleToFunctionPassAdaptor::PassConceptT>(
+ ModuleToFunctionPassAdaptor::PassConceptT::unique_ptr(
new PassModelT(std::forward<FunctionPassT>(Pass))),
EagerlyInvalidate);
}
diff --git a/llvm/include/llvm/IR/PassManagerInternal.h b/llvm/include/llvm/IR/PassManagerInternal.h
index f894f91cf1783..d731bc56a2820 100644
--- a/llvm/include/llvm/IR/PassManagerInternal.h
+++ b/llvm/include/llvm/IR/PassManagerInternal.h
@@ -34,68 +34,111 @@ class PreservedAnalyses;
// Implementation details of the pass manager interfaces.
namespace detail {
-/// Template for the abstract base class used to dispatch
-/// polymorphically over pass objects.
+/// 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 <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
-struct PassConcept {
- PassConcept() = default;
+class PassConcept {
+private:
+ using DestroyTy = void (*)(PassConcept &);
+ using RunTy = PreservedAnalyses (*)(PassConcept &, IRUnitT &,
+ AnalysisManagerT &, ExtraArgTs...);
+ using PrintPipelineTy =
+ void (*)(PassConcept &, raw_ostream &,
+ function_ref<StringRef(StringRef)> MapClassName2PassName);
- // Boiler plate necessary for the container of derived classes.
- virtual ~PassConcept() = default;
+public:
+ struct Deleter {
+ void operator()(PassConcept *P) { P->Destroy(*P); }
+ };
+
+ using unique_ptr = std::unique_ptr<PassConcept, Deleter>;
+
+private:
+ StringRef Name;
+ bool IsRequired;
+
+ DestroyTy Destroy;
+ RunTy Run;
+ PrintPipelineTy PrintPipeline;
+
+protected:
+ PassConcept(StringRef Name, bool IsRequired, DestroyTy Destroy, RunTy Run,
+ PrintPipelineTy PrintPipeline)
+ : Name(Name), IsRequired(IsRequired), Destroy(Destroy), Run(Run),
+ PrintPipeline(PrintPipeline) {}
+ // Note: this is intentionally not public to catch uses of delete and
+ // unique_ptr<PassConcept>.
+ void operator delete(void *P) { ::operator delete(P); }
+
+public:
// Passes are immovable.
PassConcept(const PassConcept &) = delete;
PassConcept &operator=(const PassConcept &) = delete;
- /// 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;
+ /// 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);
+ }
- /// Polymorphic method to let a pass optionally exempted from skipping by
+ /// Get name of a pass.
+ StringRef name() const { return Name; }
+
+ /// Indicate whether a pass can optionally be 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.
- virtual bool isRequired() const = 0;
+ bool isRequired() const { return IsRequired; }
};
-/// A template wrapper used to implement the polymorphic API.
+/// A template wrapper used to implement PassConcept.
///
/// Can be instantiated for any object which provides a \c run method accepting
-/// an \c IRUnitT& and an \c AnalysisManager<IRUnit>&. It requires the pass to
-/// be a copyable object.
+/// an \c IRUnitT& and an \c AnalysisManager<IRUnit>&.
template <typename IRUnitT, typename PassT, typename AnalysisManagerT,
typename... ExtraArgTs>
-struct PassModel final : PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> {
- explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
+class PassModel final
+ : public PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> {
+private:
+ using PassConceptT = PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...>;
- PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
- ExtraArgTs... ExtraArgs) override {
- return Pass.run(IR, AM, ExtraArgs...);
+ PassT Pass;
+
+ static PassT &getPass(PassConceptT &Self) {
+ return static_cast<PassModel &>(Self).Pass;
}
- void printPipeline(
- raw_ostream &OS,
- function_ref<StringRef(StringRef)> MapClassName2PassName) override {
- Pass.printPipeline(OS, MapClassName2PassName);
+ static void destroyImpl(PassConceptT &Self) {
+ delete static_cast<PassModel *>(&Self);
}
- StringRef name() const override { return PassT::name(); }
+ static PreservedAnalyses runImpl(PassConceptT &Self, IRUnitT &IR,
+ AnalysisManagerT &AM,
+ ExtraArgTs... ExtraArgs) {
+ return getPass(Self).run(IR, AM, ExtraArgs...);
+ }
- bool isRequired() const override { return PassT::isRequired(); }
+ static void
+ printPipelineImpl(PassConceptT &Self, raw_ostream &OS,
+ function_ref<StringRef(StringRef)> MapClassName2PassName) {
+ getPass(Self).printPipeline(OS, MapClassName2PassName);
+ }
- PassT Pass;
+public:
+ explicit PassModel(PassT Pass)
+ : PassConceptT(PassT::name(), PassT::isRequired(), destroyImpl, runImpl,
+ printPipelineImpl),
+ Pass(std::move(Pass)) {}
};
/// Abstract concept of an analysis result.
diff --git a/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h b/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h
index 973d8a3cb1008..e11af53a47142 100644
--- a/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h
+++ b/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h
@@ -113,7 +113,7 @@ class PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
IsLoopNestPass.push_back(false);
// Do not use make_unique or emplace_back, they cause too many template
// instantiations, causing terrible compile times.
- LoopPasses.push_back(std::unique_ptr<LoopPassConceptT>(
+ LoopPasses.push_back(LoopPassConceptT::unique_ptr(
new LoopPassModelT(std::forward<PassT>(Pass))));
} else {
using LoopNestPassModelT =
@@ -122,7 +122,7 @@ class PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
IsLoopNestPass.push_back(true);
// Do not use make_unique or emplace_back, they cause too many template
// instantiations, causing terrible compile times.
- LoopNestPasses.push_back(std::unique_ptr<LoopNestPassConceptT>(
+ LoopNestPasses.push_back(LoopNestPassConceptT::unique_ptr(
new LoopNestPassModelT(std::forward<PassT>(Pass))));
}
}
@@ -143,8 +143,8 @@ class PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
// BitVector that identifies whether the passes are loop passes or loop-nest
// passes (true for loop-nest passes).
BitVector IsLoopNestPass;
- std::vector<std::unique_ptr<LoopPassConceptT>> LoopPasses;
- std::vector<std::unique_ptr<LoopNestPassConceptT>> LoopNestPasses;
+ std::vector<LoopPassConceptT::unique_ptr> LoopPasses;
+ std::vector<LoopNestPassConceptT::unique_ptr> LoopNestPasses;
/// Run either a loop pass or a loop-nest pass. Returns `std::nullopt` if
/// PassInstrumentation's BeforePass returns false. Otherwise, returns the
@@ -400,7 +400,7 @@ class FunctionToLoopPassAdaptor
detail::PassConcept<Loop, LoopAnalysisManager,
LoopStandardAnalysisResults &, LPMUpdater &>;
- explicit FunctionToLoopPassAdaptor(std::unique_ptr<PassConceptT> Pass,
+ explicit FunctionToLoopPassAdaptor(PassConceptT::unique_ptr Pass,
bool UseMemorySSA = false,
bool LoopNestMode = false)
: Pass(std::move(Pass)), UseMemorySSA(UseMemorySSA),
@@ -418,7 +418,7 @@ class FunctionToLoopPassAdaptor
bool isLoopNestMode() const { return LoopNestMode; }
private:
- std::unique_ptr<PassConceptT> Pass;
+ PassConceptT::unique_ptr Pass;
FunctionPassManager LoopCanonicalizationFPM;
@@ -443,7 +443,7 @@ createFunctionToLoopPassAdaptor(LoopPassT &&Pass, bool UseMemorySSA = false) {
// Do not use make_unique, it causes too many template instantiations,
// causing terrible compile times.
return FunctionToLoopPassAdaptor(
- std::unique_ptr<FunctionToLoopPassAdaptor::PassConceptT>(
+ FunctionToLoopPassAdaptor::PassConceptT::unique_ptr(
new PassModelT(std::forward<LoopPassT>(Pass))),
UseMemorySSA, false);
} else {
@@ -455,7 +455,7 @@ createFunctionToLoopPassAdaptor(LoopPassT &&Pass, bool UseMemorySSA = false) {
// Do not use make_unique, it causes too many template instantiations,
// causing terrible compile times.
return FunctionToLoopPassAdaptor(
- std::unique_ptr<FunctionToLoopPassAdaptor::PassConceptT>(
+ FunctionToLoopPassAdaptor::PassConceptT::unique_ptr(
new PassModelT(std::move(LPM))),
UseMemorySSA, true);
}
@@ -476,7 +476,7 @@ createFunctionToLoopPassAdaptor<LoopPassManager>(LoopPassManager &&LPM,
// Do not use make_unique, it causes too many template instantiations,
// causing terrible compile times.
return FunctionToLoopPassAdaptor(
- std::unique_ptr<FunctionToLoopPassAdaptor::PassConceptT>(
+ FunctionToLoopPassAdaptor::PassConceptT::unique_ptr(
new PassModelT(std::move(LPM))),
UseMemorySSA, LoopNestMode);
}
>From a01c83d7eca786f8030635480cbade114dd0db71 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <engelke at in.tum.de>
Date: Tue, 14 Jul 2026 11:23:55 +0000
Subject: [PATCH 2/2] more cleanup, wrap PassModel construction in function
Created using spr 1.3.8-wip
---
llvm/include/llvm/Analysis/CGSCCPassManager.h | 22 +++---------
.../include/llvm/CodeGen/MachinePassManager.h | 5 +--
llvm/include/llvm/IR/PassManager.h | 13 ++-----
llvm/include/llvm/IR/PassManagerInternal.h | 8 +++--
.../llvm/Transforms/Scalar/LoopPassManager.h | 36 +++++--------------
5 files changed, 24 insertions(+), 60 deletions(-)
diff --git a/llvm/include/llvm/Analysis/CGSCCPassManager.h b/llvm/include/llvm/Analysis/CGSCCPassManager.h
index 1cfe68ee6fa59..f2ce8158675ae 100644
--- a/llvm/include/llvm/Analysis/CGSCCPassManager.h
+++ b/llvm/include/llvm/Analysis/CGSCCPassManager.h
@@ -358,11 +358,7 @@ createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT &&Pass) {
using PassModelT =
detail::PassModel<LazyCallGraph::SCC, CGSCCPassT, CGSCCAnalysisManager,
LazyCallGraph &, CGSCCUpdateResult &>;
- // Do not use make_unique, it causes too many template instantiations,
- // causing terrible compile times.
- return ModuleToPostOrderCGSCCPassAdaptor(
- ModuleToPostOrderCGSCCPassAdaptor::PassConceptT::unique_ptr(
- new PassModelT(std::forward<CGSCCPassT>(Pass))));
+ return ModuleToPostOrderCGSCCPassAdaptor(PassModelT::create(std::move(Pass)));
}
/// A proxy from a \c FunctionAnalysisManager to an \c SCC.
@@ -504,12 +500,8 @@ createCGSCCToFunctionPassAdaptor(FunctionPassT &&Pass,
bool NoRerun = false) {
using PassModelT =
detail::PassModel<Function, FunctionPassT, FunctionAnalysisManager>;
- // Do not use make_unique, it causes too many template instantiations,
- // causing terrible compile times.
- return CGSCCToFunctionPassAdaptor(
- CGSCCToFunctionPassAdaptor::PassConceptT::unique_ptr(
- new PassModelT(std::forward<FunctionPassT>(Pass))),
- EagerlyInvalidate, NoRerun);
+ return CGSCCToFunctionPassAdaptor(PassModelT::create(std::move(Pass)),
+ EagerlyInvalidate, NoRerun);
}
// A marker to determine if function passes should be run on a function within a
@@ -577,12 +569,8 @@ DevirtSCCRepeatedPass createDevirtSCCRepeatedPass(CGSCCPassT &&Pass,
using PassModelT =
detail::PassModel<LazyCallGraph::SCC, CGSCCPassT, CGSCCAnalysisManager,
LazyCallGraph &, CGSCCUpdateResult &>;
- // Do not use make_unique, it causes too many template instantiations,
- // causing terrible compile times.
- return DevirtSCCRepeatedPass(
- DevirtSCCRepeatedPass::PassConceptT::unique_ptr(
- new PassModelT(std::forward<CGSCCPassT>(Pass))),
- MaxIterations);
+ return DevirtSCCRepeatedPass(PassModelT::create(std::move(Pass)),
+ MaxIterations);
}
// Clear out the debug logging macro.
diff --git a/llvm/include/llvm/CodeGen/MachinePassManager.h b/llvm/include/llvm/CodeGen/MachinePassManager.h
index 5de520fa550f8..f4d5ab4d55b2d 100644
--- a/llvm/include/llvm/CodeGen/MachinePassManager.h
+++ b/llvm/include/llvm/CodeGen/MachinePassManager.h
@@ -212,11 +212,8 @@ FunctionToMachineFunctionPassAdaptor
createFunctionToMachineFunctionPassAdaptor(MachineFunctionPassT &&Pass) {
using PassModelT = detail::PassModel<MachineFunction, MachineFunctionPassT,
MachineFunctionAnalysisManager>;
- // Do not use make_unique, it causes too many template instantiations,
- // causing terrible compile times.
return FunctionToMachineFunctionPassAdaptor(
- FunctionToMachineFunctionPassAdaptor::PassConceptT::unique_ptr(
- new PassModelT(std::forward<MachineFunctionPassT>(Pass))));
+ PassModelT::create(std::move(Pass)));
}
template <>
diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h
index 0c6dac6be8d31..adb375f4f837a 100644
--- a/llvm/include/llvm/IR/PassManager.h
+++ b/llvm/include/llvm/IR/PassManager.h
@@ -220,10 +220,7 @@ class PassManager : public RequiredPassInfoMixin<
addPass(PassT &&Pass) {
using PassModelT =
detail::PassModel<IRUnitT, PassT, AnalysisManagerT, ExtraArgTs...>;
- // Do not use make_unique or emplace_back, they cause too many template
- // instantiations, causing terrible compile times.
- Passes.push_back(typename PassConceptT::unique_ptr(
- new PassModelT(std::forward<PassT>(Pass))));
+ Passes.push_back(PassModelT::create(std::move(Pass)));
}
/// When adding a pass manager pass that has the same type as this pass
@@ -898,12 +895,8 @@ createModuleToFunctionPassAdaptor(FunctionPassT &&Pass,
bool EagerlyInvalidate = false) {
using PassModelT =
detail::PassModel<Function, FunctionPassT, FunctionAnalysisManager>;
- // Do not use make_unique, it causes too many template instantiations,
- // causing terrible compile times.
- return ModuleToFunctionPassAdaptor(
- ModuleToFunctionPassAdaptor::PassConceptT::unique_ptr(
- new PassModelT(std::forward<FunctionPassT>(Pass))),
- EagerlyInvalidate);
+ return ModuleToFunctionPassAdaptor(PassModelT::create(std::move(Pass)),
+ EagerlyInvalidate);
}
/// A utility pass template to force an analysis result to be available.
diff --git a/llvm/include/llvm/IR/PassManagerInternal.h b/llvm/include/llvm/IR/PassManagerInternal.h
index d731bc56a2820..376dcd7d3af62 100644
--- a/llvm/include/llvm/IR/PassManagerInternal.h
+++ b/llvm/include/llvm/IR/PassManagerInternal.h
@@ -134,11 +134,15 @@ class PassModel final
getPass(Self).printPipeline(OS, MapClassName2PassName);
}
-public:
- explicit PassModel(PassT Pass)
+ explicit PassModel(PassT &&Pass)
: PassConceptT(PassT::name(), PassT::isRequired(), destroyImpl, runImpl,
printPipelineImpl),
Pass(std::move(Pass)) {}
+
+public:
+ static typename PassConceptT::unique_ptr create(PassT &&Pass) {
+ return typename PassConceptT::unique_ptr(new PassModel(std::move(Pass)));
+ }
};
/// Abstract concept of an analysis result.
diff --git a/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h b/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h
index e11af53a47142..bb882096142f7 100644
--- a/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h
+++ b/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h
@@ -111,19 +111,13 @@ class PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
detail::PassModel<Loop, PassT, LoopAnalysisManager,
LoopStandardAnalysisResults &, LPMUpdater &>;
IsLoopNestPass.push_back(false);
- // Do not use make_unique or emplace_back, they cause too many template
- // instantiations, causing terrible compile times.
- LoopPasses.push_back(LoopPassConceptT::unique_ptr(
- new LoopPassModelT(std::forward<PassT>(Pass))));
+ LoopPasses.push_back(LoopPassModelT::create(std::move(Pass)));
} else {
using LoopNestPassModelT =
detail::PassModel<LoopNest, PassT, LoopAnalysisManager,
LoopStandardAnalysisResults &, LPMUpdater &>;
IsLoopNestPass.push_back(true);
- // Do not use make_unique or emplace_back, they cause too many template
- // instantiations, causing terrible compile times.
- LoopNestPasses.push_back(LoopNestPassConceptT::unique_ptr(
- new LoopNestPassModelT(std::forward<PassT>(Pass))));
+ LoopNestPasses.push_back(LoopNestPassModelT::create(std::move(Pass)));
}
}
@@ -440,24 +434,16 @@ createFunctionToLoopPassAdaptor(LoopPassT &&Pass, bool UseMemorySSA = false) {
using PassModelT =
detail::PassModel<Loop, LoopPassT, LoopAnalysisManager,
LoopStandardAnalysisResults &, LPMUpdater &>;
- // Do not use make_unique, it causes too many template instantiations,
- // causing terrible compile times.
- return FunctionToLoopPassAdaptor(
- FunctionToLoopPassAdaptor::PassConceptT::unique_ptr(
- new PassModelT(std::forward<LoopPassT>(Pass))),
- UseMemorySSA, false);
+ return FunctionToLoopPassAdaptor(PassModelT::create(std::move(Pass)),
+ UseMemorySSA, false);
} else {
LoopPassManager LPM;
- LPM.addPass(std::forward<LoopPassT>(Pass));
+ LPM.addPass(std::move(Pass));
using PassModelT =
detail::PassModel<Loop, LoopPassManager, LoopAnalysisManager,
LoopStandardAnalysisResults &, LPMUpdater &>;
- // Do not use make_unique, it causes too many template instantiations,
- // causing terrible compile times.
- return FunctionToLoopPassAdaptor(
- FunctionToLoopPassAdaptor::PassConceptT::unique_ptr(
- new PassModelT(std::move(LPM))),
- UseMemorySSA, true);
+ return FunctionToLoopPassAdaptor(PassModelT::create(std::move(LPM)),
+ UseMemorySSA, true);
}
}
@@ -473,12 +459,8 @@ createFunctionToLoopPassAdaptor<LoopPassManager>(LoopPassManager &&LPM,
detail::PassModel<Loop, LoopPassManager, LoopAnalysisManager,
LoopStandardAnalysisResults &, LPMUpdater &>;
bool LoopNestMode = (LPM.getNumLoopPasses() == 0);
- // Do not use make_unique, it causes too many template instantiations,
- // causing terrible compile times.
- return FunctionToLoopPassAdaptor(
- FunctionToLoopPassAdaptor::PassConceptT::unique_ptr(
- new PassModelT(std::move(LPM))),
- UseMemorySSA, LoopNestMode);
+ return FunctionToLoopPassAdaptor(PassModelT::create(std::move(LPM)),
+ UseMemorySSA, LoopNestMode);
}
/// Pass for printing a loop's contents as textual IR.
More information about the llvm-commits
mailing list