LLVM  4.0.0
PassManagerInternal.h
Go to the documentation of this file.
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/STLExtras.h"
22 #include "llvm/ADT/StringRef.h"
23 #include <memory>
24 #include <utility>
25 
26 namespace llvm {
27 
28 template <typename IRUnitT> class AllAnalysesOn;
29 template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager;
30 class Invalidator;
31 class PreservedAnalyses;
32 
33 /// \brief Implementation details of the pass manager interfaces.
34 namespace detail {
35 
36 /// \brief Template for the abstract base class used to dispatch
37 /// polymorphically over pass objects.
38 template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
39 struct PassConcept {
40  // Boiler plate necessary for the container of derived classes.
41  virtual ~PassConcept() = default;
42 
43  /// \brief The polymorphic API which runs the pass over a given IR entity.
44  ///
45  /// Note that actual pass object can omit the analysis manager argument if
46  /// desired. Also that the analysis manager may be null if there is no
47  /// analysis manager in the pass pipeline.
48  virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
49  ExtraArgTs... ExtraArgs) = 0;
50 
51  /// \brief Polymorphic method to access the name of a pass.
52  virtual StringRef name() = 0;
53 };
54 
55 /// \brief A template wrapper used to implement the polymorphic API.
56 ///
57 /// Can be instantiated for any object which provides a \c run method accepting
58 /// an \c IRUnitT& and an \c AnalysisManager<IRUnit>&. It requires the pass to
59 /// be a copyable object.
60 template <typename IRUnitT, typename PassT, typename PreservedAnalysesT,
61  typename AnalysisManagerT, typename... ExtraArgTs>
62 struct PassModel : PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> {
63  explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
64  // We have to explicitly define all the special member functions because MSVC
65  // refuses to generate them.
66  PassModel(const PassModel &Arg) : Pass(Arg.Pass) {}
67  PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
68 
69  friend void swap(PassModel &LHS, PassModel &RHS) {
70  using std::swap;
71  swap(LHS.Pass, RHS.Pass);
72  }
73 
75  swap(*this, RHS);
76  return *this;
77  }
78 
79  PreservedAnalysesT run(IRUnitT &IR, AnalysisManagerT &AM,
80  ExtraArgTs... ExtraArgs) override {
81  return Pass.run(IR, AM, ExtraArgs...);
82  }
83 
84  StringRef name() override { return PassT::name(); }
85 
86  PassT Pass;
87 };
88 
89 /// \brief Abstract concept of an analysis result.
90 ///
91 /// This concept is parameterized over the IR unit that this result pertains
92 /// to.
93 template <typename IRUnitT, typename PreservedAnalysesT, typename InvalidatorT>
95  virtual ~AnalysisResultConcept() = default;
96 
97  /// \brief Method to try and mark a result as invalid.
98  ///
99  /// When the outer analysis manager detects a change in some underlying
100  /// unit of the IR, it will call this method on all of the results cached.
101  ///
102  /// \p PA is a set of preserved analyses which can be used to avoid
103  /// invalidation because the pass which changed the underlying IR took care
104  /// to update or preserve the analysis result in some way.
105  ///
106  /// \p Inv is typically a \c AnalysisManager::Invalidator object that can be
107  /// used by a particular analysis result to discover if other analyses
108  /// results are also invalidated in the event that this result depends on
109  /// them. See the documentation in the \c AnalysisManager for more details.
110  ///
111  /// \returns true if the result is indeed invalid (the default).
112  virtual bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA,
113  InvalidatorT &Inv) = 0;
114 };
115 
116 /// \brief SFINAE metafunction for computing whether \c ResultT provides an
117 /// \c invalidate member function.
118 template <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod {
119  typedef char EnabledType;
120  struct DisabledType {
121  char a, b;
122  };
123 
124  // Purely to help out MSVC which fails to disable the below specialization,
125  // explicitly enable using the result type's invalidate routine if we can
126  // successfully call that routine.
127  template <typename T> struct Nonce { typedef EnabledType Type; };
128  template <typename T>
129  static typename Nonce<decltype(std::declval<T>().invalidate(
130  std::declval<IRUnitT &>(), std::declval<PreservedAnalyses>()))>::Type
131  check(rank<2>);
132 
133  // First we define an overload that can only be taken if there is no
134  // invalidate member. We do this by taking the address of an invalidate
135  // member in an adjacent base class of a derived class. This would be
136  // ambiguous if there were an invalidate member in the result type.
137  template <typename T, typename U> static DisabledType NonceFunction(T U::*);
138  struct CheckerBase { int invalidate; };
139  template <typename T> struct Checker : CheckerBase, T {};
140  template <typename T>
141  static decltype(NonceFunction(&Checker<T>::invalidate)) check(rank<1>);
142 
143  // Now we have the fallback that will only be reached when there is an
144  // invalidate member, and enables the trait.
145  template <typename T>
146  static EnabledType check(rank<0>);
147 
148 public:
149  enum { Value = sizeof(check<ResultT>(rank<2>())) == sizeof(EnabledType) };
150 };
151 
152 /// \brief Wrapper to model the analysis result concept.
153 ///
154 /// By default, this will implement the invalidate method with a trivial
155 /// implementation so that the actual analysis result doesn't need to provide
156 /// an invalidation handler. It is only selected when the invalidation handler
157 /// is not part of the ResultT's interface.
158 template <typename IRUnitT, typename PassT, typename ResultT,
159  typename PreservedAnalysesT, typename InvalidatorT,
160  bool HasInvalidateHandler =
161  ResultHasInvalidateMethod<IRUnitT, ResultT>::Value>
163 
164 /// \brief Specialization of \c AnalysisResultModel which provides the default
165 /// invalidate functionality.
166 template <typename IRUnitT, typename PassT, typename ResultT,
167  typename PreservedAnalysesT, typename InvalidatorT>
168 struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT,
169  InvalidatorT, false>
170  : AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT> {
171  explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
172  // We have to explicitly define all the special member functions because MSVC
173  // refuses to generate them.
174  AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
176  : Result(std::move(Arg.Result)) {}
177 
178  friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
179  using std::swap;
180  swap(LHS.Result, RHS.Result);
181  }
182 
184  swap(*this, RHS);
185  return *this;
186  }
187 
188  /// \brief The model bases invalidation solely on being in the preserved set.
189  //
190  // FIXME: We should actually use two different concepts for analysis results
191  // rather than two different models, and avoid the indirect function call for
192  // ones that use the trivial behavior.
193  bool invalidate(IRUnitT &, const PreservedAnalysesT &PA,
194  InvalidatorT &) override {
195  auto PAC = PA.template getChecker<PassT>();
196  return !PAC.preserved() &&
197  !PAC.template preservedSet<AllAnalysesOn<IRUnitT>>();
198  }
199 
200  ResultT Result;
201 };
202 
203 /// \brief Specialization of \c AnalysisResultModel which delegates invalidate
204 /// handling to \c ResultT.
205 template <typename IRUnitT, typename PassT, typename ResultT,
206  typename PreservedAnalysesT, typename InvalidatorT>
207 struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT,
208  InvalidatorT, true>
209  : AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT> {
210  explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
211  // We have to explicitly define all the special member functions because MSVC
212  // refuses to generate them.
213  AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
215  : Result(std::move(Arg.Result)) {}
216 
217  friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
218  using std::swap;
219  swap(LHS.Result, RHS.Result);
220  }
221 
223  swap(*this, RHS);
224  return *this;
225  }
226 
227  /// \brief The model delegates to the \c ResultT method.
228  bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA,
229  InvalidatorT &Inv) override {
230  return Result.invalidate(IR, PA, Inv);
231  }
232 
233  ResultT Result;
234 };
235 
236 /// \brief Abstract concept of an analysis pass.
237 ///
238 /// This concept is parameterized over the IR unit that it can run over and
239 /// produce an analysis result.
240 template <typename IRUnitT, typename PreservedAnalysesT, typename InvalidatorT,
241  typename... ExtraArgTs>
243  virtual ~AnalysisPassConcept() = default;
244 
245  /// \brief Method to run this analysis over a unit of IR.
246  /// \returns A unique_ptr to the analysis result object to be queried by
247  /// users.
248  virtual std::unique_ptr<
251  ExtraArgTs... ExtraArgs) = 0;
252 
253  /// \brief Polymorphic method to access the name of a pass.
254  virtual StringRef name() = 0;
255 };
256 
257 /// \brief Wrapper to model the analysis pass concept.
258 ///
259 /// Can wrap any type which implements a suitable \c run method. The method
260 /// must accept an \c IRUnitT& and an \c AnalysisManager<IRUnitT>& as arguments
261 /// and produce an object which can be wrapped in a \c AnalysisResultModel.
262 template <typename IRUnitT, typename PassT, typename PreservedAnalysesT,
263  typename InvalidatorT, typename... ExtraArgTs>
264 struct AnalysisPassModel : AnalysisPassConcept<IRUnitT, PreservedAnalysesT,
265  InvalidatorT, ExtraArgTs...> {
266  explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
267  // We have to explicitly define all the special member functions because MSVC
268  // refuses to generate them.
270  AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
271 
272  friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
273  using std::swap;
274  swap(LHS.Pass, RHS.Pass);
275  }
276 
278  swap(*this, RHS);
279  return *this;
280  }
281 
282  // FIXME: Replace PassT::Result with type traits when we use C++11.
283  typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result,
284  PreservedAnalysesT, InvalidatorT>
286 
287  /// \brief The model delegates to the \c PassT::run method.
288  ///
289  /// The return is wrapped in an \c AnalysisResultModel.
290  std::unique_ptr<
293  ExtraArgTs... ExtraArgs) override {
294  return make_unique<ResultModelT>(Pass.run(IR, AM, ExtraArgs...));
295  }
296 
297  /// \brief The model delegates to a static \c PassT::name method.
298  ///
299  /// The returned string ref must point to constant immutable data!
300  StringRef name() override { return PassT::name(); }
301 
302  PassT Pass;
303 };
304 
305 } // end namespace detail
306 
307 } // end namespace llvm
308 
309 #endif // LLVM_IR_PASSMANAGERINTERNAL_H
Pass interface - Implemented by all 'passes'.
Definition: Pass.h:81
Wrapper to model the analysis pass concept.
Template for the abstract base class used to dispatch polymorphically over pass objects.
virtual StringRef name()=0
Polymorphic method to access the name of a pass.
SFINAE metafunction for computing whether ResultT provides an invalidate member function.
virtual ~AnalysisResultConcept()=default
Abstract concept of an analysis pass.
virtual bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA, InvalidatorT &Inv)=0
Method to try and mark a result as invalid.
virtual ~AnalysisPassConcept()=default
PassModel & operator=(PassModel RHS)
friend void swap(PassModel &LHS, PassModel &RHS)
Function Alias Analysis false
virtual std::unique_ptr< AnalysisResultConcept< IRUnitT, PreservedAnalysesT, InvalidatorT > > run(IRUnitT &IR, AnalysisManager< IRUnitT, ExtraArgTs...> &AM, ExtraArgTs...ExtraArgs)=0
Method to run this analysis over a unit of IR.
bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA, InvalidatorT &Inv) override
The model delegates to the ResultT method.
virtual StringRef name()=0
Polymorphic method to access the name of a pass.
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:107
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS)
Wrapper to model the analysis result concept.
StringRef name() override
Polymorphic method to access the name of a pass.
StringRef name() override
The model delegates to a static PassT::name method.
PreservedAnalysesT run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs...ExtraArgs) override
The polymorphic API which runs the pass over a given IR entity.
AnalysisPassModel(const AnalysisPassModel &Arg)
virtual ~PassConcept()=default
AnalysisPassModel & operator=(AnalysisPassModel RHS)
std::unique_ptr< AnalysisResultConcept< IRUnitT, PreservedAnalysesT, InvalidatorT > > run(IRUnitT &IR, AnalysisManager< IRUnitT, ExtraArgTs...> &AM, ExtraArgTs...ExtraArgs) override
The model delegates to the PassT::run method.
A template wrapper used to implement the polymorphic API.
Abstract concept of an analysis result.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:586
virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs...ExtraArgs)=0
The polymorphic API which runs the pass over a given IR entity.
Basic Alias true
PassModel(const PassModel &Arg)
bool invalidate(IRUnitT &, const PreservedAnalysesT &PA, InvalidatorT &) override
The model bases invalidation solely on being in the preserved set.
AnalysisResultModel< IRUnitT, PassT, typename PassT::Result, PreservedAnalysesT, InvalidatorT > ResultModelT
LLVM Value Representation.
Definition: Value.h:71
static const char * name
AnalysisPassModel(AnalysisPassModel &&Arg)
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
A container for analyses that lazily runs them and caches their results.
Utility type to build an inheritance chain that makes it easy to rank overload candidates.
Definition: STLExtras.h:628
Statically lint checks LLVM IR
Definition: Lint.cpp:192