LLVM  8.0.1
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 /// Implementation details of the pass manager interfaces.
33 namespace detail {
34 
35 /// 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  /// 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  /// Polymorphic method to access the name of a pass.
51  virtual StringRef name() const = 0;
52 };
53 
54 /// 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() const override { return PassT::name(); }
84 
85  PassT Pass;
86 };
87 
88 /// 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  /// 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 /// 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 /// 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 /// 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  /// 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 /// 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  /// 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 /// 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  /// 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  /// Polymorphic method to access the name of a pass.
253  virtual StringRef name() const = 0;
254 };
255 
256 /// 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  /// 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>(
294  Pass.run(IR, AM, std::forward<ExtraArgTs>(ExtraArgs)...));
295  }
296 
297  /// 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() const 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 &#39;passes&#39;.
Definition: Pass.h:81
Wrapper to model the analysis pass concept.
This class represents lattice values for constants.
Definition: AllocatorList.h:24
Template for the abstract base class used to dispatch polymorphically over pass objects.
block Block Frequency true
SFINAE metafunction for computing whether ResultT provides an invalidate member function.
Abstract concept of an analysis pass.
Definition: BitVector.h:938
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:154
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.
AnalysisPassModel(const AnalysisPassModel &Arg)
virtual StringRef name() const =0
Polymorphic method to access the name of a pass.
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:941
StringRef name() const override
Polymorphic method to access the name of a pass.
amdgpu Simplify well known AMD library false Value Value * Arg
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:1011
Statically lint checks LLVM IR
Definition: Lint.cpp:193
StringRef name() const override
The model delegates to a static PassT::name method.