My Project
AnalysisManager.h
Go to the documentation of this file.
1 //===- AnalysisManager.h - Analysis Management Infrastructure ---*- C++ -*-===//
2 //
3 // Part of the MLIR 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 
9 #ifndef MLIR_PASS_ANALYSISMANAGER_H
10 #define MLIR_PASS_ANALYSISMANAGER_H
11 
12 #include "mlir/IR/Module.h"
14 #include "mlir/Support/LLVM.h"
15 #include "llvm/ADT/DenseMap.h"
16 #include "llvm/ADT/SmallPtrSet.h"
17 #include "llvm/Support/TypeName.h"
18 
19 namespace mlir {
23 
24 //===----------------------------------------------------------------------===//
25 // Analysis Preservation and Concept Modeling
26 //===----------------------------------------------------------------------===//
27 
28 namespace detail {
31 public:
33  void preserveAll() { preservedIDs.insert(&allAnalysesID); }
34 
36  bool isAll() const { return preservedIDs.count(&allAnalysesID); }
37 
39  bool isNone() const { return preservedIDs.empty(); }
40 
42  template <typename AnalysisT> void preserve() {
43  preserve(AnalysisID::getID<AnalysisT>());
44  }
45  template <typename AnalysisT, typename AnalysisT2, typename... OtherAnalysesT>
46  void preserve() {
47  preserve<AnalysisT>();
48  preserve<AnalysisT2, OtherAnalysesT...>();
49  }
50  void preserve(const AnalysisID *id) { preservedIDs.insert(id); }
51 
55  template <typename AnalysisT> bool isPreserved() const {
56  return isPreserved(AnalysisID::getID<AnalysisT>());
57  }
58  bool isPreserved(const AnalysisID *id) const {
59  return preservedIDs.count(id);
60  }
61 
62 private:
64  constexpr static AnalysisID allAnalysesID = {};
65 
67  SmallPtrSet<const void *, 2> preservedIDs;
68 };
69 
70 namespace analysis_impl {
72 template <typename T, typename... Args>
73 using has_is_invalidated = decltype(std::declval<T &>().isInvalidated(
74  std::declval<const PreservedAnalyses &>()));
75 
77 template <typename AnalysisT>
78 std::enable_if_t<is_detected<has_is_invalidated, AnalysisT>::value, bool>
79 isInvalidated(AnalysisT &analysis, const PreservedAnalyses &pa) {
80  return analysis.isInvalidated(pa);
81 }
83 template <typename AnalysisT>
84 std::enable_if_t<!is_detected<has_is_invalidated, AnalysisT>::value, bool>
85 isInvalidated(AnalysisT &analysis, const PreservedAnalyses &pa) {
86  return !pa.isPreserved<AnalysisT>();
87 }
88 } // end namespace analysis_impl
89 
92  virtual ~AnalysisConcept() = default;
93 
99  virtual bool isInvalidated(const PreservedAnalyses &pa) = 0;
100 };
101 
103 template <typename AnalysisT> struct AnalysisModel : public AnalysisConcept {
104  template <typename... Args>
105  explicit AnalysisModel(Args &&... args)
106  : analysis(std::forward<Args>(args)...) {}
107 
109  bool isInvalidated(const PreservedAnalyses &pa) final {
110  return analysis_impl::isInvalidated(analysis, pa);
111  }
112 
114  AnalysisT analysis;
115 };
116 
119 class AnalysisMap {
121  using ConceptMap =
123 
125  template <typename AnalysisT> static StringRef getAnalysisName() {
126  StringRef name = llvm::getTypeName<AnalysisT>();
127  if (!name.consume_front("mlir::"))
128  name.consume_front("(anonymous namespace)::");
129  return name;
130  }
131 
132 public:
133  explicit AnalysisMap(Operation *ir) : ir(ir) {}
134 
136  template <typename AnalysisT> AnalysisT &getAnalysis(PassInstrumentor *pi) {
137  auto *id = AnalysisID::getID<AnalysisT>();
138 
139  typename ConceptMap::iterator it;
140  bool wasInserted;
141  std::tie(it, wasInserted) = analyses.try_emplace(id);
142 
143  // If we don't have a cached analysis for this function, compute it directly
144  // and add it to the cache.
145  if (wasInserted) {
146  if (pi)
147  pi->runBeforeAnalysis(getAnalysisName<AnalysisT>(), id, ir);
148 
149  it->second = std::make_unique<AnalysisModel<AnalysisT>>(ir);
150 
151  if (pi)
152  pi->runAfterAnalysis(getAnalysisName<AnalysisT>(), id, ir);
153  }
154  return static_cast<AnalysisModel<AnalysisT> &>(*it->second).analysis;
155  }
156 
158  template <typename AnalysisT>
160  auto res = analyses.find(AnalysisID::getID<AnalysisT>());
161  if (res == analyses.end())
162  return llvm::None;
163  return {static_cast<AnalysisModel<AnalysisT> &>(*res->second).analysis};
164  }
165 
167  Operation *getOperation() const { return ir; }
168 
170  void clear() { analyses.clear(); }
171 
174  void invalidate(const PreservedAnalyses &pa) {
175  // Remove any analyses that were invalidated.
176  for (auto it = analyses.begin(), e = analyses.end(); it != e;) {
177  auto curIt = it++;
178  if (curIt->second->isInvalidated(pa))
179  analyses.erase(curIt);
180  }
181  }
182 
183 private:
184  Operation *ir;
185  ConceptMap analyses;
186 };
187 
191  NestedAnalysisMap(Operation *op) : analyses(op) {}
192 
194  Operation *getOperation() const { return analyses.getOperation(); }
195 
197  void invalidate(const PreservedAnalyses &pa);
198 
201 
204 };
205 } // namespace detail
206 
207 //===----------------------------------------------------------------------===//
208 // Analysis Management
209 //===----------------------------------------------------------------------===//
211 
218  using ParentPointerT =
220 
221 public:
223 
224  // Query for a cached analysis on the given parent operation. The analysis may
225  // not exist and if it does it may be out-of-date.
226  template <typename AnalysisT>
229  ParentPointerT curParent = parent;
230  while (auto *parentAM = curParent.dyn_cast<const AnalysisManager *>()) {
231  if (parentAM->impl->getOperation() == parentOp)
232  return parentAM->getCachedAnalysis<AnalysisT>();
233  curParent = parentAM->parent;
234  }
235  return None;
236  }
237 
238  // Query for the given analysis for the current operation.
239  template <typename AnalysisT> AnalysisT &getAnalysis() {
240  return impl->analyses.getAnalysis<AnalysisT>(getPassInstrumentor());
241  }
242 
243  // Query for a cached entry of the given analysis on the current operation.
244  template <typename AnalysisT>
246  return impl->analyses.getCachedAnalysis<AnalysisT>();
247  }
248 
250  template <typename AnalysisT> AnalysisT &getChildAnalysis(Operation *op) {
251  return slice(op).template getAnalysis<AnalysisT>();
252  }
253 
255  template <typename AnalysisT>
258  assert(op->getParentOp() == impl->getOperation());
259  auto it = impl->childAnalyses.find(op);
260  if (it == impl->childAnalyses.end())
261  return llvm::None;
262  return it->second->analyses.getCachedAnalysis<AnalysisT>();
263  }
264 
267 
269  void invalidate(const PreservedAnalyses &pa) { impl->invalidate(pa); }
270 
272  void clear() {
273  impl->analyses.clear();
274  impl->childAnalyses.clear();
275  }
276 
279  PassInstrumentor *getPassInstrumentor() const;
280 
281 private:
282  AnalysisManager(const AnalysisManager *parent,
284  : parent(parent), impl(impl) {}
287  : parent(parent), impl(impl) {}
288 
291  ParentPointerT parent;
292 
295 
297  friend class ModuleAnalysisManager;
298 };
299 
305 public:
307  : analyses(module), passInstrumentor(passInstrumentor) {}
309  ModuleAnalysisManager &operator=(const ModuleAnalysisManager &) = delete;
310 
313  PassInstrumentor *getPassInstrumentor() const { return passInstrumentor; }
314 
316  operator AnalysisManager() { return AnalysisManager(this, &analyses); }
317 
318 private:
320  detail::NestedAnalysisMap analyses;
321 
323  PassInstrumentor *passInstrumentor;
324 };
325 
326 } // end namespace mlir
327 
328 #endif // MLIR_PASS_ANALYSISMANAGER_H
Definition: InferTypeOpInterface.cpp:20
AnalysisT & getAnalysis()
Definition: AnalysisManager.h:239
Definition: STLExtras.h:95
Definition: Operation.h:27
bool isAll() const
Returns true if all analyses were marked preserved.
Definition: AnalysisManager.h:36
bool isPreserved(const AnalysisID *id) const
Definition: AnalysisManager.h:58
Definition: LLVM.h:48
Definition: AnalysisManager.h:217
void preserveAll()
Mark all analyses as preserved.
Definition: AnalysisManager.h:33
AnalysisMap(Operation *ir)
Definition: AnalysisManager.h:133
Definition: LLVM.h:40
void runBeforeAnalysis(StringRef name, AnalysisID *id, Operation *op)
See PassInstrumentation::runBeforeAnalysis for details.
Definition: Pass.cpp:733
ModuleAnalysisManager(ModuleOp module, PassInstrumentor *passInstrumentor)
Definition: AnalysisManager.h:306
AnalysisT & getAnalysis(PassInstrumentor *pi)
Get an analysis for the current IR unit, computing it if necessary.
Definition: AnalysisManager.h:136
void invalidate(const PreservedAnalyses &pa)
Definition: AnalysisManager.h:174
Definition: AnalysisManager.h:304
AnalysisT analysis
The actual analysis object.
Definition: AnalysisManager.h:114
The abstract polymorphic base class representing an analysis.
Definition: AnalysisManager.h:91
decltype(std::declval< T & >().isInvalidated(std::declval< const PreservedAnalyses & >())) has_is_invalidated
Trait to check if T provides a static &#39;isInvalidated&#39; method.
Definition: AnalysisManager.h:74
Operation * getOperation() const
Get the operation for this analysis map.
Definition: AnalysisManager.h:194
Definition: AnalysisManager.h:119
PassInstrumentor * getPassInstrumentor() const
Definition: AnalysisManager.h:313
detail::AnalysisMap analyses
The analyses for the owning module.
Definition: AnalysisManager.h:203
NestedAnalysisMap(Operation *op)
Definition: AnalysisManager.h:191
std::enable_if_t<!is_detected< has_is_invalidated, AnalysisT >::value, bool > isInvalidated(AnalysisT &analysis, const PreservedAnalyses &pa)
Default implementation of &#39;isInvalidated&#39;.
Definition: AnalysisManager.h:85
void runAfterAnalysis(StringRef name, AnalysisID *id, Operation *op)
See PassInstrumentation::runAfterAnalysis for details.
Definition: Pass.cpp:741
Operation * getOperation() const
Returns the operation that this analysis map represents.
Definition: AnalysisManager.h:167
A utility class to represent the analyses that are known to be preserved.
Definition: AnalysisManager.h:30
Definition: Module.h:29
mlir::edsc::intrinsics::ValueBuilder< SliceOp > slice
Definition: Intrinsics.h:24
bool isPreserved() const
Definition: AnalysisManager.h:55
bool isInvalidated(const PreservedAnalyses &pa) final
A hook used to query analyses for invalidation.
Definition: AnalysisManager.h:109
Optional< std::reference_wrapper< AnalysisT > > getCachedChildAnalysis(Operation *op) const
Query for a cached analysis of a child operation, or return null.
Definition: AnalysisManager.h:257
Definition: LLVM.h:33
void invalidate(const PreservedAnalyses &pa)
Invalidate any non preserved analyses,.
Definition: AnalysisManager.h:269
std::enable_if_t< is_detected< has_is_invalidated, AnalysisT >::value, bool > isInvalidated(AnalysisT &analysis, const PreservedAnalyses &pa)
Implementation of &#39;isInvalidated&#39; if the analysis provides a definition.
Definition: AnalysisManager.h:79
Definition: PassInstrumentation.h:89
void preserve()
Definition: AnalysisManager.h:46
DenseMap< Operation *, std::unique_ptr< NestedAnalysisMap > > childAnalyses
The cached analyses for nested operations.
Definition: AnalysisManager.h:200
Operation * getParentOp()
Definition: Operation.cpp:265
Definition: AnalysisManager.h:190
void clear()
Clear any held analyses.
Definition: AnalysisManager.h:272
Definition: StandardTypes.h:63
AnalysisT & getChildAnalysis(Operation *op)
Query for a analysis of a child operation, constructing it if necessary.
Definition: AnalysisManager.h:250
Optional< std::reference_wrapper< AnalysisT > > getCachedAnalysis() const
Definition: AnalysisManager.h:245
Optional< std::reference_wrapper< AnalysisT > > getCachedAnalysis() const
Get a cached analysis instance if one exists, otherwise return null.
Definition: AnalysisManager.h:159
Optional< std::reference_wrapper< AnalysisT > > getCachedParentAnalysis(Operation *parentOp) const
Definition: AnalysisManager.h:228
void preserve(const AnalysisID *id)
Definition: AnalysisManager.h:50
AnalysisModel(Args &&... args)
Definition: AnalysisManager.h:105
void clear()
Clear any held analyses.
Definition: AnalysisManager.h:170
A derived analysis model used to hold a specific analysis object.
Definition: AnalysisManager.h:103
bool isNone() const
Returns true if no analyses were marked preserved.
Definition: AnalysisManager.h:39
void preserve()
Preserve the given analyses.
Definition: AnalysisManager.h:42
Definition: LLVM.h:41