[PM] Add names and debug logging for analysis passes to the new pass
[oota-llvm.git] / include / llvm / IR / PassManagerInternal.h
1 //===- PassManager internal APIs and implementation details -----*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 ///
11 /// This header provides internal APIs and implementation details used by the
12 /// pass management interfaces exposed in PassManager.h. To understand more
13 /// context of why these particular interfaces are needed, see that header
14 /// file. None of these APIs should be used elsewhere.
15 ///
16 //===----------------------------------------------------------------------===//
17
18 #ifndef LLVM_IR_PASSMANAGERINTERNAL_H
19 #define LLVM_IR_PASSMANAGERINTERNAL_H
20
21 #include "llvm/ADT/StringRef.h"
22
23 namespace llvm {
24
25 class Function;
26 class Module;
27 class PreservedAnalyses;
28
29 /// \brief Implementation details of the pass manager interfaces.
30 namespace detail {
31
32 /// \brief Template for the abstract base class used to dispatch
33 /// polymorphically over pass objects.
34 template <typename IRUnitT, typename AnalysisManagerT> struct PassConcept {
35   // Boiler plate necessary for the container of derived classes.
36   virtual ~PassConcept() {}
37
38   /// \brief The polymorphic API which runs the pass over a given IR entity.
39   ///
40   /// Note that actual pass object can omit the analysis manager argument if
41   /// desired. Also that the analysis manager may be null if there is no
42   /// analysis manager in the pass pipeline.
43   virtual PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) = 0;
44
45   /// \brief Polymorphic method to access the name of a pass.
46   virtual StringRef name() = 0;
47 };
48
49 /// \brief SFINAE metafunction for computing whether \c PassT has a run method
50 /// accepting an \c AnalysisManagerT.
51 template <typename IRUnitT, typename AnalysisManagerT, typename PassT,
52           typename ResultT>
53 class PassRunAcceptsAnalysisManager {
54   typedef char SmallType;
55   struct BigType {
56     char a, b;
57   };
58
59   template <typename T, ResultT (T::*)(IRUnitT, AnalysisManagerT *)>
60   struct Checker;
61
62   template <typename T> static SmallType f(Checker<T, &T::run> *);
63   template <typename T> static BigType f(...);
64
65 public:
66   enum { Value = sizeof(f<PassT>(nullptr)) == sizeof(SmallType) };
67 };
68
69 /// \brief A template wrapper used to implement the polymorphic API.
70 ///
71 /// Can be instantiated for any object which provides a \c run method accepting
72 /// an \c IRUnitT. It requires the pass to be a copyable object. When the
73 /// \c run method also accepts an \c AnalysisManagerT*, we pass it along.
74 template <typename IRUnitT, typename AnalysisManagerT, typename PassT,
75           typename PreservedAnalysesT = PreservedAnalyses,
76           bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
77               IRUnitT, AnalysisManagerT, PassT, PreservedAnalysesT>::Value>
78 struct PassModel;
79
80 /// \brief Specialization of \c PassModel for passes that accept an analyis
81 /// manager.
82 template <typename IRUnitT, typename AnalysisManagerT, typename PassT,
83           typename PreservedAnalysesT>
84 struct PassModel<IRUnitT, AnalysisManagerT, PassT, PreservedAnalysesT, true>
85     : PassConcept<IRUnitT, AnalysisManagerT> {
86   explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
87   // We have to explicitly define all the special member functions because MSVC
88   // refuses to generate them.
89   PassModel(const PassModel &Arg) : Pass(Arg.Pass) {}
90   PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
91   friend void swap(PassModel &LHS, PassModel &RHS) {
92     using std::swap;
93     swap(LHS.Pass, RHS.Pass);
94   }
95   PassModel &operator=(PassModel RHS) {
96     swap(*this, RHS);
97     return *this;
98   }
99
100   PreservedAnalysesT run(IRUnitT IR, AnalysisManagerT *AM) override {
101     return Pass.run(IR, AM);
102   }
103   StringRef name() override { return PassT::name(); }
104   PassT Pass;
105 };
106
107 /// \brief Specialization of \c PassModel for passes that accept an analyis
108 /// manager.
109 template <typename IRUnitT, typename AnalysisManagerT, typename PassT,
110           typename PreservedAnalysesT>
111 struct PassModel<IRUnitT, AnalysisManagerT, PassT, PreservedAnalysesT, false>
112     : PassConcept<IRUnitT, AnalysisManagerT> {
113   explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
114   // We have to explicitly define all the special member functions because MSVC
115   // refuses to generate them.
116   PassModel(const PassModel &Arg) : Pass(Arg.Pass) {}
117   PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
118   friend void swap(PassModel &LHS, PassModel &RHS) {
119     using std::swap;
120     swap(LHS.Pass, RHS.Pass);
121   }
122   PassModel &operator=(PassModel RHS) {
123     swap(*this, RHS);
124     return *this;
125   }
126
127   PreservedAnalysesT run(IRUnitT IR, AnalysisManagerT *AM) override {
128     return Pass.run(IR);
129   }
130   StringRef name() override { return PassT::name(); }
131   PassT Pass;
132 };
133
134 /// \brief Abstract concept of an analysis result.
135 ///
136 /// This concept is parameterized over the IR unit that this result pertains
137 /// to.
138 template <typename IRUnitT> struct AnalysisResultConcept {
139   virtual ~AnalysisResultConcept() {}
140
141   /// \brief Method to try and mark a result as invalid.
142   ///
143   /// When the outer analysis manager detects a change in some underlying
144   /// unit of the IR, it will call this method on all of the results cached.
145   ///
146   /// This method also receives a set of preserved analyses which can be used
147   /// to avoid invalidation because the pass which changed the underlying IR
148   /// took care to update or preserve the analysis result in some way.
149   ///
150   /// \returns true if the result is indeed invalid (the default).
151   virtual bool invalidate(IRUnitT IR, const PreservedAnalyses &PA) = 0;
152 };
153
154 /// \brief SFINAE metafunction for computing whether \c ResultT provides an
155 /// \c invalidate member function.
156 template <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod {
157   typedef char SmallType;
158   struct BigType {
159     char a, b;
160   };
161
162   template <typename T, bool (T::*)(IRUnitT, const PreservedAnalyses &)>
163   struct Checker;
164
165   template <typename T> static SmallType f(Checker<T, &T::invalidate> *);
166   template <typename T> static BigType f(...);
167
168 public:
169   enum { Value = sizeof(f<ResultT>(nullptr)) == sizeof(SmallType) };
170 };
171
172 /// \brief Wrapper to model the analysis result concept.
173 ///
174 /// By default, this will implement the invalidate method with a trivial
175 /// implementation so that the actual analysis result doesn't need to provide
176 /// an invalidation handler. It is only selected when the invalidation handler
177 /// is not part of the ResultT's interface.
178 template <typename IRUnitT, typename PassT, typename ResultT,
179           typename PreservedAnalysesT = PreservedAnalyses,
180           bool HasInvalidateHandler =
181               ResultHasInvalidateMethod<IRUnitT, ResultT>::Value>
182 struct AnalysisResultModel;
183
184 /// \brief Specialization of \c AnalysisResultModel which provides the default
185 /// invalidate functionality.
186 template <typename IRUnitT, typename PassT, typename ResultT,
187           typename PreservedAnalysesT>
188 struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT, false>
189     : AnalysisResultConcept<IRUnitT> {
190   explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
191   // We have to explicitly define all the special member functions because MSVC
192   // refuses to generate them.
193   AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
194   AnalysisResultModel(AnalysisResultModel &&Arg)
195       : Result(std::move(Arg.Result)) {}
196   friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
197     using std::swap;
198     swap(LHS.Result, RHS.Result);
199   }
200   AnalysisResultModel &operator=(AnalysisResultModel RHS) {
201     swap(*this, RHS);
202     return *this;
203   }
204
205   /// \brief The model bases invalidation solely on being in the preserved set.
206   //
207   // FIXME: We should actually use two different concepts for analysis results
208   // rather than two different models, and avoid the indirect function call for
209   // ones that use the trivial behavior.
210   bool invalidate(IRUnitT, const PreservedAnalysesT &PA) override {
211     return !PA.preserved(PassT::ID());
212   }
213
214   ResultT Result;
215 };
216
217 /// \brief Specialization of \c AnalysisResultModel which delegates invalidate
218 /// handling to \c ResultT.
219 template <typename IRUnitT, typename PassT, typename ResultT,
220           typename PreservedAnalysesT>
221 struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT, true>
222     : AnalysisResultConcept<IRUnitT> {
223   explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
224   // We have to explicitly define all the special member functions because MSVC
225   // refuses to generate them.
226   AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
227   AnalysisResultModel(AnalysisResultModel &&Arg)
228       : Result(std::move(Arg.Result)) {}
229   friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
230     using std::swap;
231     swap(LHS.Result, RHS.Result);
232   }
233   AnalysisResultModel &operator=(AnalysisResultModel RHS) {
234     swap(*this, RHS);
235     return *this;
236   }
237
238   /// \brief The model delegates to the \c ResultT method.
239   bool invalidate(IRUnitT IR, const PreservedAnalysesT &PA) override {
240     return Result.invalidate(IR, PA);
241   }
242
243   ResultT Result;
244 };
245
246 /// \brief Abstract concept of an analysis pass.
247 ///
248 /// This concept is parameterized over the IR unit that it can run over and
249 /// produce an analysis result.
250 template <typename IRUnitT, typename AnalysisManagerT>
251 struct AnalysisPassConcept {
252   virtual ~AnalysisPassConcept() {}
253
254   /// \brief Method to run this analysis over a unit of IR.
255   /// \returns A unique_ptr to the analysis result object to be queried by
256   /// users.
257   virtual std::unique_ptr<AnalysisResultConcept<IRUnitT>>
258   run(IRUnitT IR, AnalysisManagerT *AM) = 0;
259
260   /// \brief Polymorphic method to access the name of a pass.
261   virtual StringRef name() = 0;
262 };
263
264 /// \brief Wrapper to model the analysis pass concept.
265 ///
266 /// Can wrap any type which implements a suitable \c run method. The method
267 /// must accept the IRUnitT as an argument and produce an object which can be
268 /// wrapped in a \c AnalysisResultModel.
269 template <typename IRUnitT, typename AnalysisManagerT, typename PassT,
270           bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
271               IRUnitT, AnalysisManagerT, PassT, typename PassT::Result>::Value>
272 struct AnalysisPassModel;
273
274 /// \brief Specialization of \c AnalysisPassModel which passes an
275 /// \c AnalysisManager to PassT's run method.
276 template <typename IRUnitT, typename AnalysisManagerT, typename PassT>
277 struct AnalysisPassModel<IRUnitT, AnalysisManagerT, PassT, true>
278     : AnalysisPassConcept<IRUnitT, AnalysisManagerT> {
279   explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
280   // We have to explicitly define all the special member functions because MSVC
281   // refuses to generate them.
282   AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {}
283   AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
284   friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
285     using std::swap;
286     swap(LHS.Pass, RHS.Pass);
287   }
288   AnalysisPassModel &operator=(AnalysisPassModel RHS) {
289     swap(*this, RHS);
290     return *this;
291   }
292
293   // FIXME: Replace PassT::Result with type traits when we use C++11.
294   typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
295       ResultModelT;
296
297   /// \brief The model delegates to the \c PassT::run method.
298   ///
299   /// The return is wrapped in an \c AnalysisResultModel.
300   std::unique_ptr<AnalysisResultConcept<IRUnitT>>
301   run(IRUnitT IR, AnalysisManagerT *AM) override {
302     return make_unique<ResultModelT>(Pass.run(IR, AM));
303   }
304
305   /// \brief The model delegates to a static \c PassT::name method.
306   ///
307   /// The returned string ref must point to constant immutable data!
308   StringRef name() override { return PassT::name(); }
309
310   PassT Pass;
311 };
312
313 /// \brief Specialization of \c AnalysisPassModel which does not pass an
314 /// \c AnalysisManager to PassT's run method.
315 template <typename IRUnitT, typename AnalysisManagerT, typename PassT>
316 struct AnalysisPassModel<IRUnitT, AnalysisManagerT, PassT, false>
317     : AnalysisPassConcept<IRUnitT, AnalysisManagerT> {
318   explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
319   // We have to explicitly define all the special member functions because MSVC
320   // refuses to generate them.
321   AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {}
322   AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
323   friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
324     using std::swap;
325     swap(LHS.Pass, RHS.Pass);
326   }
327   AnalysisPassModel &operator=(AnalysisPassModel RHS) {
328     swap(*this, RHS);
329     return *this;
330   }
331
332   // FIXME: Replace PassT::Result with type traits when we use C++11.
333   typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
334       ResultModelT;
335
336   /// \brief The model delegates to the \c PassT::run method.
337   ///
338   /// The return is wrapped in an \c AnalysisResultModel.
339   std::unique_ptr<AnalysisResultConcept<IRUnitT>>
340   run(IRUnitT IR, AnalysisManagerT *) override {
341     return make_unique<ResultModelT>(Pass.run(IR));
342   }
343
344   /// \brief The model delegates to a static \c PassT::name method.
345   ///
346   /// The returned string ref must point to constant immutable data!
347   StringRef name() override { return PassT::name(); }
348
349   PassT Pass;
350 };
351
352 } // End namespace detail
353 }
354
355 #endif