LLVM  11.0.0git
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 std::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:77
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.
static const char * name
SFINAE metafunction for computing whether ResultT provides an invalidate member function.
Abstract concept of an analysis pass.
Definition: BitVector.h:959
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.
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:962
StringRef name() const override
Polymorphic method to access the name of a pass.
basic 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:74
AnalysisPassModel(AnalysisPassModel &&Arg)
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
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:1292
Statically lint checks LLVM IR
Definition: Lint.cpp:189
StringRef name() const override
The model delegates to a static PassT::name method.