[InstCombine] Signed saturation patterns
[llvm-core.git] / include / llvm / IR / PassManagerInternal.h
blobc602c0b5cc20a1e72c081584f662652dee3edb52
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 //===----------------------------------------------------------------------===//
17 #ifndef LLVM_IR_PASSMANAGERINTERNAL_H
18 #define LLVM_IR_PASSMANAGERINTERNAL_H
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/ADT/StringRef.h"
22 #include <memory>
23 #include <utility>
25 namespace llvm {
27 template <typename IRUnitT> class AllAnalysesOn;
28 template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager;
29 class PreservedAnalyses;
31 /// Implementation details of the pass manager interfaces.
32 namespace detail {
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;
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;
49 /// Polymorphic method to access the name of a pass.
50 virtual StringRef name() const = 0;
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) {}
65 PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
67 friend void swap(PassModel &LHS, PassModel &RHS) {
68 using std::swap;
69 swap(LHS.Pass, RHS.Pass);
72 PassModel &operator=(PassModel RHS) {
73 swap(*this, RHS);
74 return *this;
77 PreservedAnalysesT run(IRUnitT &IR, AnalysisManagerT &AM,
78 ExtraArgTs... ExtraArgs) override {
79 return Pass.run(IR, AM, ExtraArgs...);
82 StringRef name() const override { return PassT::name(); }
84 PassT Pass;
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>
92 struct AnalysisResultConcept {
93 virtual ~AnalysisResultConcept() = default;
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.
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.
109 /// \returns true if the result is indeed invalid (the default).
110 virtual bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA,
111 InvalidatorT &Inv) = 0;
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;
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>);
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>);
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>);
146 public:
147 enum { Value = sizeof(check<ResultT>(rank<2>())) == sizeof(EnabledType) };
150 /// Wrapper to model the analysis result concept.
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 =
159 ResultHasInvalidateMethod<IRUnitT, ResultT>::Value>
160 struct AnalysisResultModel;
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) {}
173 AnalysisResultModel(AnalysisResultModel &&Arg)
174 : Result(std::move(Arg.Result)) {}
176 friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
177 using std::swap;
178 swap(LHS.Result, RHS.Result);
181 AnalysisResultModel &operator=(AnalysisResultModel RHS) {
182 swap(*this, RHS);
183 return *this;
186 /// The model bases invalidation solely on being in the preserved set.
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>>();
198 ResultT Result;
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) {}
212 AnalysisResultModel(AnalysisResultModel &&Arg)
213 : Result(std::move(Arg.Result)) {}
215 friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
216 using std::swap;
217 swap(LHS.Result, RHS.Result);
220 AnalysisResultModel &operator=(AnalysisResultModel RHS) {
221 swap(*this, RHS);
222 return *this;
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);
231 ResultT Result;
234 /// Abstract concept of an analysis pass.
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>
240 struct AnalysisPassConcept {
241 virtual ~AnalysisPassConcept() = default;
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<
247 AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT>>
248 run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
249 ExtraArgTs... ExtraArgs) = 0;
251 /// Polymorphic method to access the name of a pass.
252 virtual StringRef name() const = 0;
255 /// Wrapper to model the analysis pass concept.
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.
267 AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {}
268 AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
270 friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
271 using std::swap;
272 swap(LHS.Pass, RHS.Pass);
275 AnalysisPassModel &operator=(AnalysisPassModel RHS) {
276 swap(*this, RHS);
277 return *this;
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>;
285 /// The model delegates to the \c PassT::run method.
287 /// The return is wrapped in an \c AnalysisResultModel.
288 std::unique_ptr<
289 AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT>>
290 run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
291 ExtraArgTs... ExtraArgs) override {
292 return std::make_unique<ResultModelT>(
293 Pass.run(IR, AM, std::forward<ExtraArgTs>(ExtraArgs)...));
296 /// The model delegates to a static \c PassT::name method.
298 /// The returned string ref must point to constant immutable data!
299 StringRef name() const override { return PassT::name(); }
301 PassT Pass;
304 } // end namespace detail
306 } // end namespace llvm
308 #endif // LLVM_IR_PASSMANAGERINTERNAL_H