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