LLVM 24.0.0git
PassManagerInternal.h
Go to the documentation of this file.
1//===- PassManager internal APIs and implementation details -----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9///
10/// This header provides internal APIs and implementation details used by the
11/// pass management interfaces exposed in PassManager.h. To understand more
12/// context of why these particular interfaces are needed, see that header
13/// file. None of these APIs should be used elsewhere.
14///
15//===----------------------------------------------------------------------===//
16
17#ifndef LLVM_IR_PASSMANAGERINTERNAL_H
18#define LLVM_IR_PASSMANAGERINTERNAL_H
19
20#include "llvm/ADT/STLExtras.h"
21#include "llvm/ADT/StringRef.h"
22#include "llvm/IR/Analysis.h"
24#include <memory>
25#include <type_traits>
26#include <utility>
27
28namespace llvm {
29
30template <typename IRUnitT> class AllAnalysesOn;
31template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager;
33
34// Implementation details of the pass manager interfaces.
35namespace detail {
36
37/// Template for the abstract base class used to dispatch over pass objects.
38/// This doesn't use virtual functions to avoid vtables, which cost a fair
39/// amount of storage that needs to be relocated in PIC builds and add an extra
40/// indirection on dispatch.
41template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
43private:
44 using DestroyTy = void (*)(PassConcept &);
45 using RunTy = PreservedAnalyses (*)(PassConcept &, IRUnitT &,
46 AnalysisManagerT &, ExtraArgTs...);
47 using PrintPipelineTy =
48 void (*)(PassConcept &, raw_ostream &,
49 function_ref<StringRef(StringRef)> MapClassName2PassName);
50
51public:
52 struct Deleter {
53 void operator()(PassConcept *P) { P->Destroy(*P); }
54 };
55
56 using unique_ptr = std::unique_ptr<PassConcept, Deleter>;
57
58private:
59 StringRef Name;
60 bool IsRequired;
61
62 DestroyTy Destroy;
63 RunTy Run;
64 PrintPipelineTy PrintPipeline;
65
66protected:
67 PassConcept(StringRef Name, bool IsRequired, DestroyTy Destroy, RunTy Run,
68 PrintPipelineTy PrintPipeline)
69 : Name(Name), IsRequired(IsRequired), Destroy(Destroy), Run(Run),
70 PrintPipeline(PrintPipeline) {}
71
72 // Note: this is intentionally not public to catch uses of delete and
73 // unique_ptr<PassConcept>.
74 void operator delete(void *P) { ::operator delete(P); }
75
76public:
77 // Passes are immovable.
78 PassConcept(const PassConcept &) = delete;
79 PassConcept &operator=(const PassConcept &) = delete;
80
81 /// Run the pass.
82 PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
83 ExtraArgTs... ExtraArgs) {
84 return Run(*this, IR, AM, std::forward<ExtraArgTs>(ExtraArgs)...);
85 }
86
88 function_ref<StringRef(StringRef)> MapClassName2PassName) {
89 PrintPipeline(*this, OS, MapClassName2PassName);
90 }
91
92 /// Get name of a pass.
93 StringRef name() const { return Name; }
94
95 /// Indicate whether a pass can optionally be exempted from skipping by
96 /// PassInstrumentation.
97 /// To opt-in, pass should implement `static bool isRequired()`, or inherit
98 /// from `RequiredPassInfoMixin` or `OptionalPassInfoMixin`.
99 /// It's no-op to have `isRequired` always return false since that is the
100 /// default.
101 bool isRequired() const { return IsRequired; }
102};
103
104/// A template wrapper used to implement PassConcept.
105///
106/// Can be instantiated for any object which provides a \c run method accepting
107/// an \c IRUnitT& and an \c AnalysisManager<IRUnit>&.
108template <typename IRUnitT, typename PassT, typename AnalysisManagerT,
109 typename... ExtraArgTs>
110class PassModel final
111 : public PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> {
112private:
113 using PassConceptT = PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...>;
114
115 PassT Pass;
116
117 static PassT &getPass(PassConceptT &Self) {
118 return static_cast<PassModel &>(Self).Pass;
119 }
120
121 static void destroyImpl(PassConceptT &Self) {
122 delete static_cast<PassModel *>(&Self);
123 }
124
125 static PreservedAnalyses runImpl(PassConceptT &Self, IRUnitT &IR,
126 AnalysisManagerT &AM,
127 ExtraArgTs... ExtraArgs) {
128 return getPass(Self).run(IR, AM, ExtraArgs...);
129 }
130
131 static void
132 printPipelineImpl(PassConceptT &Self, raw_ostream &OS,
133 function_ref<StringRef(StringRef)> MapClassName2PassName) {
134 getPass(Self).printPipeline(OS, MapClassName2PassName);
135 }
136
137 explicit PassModel(PassT &&Pass)
138 : PassConceptT(PassT::name(), PassT::isRequired(), destroyImpl, runImpl,
139 printPipelineImpl),
140 Pass(std::move(Pass)) {}
141
142public:
143 static typename PassConceptT::unique_ptr create(PassT &&Pass) {
144 return typename PassConceptT::unique_ptr(new PassModel(std::move(Pass)));
145 }
146};
147
148/// Abstract concept of an analysis result.
149///
150/// This concept is parameterized over the IR unit that this result pertains
151/// to.
152template <typename IRUnitT, typename InvalidatorT>
154private:
155 using DestroyTy = void (*)(AnalysisResultConcept &);
156 using InvalidateTy = bool (*)(AnalysisResultConcept &, IRUnitT &,
157 const PreservedAnalyses &, InvalidatorT &);
158
159public:
160 struct Deleter {
161 void operator()(AnalysisResultConcept *C) { C->Destroy(*C); }
162 };
163
164 using unique_ptr = std::unique_ptr<AnalysisResultConcept, Deleter>;
165
166protected:
167 DestroyTy Destroy;
168 InvalidateTy Invalidate = nullptr;
169
171
172public:
173 /// Method to try and mark a result as invalid.
174 ///
175 /// When the outer analysis manager detects a change in some underlying
176 /// unit of the IR, it will call this method on all of the results cached.
177 ///
178 /// \p PA is a set of preserved analyses which can be used to avoid
179 /// invalidation because the pass which changed the underlying IR took care
180 /// to update or preserve the analysis result in some way.
181 ///
182 /// \p Inv is typically a \c AnalysisManager::Invalidator object that can be
183 /// used by a particular analysis result to discover if other analyses
184 /// results are also invalidated in the event that this result depends on
185 /// them. See the documentation in the \c AnalysisManager for more details.
186 ///
187 /// \returns true if the result is indeed invalid (the default).
188 bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA, InvalidatorT &Inv) {
189 return Invalidate(*this, IR, PA, Inv);
190 }
191};
192
193/// SFINAE metafunction for computing whether \c ResultT provides an
194/// \c invalidate member function.
195template <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod {
196 using EnabledType = char;
197 struct DisabledType {
198 char a, b;
199 };
200
201 // Purely to help out MSVC which fails to disable the below specialization,
202 // explicitly enable using the result type's invalidate routine if we can
203 // successfully call that routine.
204 template <typename T> struct Nonce { using Type = EnabledType; };
205 template <typename T>
206 static typename Nonce<decltype(std::declval<T>().invalidate(
207 std::declval<IRUnitT &>(), std::declval<PreservedAnalyses>()))>::Type
208 check(rank<2>);
209
210 // First we define an overload that can only be taken if there is no
211 // invalidate member. We do this by taking the address of an invalidate
212 // member in an adjacent base class of a derived class. This would be
213 // ambiguous if there were an invalidate member in the result type.
214 template <typename T, typename U> static DisabledType NonceFunction(T U::*);
215 struct CheckerBase { int invalidate; };
216 template <typename T> struct Checker : CheckerBase, std::remove_cv_t<T> {};
217 template <typename T>
218 static decltype(NonceFunction(&Checker<T>::invalidate)) check(rank<1>);
219
220 // Now we have the fallback that will only be reached when there is an
221 // invalidate member, and enables the trait.
222 template <typename T>
223 static EnabledType check(rank<0>);
224
225public:
226 enum { Value = sizeof(check<ResultT>(rank<2>())) == sizeof(EnabledType) };
227};
228
229/// Wrapper to model the analysis result concept.
230template <typename IRUnitT, typename PassT, typename ResultT,
231 typename InvalidatorT>
233 : public AnalysisResultConcept<IRUnitT, InvalidatorT> {
235
236 ResultT Result;
237
239 delete static_cast<AnalysisResultModel *>(&Self);
240 }
241
242 template <typename... ExtraArgTs>
243 AnalysisResultModel(PassT &Pass, IRUnitT &IR,
245 ExtraArgTs &&...ExtraArgs)
247 Result(Pass.run(IR, AM, std::forward<ExtraArgTs>(ExtraArgs)...)) {
248 this->Invalidate = [](AnalysisResultConceptT &Self, IRUnitT &IR,
249 const PreservedAnalyses &PA, InvalidatorT &Inv) {
251 ResultT &Result = static_cast<AnalysisResultModel &>(Self).Result;
252 return Result.invalidate(IR, PA, Inv);
253 }
254 auto PAC = PA.template getChecker<PassT>();
255 return !PAC.preserved() &&
256 !PAC.template preservedSet<AllAnalysesOn<IRUnitT>>();
257 };
258 }
259};
260
261/// Abstract concept of an analysis pass.
262///
263/// This concept is parameterized over the IR unit that it can run over and
264/// produce an analysis result.
265template <typename IRUnitT, typename InvalidatorT, typename... ExtraArgTs>
267public:
270 using AnalysisManagerT = AnalysisManager<IRUnitT, ExtraArgTs...>;
271
272 struct Deleter {
273 void operator()(AnalysisPassConcept *P) { P->Destroy(*P); }
274 };
275 using unique_ptr = std::unique_ptr<AnalysisPassConcept, Deleter>;
276
277private:
278 using DestroyTy = void (*)(AnalysisPassConcept &);
279 using RunTy = ResultPtrT (*)(AnalysisPassConcept &, IRUnitT &,
280 AnalysisManagerT &, ExtraArgTs &&...);
281
282 StringRef Name;
283
284 DestroyTy Destroy;
285 RunTy Run;
286
287protected:
288 AnalysisPassConcept(StringRef Name, DestroyTy Destroy, RunTy Run)
289 : Name(Name), Destroy(Destroy), Run(Run) {}
290
291public:
292 // Passes are immovable.
295
296 /// Method to run this analysis over a unit of IR.
297 /// \returns A unique_ptr to the analysis result object to be queried by
298 /// users.
299 ResultPtrT run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs &&...ExtraArgs) {
300 return Run(*this, IR, AM, std::forward<ExtraArgTs>(ExtraArgs)...);
301 }
302
303 /// Get the name of the pass.
304 StringRef name() const { return Name; }
305};
306
307/// Wrapper to model the analysis pass concept.
308///
309/// Can wrap any type which implements a suitable \c run method. The method
310/// must accept an \c IRUnitT& and an \c AnalysisManager<IRUnitT>& as arguments
311/// and produce an object which can be wrapped in a \c AnalysisResultModel.
312template <typename IRUnitT, typename PassT, typename InvalidatorT,
313 typename... ExtraArgTs>
314class AnalysisPassModel final
315 : public AnalysisPassConcept<IRUnitT, InvalidatorT, ExtraArgTs...> {
316 using AnalysisPassConceptT =
317 AnalysisPassConcept<IRUnitT, InvalidatorT, ExtraArgTs...>;
318 using ResultModelT =
320
321 PassT Pass;
322
323 static void destroyImpl(AnalysisPassConceptT &Self) {
324 delete static_cast<AnalysisPassModel *>(&Self);
325 }
326
327 static typename ResultModelT::unique_ptr
328 runImpl(AnalysisPassConceptT &Self, IRUnitT &IR,
330 ExtraArgTs &&...ExtraArgs) {
331 PassT &Pass = static_cast<AnalysisPassModel &>(Self).Pass;
332 return typename ResultModelT::unique_ptr(
333 new ResultModelT(Pass, IR, AM, std::forward<ExtraArgTs>(ExtraArgs)...));
334 }
335
336 explicit AnalysisPassModel(PassT &&Pass)
337 : AnalysisPassConceptT(PassT::name(), destroyImpl, runImpl),
338 Pass(std::move(Pass)) {}
339
340public:
341 static typename AnalysisPassConceptT::unique_ptr create(PassT &&Pass) {
342 return typename AnalysisPassConceptT::unique_ptr(
343 new AnalysisPassModel(std::move(Pass)));
344 }
345};
346
347} // end namespace detail
348
349} // end namespace llvm
350
351#endif // LLVM_IR_PASSMANAGERINTERNAL_H
Legalize the Machine IR a function s Machine IR
Definition Legalizer.cpp:81
print mir2vec MIR2Vec Vocabulary Printer Pass
Definition MIR2Vec.cpp:598
#define T
#define P(N)
This file contains some templates that are useful if you are working with the STL at all.
This templated class represents "all analyses that operate over <aparticular IR unit>" (e....
Definition Analysis.h:50
A container for analyses that lazily runs them and caches their results.
Pass interface - Implemented by all 'passes'.
Definition Pass.h:99
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
AnalysisPassConcept(const AnalysisPassConcept &)=delete
typename AnalysisResultConcept< IRUnitT, Invalidator >::unique_ptr ResultPtrT
AnalysisPassConcept & operator=(const AnalysisPassConcept &)=delete
AnalysisPassConcept(StringRef Name, DestroyTy Destroy, RunTy Run)
ResultPtrT run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs &&...ExtraArgs)
Method to run this analysis over a unit of IR.
StringRef name() const
Get the name of the pass.
static AnalysisPassConceptT::unique_ptr create(PassT &&Pass)
PassConcept(const PassConcept &)=delete
PassConcept & operator=(const PassConcept &)=delete
PassConcept(StringRef Name, bool IsRequired, DestroyTy Destroy, RunTy Run, PrintPipelineTy PrintPipeline)
bool isRequired() const
Indicate whether a pass can optionally be exempted from skipping by PassInstrumentation.
void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
StringRef name() const
Get name of a pass.
PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs)
Run the pass.
static PassConceptT::unique_ptr create(PassT &&Pass)
SFINAE metafunction for computing whether ResultT provides an invalidate member function.
An efficient, type-erasing, non-owning reference to a callable.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
Pass manager infrastructure for declaring and invalidating analyses.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
A self-contained host- and target-independent arbitrary-precision floating-point software implementat...
Definition ADL.h:123
This is an optimization pass for GlobalISel generic memory operations.
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
std::unique_ptr< AnalysisResultConcept, Deleter > unique_ptr
bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA, InvalidatorT &Inv)
Method to try and mark a result as invalid.
Wrapper to model the analysis result concept.
AnalysisResultModel(PassT &Pass, IRUnitT &IR, AnalysisManager< IRUnitT, ExtraArgTs... > &AM, ExtraArgTs &&...ExtraArgs)
static void destroyImpl(AnalysisResultConceptT &Self)
AnalysisResultConcept< IRUnitT, InvalidatorT > AnalysisResultConceptT
Utility type to build an inheritance chain that makes it easy to rank overload candidates.
Definition STLExtras.h:1468