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