LLVM 23.0.0git
PassManager.h
Go to the documentation of this file.
1//===- PassManager.h - Pass management infrastructure -----------*- 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 defines various interfaces for pass management in LLVM. There
11/// is no "pass" interface in LLVM per se. Instead, an instance of any class
12/// which supports a method to 'run' it over a unit of IR can be used as
13/// a pass. A pass manager is generally a tool to collect a sequence of passes
14/// which run over a particular IR construct, and run each of them in sequence
15/// over each such construct in the containing IR construct. As there is no
16/// containing IR construct for a Module, a manager for passes over modules
17/// forms the base case which runs its managed passes in sequence over the
18/// single module provided.
19///
20/// The core IR library provides managers for running passes over
21/// modules and functions.
22///
23/// * FunctionPassManager can run over a Module, runs each pass over
24/// a Function.
25/// * ModulePassManager must be directly run, runs each pass over the Module.
26///
27/// Note that the implementations of the pass managers use concept-based
28/// polymorphism as outlined in the "Value Semantics and Concept-based
29/// Polymorphism" talk (or its abbreviated sibling "Inheritance Is The Base
30/// Class of Evil") by Sean Parent:
31/// * https://sean-parent.stlab.cc/papers-and-presentations
32/// * http://www.youtube.com/watch?v=_BpMYeUFXv8
33/// * https://learn.microsoft.com/en-us/shows/goingnative-2013/inheritance-base-class-of-evil
34///
35//===----------------------------------------------------------------------===//
36
37#ifndef LLVM_IR_PASSMANAGER_H
38#define LLVM_IR_PASSMANAGER_H
39
40#include "llvm/ADT/DenseMap.h"
41#include "llvm/ADT/STLExtras.h"
43#include "llvm/ADT/StringRef.h"
45#include "llvm/IR/Analysis.h"
49#include <cassert>
50#include <cstring>
51#include <list>
52#include <memory>
53#include <tuple>
54#include <type_traits>
55#include <utility>
56#include <vector>
57
58namespace llvm {
59
60namespace detail {
61template <typename DerivedT> struct InfoMixin {
62 /// Gets the name of the pass we are mixed into.
63 static StringRef name() {
64 static_assert(std::is_base_of<InfoMixin, DerivedT>::value,
65 "Must pass the derived type as the template argument!");
67 Name.consume_front("llvm::");
68 return Name;
69 }
70};
71} // namespace detail
72
73class Function;
74class Module;
75
76// Forward declare the analysis manager template.
77template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager;
78
79/// A CRTP mix-in to automatically provide informational APIs needed for
80/// passes.
81///
82/// This provides some boilerplate for types that are passes.
83///
84/// Actual passes should inherit from RequiredPassInfoMixin or
85/// OptionalPassInfoMixin.
86///
87/// TODO: move to a detail namespace once we've branched for LLVM 23.
88template <typename DerivedT>
89struct PassInfoMixin : detail::InfoMixin<DerivedT> {
91 function_ref<StringRef(StringRef)> MapClassName2PassName) {
92 StringRef ClassName = DerivedT::name();
93 auto PassName = MapClassName2PassName(ClassName);
94 OS << PassName;
95 }
96
97 // TODO: remove once out of tree users are updated.
98 static bool isRequired() { return false; }
99};
100
101/// A CRTP mix-in for passes that should not be skipped.
102template <typename DerivedT>
104 static bool isRequired() { return true; }
105};
106
107/// A CRTP mix-in for passes that can be skipped.
108template <typename DerivedT>
110 static bool isRequired() { return false; }
111};
112
113/// A CRTP mix-in that provides informational APIs needed for analysis passes.
114///
115/// This provides some boilerplate for types that are analysis passes. It
116/// automatically mixes in \c PassInfoMixin.
117template <typename DerivedT>
119 /// Returns an opaque, unique ID for this analysis type.
120 ///
121 /// This ID is a pointer type that is guaranteed to be 8-byte aligned and thus
122 /// suitable for use in sets, maps, and other data structures that use the low
123 /// bits of pointers.
124 ///
125 /// Note that this requires the derived type provide a static \c AnalysisKey
126 /// member called \c Key.
127 ///
128 /// FIXME: The only reason the mixin type itself can't declare the Key value
129 /// is that some compilers cannot correctly unique a templated static variable
130 /// so it has the same addresses in each instantiation. The only currently
131 /// known platform with this limitation is Windows DLL builds, specifically
132 /// building each part of LLVM as a DLL. If we ever remove that build
133 /// configuration, this mixin can provide the static key as well.
134 static AnalysisKey *ID() {
135 static_assert(std::is_base_of<AnalysisInfoMixin, DerivedT>::value,
136 "Must pass the derived type as the template argument!");
137 return &DerivedT::Key;
138 }
139};
140
141namespace detail {
142
143/// Actual unpacker of extra arguments in getAnalysisResult,
144/// passes only those tuple arguments that are mentioned in index_sequence.
145template <typename PassT, typename IRUnitT, typename AnalysisManagerT,
146 typename... ArgTs, size_t... Ns>
147typename PassT::Result
148getAnalysisResultUnpackTuple(AnalysisManagerT &AM, IRUnitT &IR,
149 std::tuple<ArgTs...> Args,
150 std::index_sequence<Ns...>) {
151 (void)Args;
152 return AM.template getResult<PassT>(IR, std::get<Ns>(Args)...);
153}
154
155/// Helper for *partial* unpacking of extra arguments in getAnalysisResult.
156///
157/// Arguments passed in tuple come from PassManager, so they might have extra
158/// arguments after those AnalysisManager's ExtraArgTs ones that we need to
159/// pass to getResult.
160template <typename PassT, typename IRUnitT, typename... AnalysisArgTs,
161 typename... MainArgTs>
162typename PassT::Result
164 std::tuple<MainArgTs...> Args) {
166 PassT, IRUnitT>)(AM, IR, Args,
167 std::index_sequence_for<AnalysisArgTs...>{});
168}
169
170} // namespace detail
171
172/// Manages a sequence of passes over a particular unit of IR.
173///
174/// A pass manager contains a sequence of passes to run over a particular unit
175/// of IR (e.g. Functions, Modules). It is itself a valid pass over that unit of
176/// IR, and when run over some given IR will run each of its contained passes in
177/// sequence. Pass managers are the primary and most basic building block of a
178/// pass pipeline.
179///
180/// When you run a pass manager, you provide an \c AnalysisManager<IRUnitT>
181/// argument. The pass manager will propagate that analysis manager to each
182/// pass it runs, and will call the analysis manager's invalidation routine with
183/// the PreservedAnalyses of each pass it runs.
184template <typename IRUnitT,
185 typename AnalysisManagerT = AnalysisManager<IRUnitT>,
186 typename... ExtraArgTs>
188 PassManager<IRUnitT, AnalysisManagerT, ExtraArgTs...>> {
189public:
190 /// Construct a pass manager.
191 explicit PassManager() = default;
192
193 // FIXME: These are equivalent to the default move constructor/move
194 // assignment. However, using = default triggers linker errors due to the
195 // explicit instantiations below. Find away to use the default and remove the
196 // duplicated code here.
198
200 Passes = std::move(RHS.Passes);
201 return *this;
202 }
203
205 function_ref<StringRef(StringRef)> MapClassName2PassName) {
206 ListSeparator LS(",");
207 for (auto &P : Passes) {
208 OS << LS;
209 P->printPipeline(OS, MapClassName2PassName);
210 }
211 }
212
213 /// Run all of the passes in this manager over the given unit of IR.
214 /// ExtraArgs are passed to each pass.
215 PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
216 ExtraArgTs... ExtraArgs);
217
218 template <typename PassT>
219 LLVM_ATTRIBUTE_MINSIZE std::enable_if_t<!std::is_same_v<PassT, PassManager>>
220 addPass(PassT &&Pass) {
221 using PassModelT =
222 detail::PassModel<IRUnitT, PassT, AnalysisManagerT, ExtraArgTs...>;
223 // Do not use make_unique or emplace_back, they cause too many template
224 // instantiations, causing terrible compile times.
225 Passes.push_back(std::unique_ptr<PassConceptT>(
226 new PassModelT(std::forward<PassT>(Pass))));
227 }
228
229 /// When adding a pass manager pass that has the same type as this pass
230 /// manager, simply move the passes over. This is because we don't have
231 /// use cases rely on executing nested pass managers. Doing this could
232 /// reduce implementation complexity and avoid potential invalidation
233 /// issues that may happen with nested pass managers of the same type.
234 template <typename PassT>
235 LLVM_ATTRIBUTE_MINSIZE std::enable_if_t<std::is_same_v<PassT, PassManager>>
236 addPass(PassT &&Pass) {
237 for (auto &P : Pass.Passes)
238 Passes.push_back(std::move(P));
239 }
240
241 /// Returns if the pass manager contains any passes.
242 bool isEmpty() const { return Passes.empty(); }
243
244protected:
246 detail::PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...>;
247
248 std::vector<std::unique_ptr<PassConceptT>> Passes;
249};
250
251template <typename IRUnitT>
253
254template <>
256 const Module &IR);
257
258extern template class LLVM_TEMPLATE_ABI PassManager<Module>;
259
260/// Convenience typedef for a pass manager over modules.
262
263template <>
265 const Function &IR);
266
267extern template class LLVM_TEMPLATE_ABI PassManager<Function>;
268
269/// Convenience typedef for a pass manager over functions.
271
272/// A container for analyses that lazily runs them and caches their
273/// results.
274///
275/// This class can manage analyses for any IR unit where the address of the IR
276/// unit sufficies as its identity.
277template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager {
278public:
279 class Invalidator;
280
281private:
282 // Now that we've defined our invalidator, we can define the concept types.
284 using PassConceptT =
285 detail::AnalysisPassConcept<IRUnitT, Invalidator, ExtraArgTs...>;
286
287 /// List of analysis pass IDs and associated concept pointers.
288 ///
289 /// Requires iterators to be valid across appending new entries and arbitrary
290 /// erases. Provides the analysis ID to enable finding iterators to a given
291 /// entry in maps below, and provides the storage for the actual result
292 /// concept.
293 using AnalysisResultListT =
294 std::list<std::pair<AnalysisKey *, std::unique_ptr<ResultConceptT>>>;
295
296 /// Map type from IRUnitT pointer to our custom list type.
297 using AnalysisResultListMapT = DenseMap<IRUnitT *, AnalysisResultListT>;
298
299 /// Map type from a pair of analysis ID and IRUnitT pointer to an
300 /// iterator into a particular result list (which is where the actual analysis
301 /// result is stored).
302 using AnalysisResultMapT =
304 typename AnalysisResultListT::iterator>;
305
306public:
307 /// API to communicate dependencies between analyses during invalidation.
308 ///
309 /// When an analysis result embeds handles to other analysis results, it
310 /// needs to be invalidated both when its own information isn't preserved and
311 /// when any of its embedded analysis results end up invalidated. We pass an
312 /// \c Invalidator object as an argument to \c invalidate() in order to let
313 /// the analysis results themselves define the dependency graph on the fly.
314 /// This lets us avoid building an explicit representation of the
315 /// dependencies between analysis results.
316 class Invalidator {
317 public:
318 /// Trigger the invalidation of some other analysis pass if not already
319 /// handled and return whether it was in fact invalidated.
320 ///
321 /// This is expected to be called from within a given analysis result's \c
322 /// invalidate method to trigger a depth-first walk of all inter-analysis
323 /// dependencies. The same \p IR unit and \p PA passed to that result's \c
324 /// invalidate method should in turn be provided to this routine.
325 ///
326 /// The first time this is called for a given analysis pass, it will call
327 /// the corresponding result's \c invalidate method. Subsequent calls will
328 /// use a cache of the results of that initial call. It is an error to form
329 /// cyclic dependencies between analysis results.
330 ///
331 /// This returns true if the given analysis's result is invalid. Any
332 /// dependecies on it will become invalid as a result.
333 template <typename PassT>
334 bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA) {
335 using ResultModelT =
336 detail::AnalysisResultModel<IRUnitT, PassT, typename PassT::Result,
337 Invalidator>;
338
339 return invalidateImpl<ResultModelT>(PassT::ID(), IR, PA);
340 }
341
342 /// A type-erased variant of the above invalidate method with the same core
343 /// API other than passing an analysis ID rather than an analysis type
344 /// parameter.
345 ///
346 /// This is sadly less efficient than the above routine, which leverages
347 /// the type parameter to avoid the type erasure overhead.
348 bool invalidate(AnalysisKey *ID, IRUnitT &IR, const PreservedAnalyses &PA) {
349 return invalidateImpl<>(ID, IR, PA);
350 }
351
352 private:
353 friend class AnalysisManager;
354
355 template <typename ResultT = ResultConceptT>
356 bool invalidateImpl(AnalysisKey *ID, IRUnitT &IR,
357 const PreservedAnalyses &PA) {
358 // If we've already visited this pass, return true if it was invalidated
359 // and false otherwise.
360 auto IMapI = IsResultInvalidated.find(ID);
361 if (IMapI != IsResultInvalidated.end())
362 return IMapI->second;
363
364 // Otherwise look up the result object.
365 auto RI = Results.find({ID, &IR});
366 assert(RI != Results.end() &&
367 "Trying to invalidate a dependent result that isn't in the "
368 "manager's cache is always an error, likely due to a stale result "
369 "handle!");
370
371 auto &Result = static_cast<ResultT &>(*RI->second->second);
372
373 // Insert into the map whether the result should be invalidated and return
374 // that. Note that we cannot reuse IMapI and must do a fresh insert here,
375 // as calling invalidate could (recursively) insert things into the map,
376 // making any iterator or reference invalid.
377 bool Inserted;
378 std::tie(IMapI, Inserted) =
379 IsResultInvalidated.insert({ID, Result.invalidate(IR, PA, *this)});
380 (void)Inserted;
381 assert(Inserted && "Should not have already inserted this ID, likely "
382 "indicates a dependency cycle!");
383 return IMapI->second;
384 }
385
386 Invalidator(SmallDenseMap<AnalysisKey *, bool, 8> &IsResultInvalidated,
387 const AnalysisResultMapT &Results)
388 : IsResultInvalidated(IsResultInvalidated), Results(Results) {}
389
390 SmallDenseMap<AnalysisKey *, bool, 8> &IsResultInvalidated;
391 const AnalysisResultMapT &Results;
392 };
393
394 /// Construct an empty analysis manager.
398
399 /// Returns true if the analysis manager has an empty results cache.
400 bool empty() const {
401 assert(AnalysisResults.empty() == AnalysisResultLists.empty() &&
402 "The storage and index of analysis results disagree on how many "
403 "there are!");
404 return AnalysisResults.empty();
405 }
406
407 /// Clear any cached analysis results for a single unit of IR.
408 ///
409 /// This doesn't invalidate, but instead simply deletes, the relevant results.
410 /// It is useful when the IR is being removed and we want to clear out all the
411 /// memory pinned for it.
412 void clear(IRUnitT &IR, llvm::StringRef Name);
413
414 /// Clear all analysis results cached by this AnalysisManager.
415 ///
416 /// Like \c clear(IRUnitT&), this doesn't invalidate the results; it simply
417 /// deletes them. This lets you clean up the AnalysisManager when the set of
418 /// IR units itself has potentially changed, and thus we can't even look up a
419 /// a result and invalidate/clear it directly.
420 void clear() {
421 AnalysisResults.clear();
422 AnalysisResultLists.clear();
423 }
424
425 /// Returns true if the specified analysis pass is registered.
426 template <typename PassT> bool isPassRegistered() const {
427 return AnalysisPasses.count(PassT::ID());
428 }
429
430 /// Get the result of an analysis pass for a given IR unit.
431 ///
432 /// Runs the analysis if a cached result is not available.
433 template <typename PassT>
434 typename PassT::Result &getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs) {
435 assert(AnalysisPasses.count(PassT::ID()) &&
436 "This analysis pass was not registered prior to being queried");
437 ResultConceptT &ResultConcept =
438 getResultImpl(PassT::ID(), IR, ExtraArgs...);
439
440 using ResultModelT =
441 detail::AnalysisResultModel<IRUnitT, PassT, typename PassT::Result,
442 Invalidator>;
443
444 return static_cast<ResultModelT &>(ResultConcept).Result;
445 }
446
447 /// Get the cached result of an analysis pass for a given IR unit.
448 ///
449 /// This method never runs the analysis.
450 ///
451 /// \returns null if there is no cached result.
452 template <typename PassT>
453 typename PassT::Result *getCachedResult(IRUnitT &IR) const {
454 assert(AnalysisPasses.count(PassT::ID()) &&
455 "This analysis pass was not registered prior to being queried");
456
457 ResultConceptT *ResultConcept = getCachedResultImpl(PassT::ID(), IR);
458 if (!ResultConcept)
459 return nullptr;
460
461 using ResultModelT =
462 detail::AnalysisResultModel<IRUnitT, PassT, typename PassT::Result,
463 Invalidator>;
464
465 return &static_cast<ResultModelT *>(ResultConcept)->Result;
466 }
467
468 /// Verify that the given Result cannot be invalidated, assert otherwise.
469 template <typename PassT>
470 void verifyNotInvalidated(IRUnitT &IR, typename PassT::Result *Result) const {
472 SmallDenseMap<AnalysisKey *, bool, 8> IsResultInvalidated;
473 Invalidator Inv(IsResultInvalidated, AnalysisResults);
474 assert(!Result->invalidate(IR, PA, Inv) &&
475 "Cached result cannot be invalidated");
476 }
477
478 /// Register an analysis pass with the manager.
479 ///
480 /// The parameter is a callable whose result is an analysis pass. This allows
481 /// passing in a lambda to construct the analysis.
482 ///
483 /// The analysis type to register is the type returned by calling the \c
484 /// PassBuilder argument. If that type has already been registered, then the
485 /// argument will not be called and this function will return false.
486 /// Otherwise, we register the analysis returned by calling \c PassBuilder(),
487 /// and this function returns true.
488 ///
489 /// (Note: Although the return value of this function indicates whether or not
490 /// an analysis was previously registered, you should just register all the
491 /// analyses you might want and let this class run them lazily. This idiom
492 /// lets us minimize the number of times we have to look up analyses in our
493 /// hashtable.)
494 template <typename PassBuilderT>
495 bool registerPass(PassBuilderT &&PassBuilder) {
496 using PassT = decltype(PassBuilder());
497 using PassModelT =
498 detail::AnalysisPassModel<IRUnitT, PassT, Invalidator, ExtraArgTs...>;
499
500 auto &PassPtr = AnalysisPasses[PassT::ID()];
501 if (PassPtr)
502 // Already registered this pass type!
503 return false;
504
505 // Construct a new model around the instance returned by the builder.
506 PassPtr.reset(new PassModelT(PassBuilder()));
507 return true;
508 }
509
510 /// Invalidate cached analyses for an IR unit.
511 ///
512 /// Walk through all of the analyses pertaining to this unit of IR and
513 /// invalidate them, unless they are preserved by the PreservedAnalyses set.
514 void invalidate(IRUnitT &IR, const PreservedAnalyses &PA);
515
516 /// Directly clear a cached analysis for an IR unit.
517 ///
518 /// Using invalidate() over this is preferred unless you are really
519 /// sure you want to *only* clear this analysis without asking if it is
520 /// invalid.
521 template <typename AnalysisT> void clearAnalysis(IRUnitT &IR) {
522 AnalysisResultListT &ResultsList = AnalysisResultLists[&IR];
523 AnalysisKey *ID = AnalysisT::ID();
524
525 auto I =
526 llvm::find_if(ResultsList, [&ID](auto &E) { return E.first == ID; });
527 assert(I != ResultsList.end() && "Analysis must be available");
528 ResultsList.erase(I);
529 AnalysisResults.erase({ID, &IR});
530 }
531
532private:
533 /// Look up a registered analysis pass.
534 PassConceptT &lookUpPass(AnalysisKey *ID) {
535 typename AnalysisPassMapT::iterator PI = AnalysisPasses.find(ID);
536 assert(PI != AnalysisPasses.end() &&
537 "Analysis passes must be registered prior to being queried!");
538 return *PI->second;
539 }
540
541 /// Look up a registered analysis pass.
542 const PassConceptT &lookUpPass(AnalysisKey *ID) const {
543 typename AnalysisPassMapT::const_iterator PI = AnalysisPasses.find(ID);
544 assert(PI != AnalysisPasses.end() &&
545 "Analysis passes must be registered prior to being queried!");
546 return *PI->second;
547 }
548
549 /// Get an analysis result, running the pass if necessary.
550 ResultConceptT &getResultImpl(AnalysisKey *ID, IRUnitT &IR,
551 ExtraArgTs... ExtraArgs);
552
553 /// Get a cached analysis result or return null.
554 ResultConceptT *getCachedResultImpl(AnalysisKey *ID, IRUnitT &IR) const {
555 typename AnalysisResultMapT::const_iterator RI =
556 AnalysisResults.find({ID, &IR});
557 return RI == AnalysisResults.end() ? nullptr : &*RI->second->second;
558 }
559
560 /// Map type from analysis pass ID to pass concept pointer.
561 using AnalysisPassMapT =
562 DenseMap<AnalysisKey *, std::unique_ptr<PassConceptT>>;
563
564 /// Collection of analysis passes, indexed by ID.
565 AnalysisPassMapT AnalysisPasses;
566
567 /// Map from IR unit to a list of analysis results.
568 ///
569 /// Provides linear time removal of all analysis results for a IR unit and
570 /// the ultimate storage for a particular cached analysis result.
571 AnalysisResultListMapT AnalysisResultLists;
572
573 /// Map from an analysis ID and IR unit to a particular cached
574 /// analysis result.
575 AnalysisResultMapT AnalysisResults;
576};
577
578extern template class LLVM_TEMPLATE_ABI AnalysisManager<Module>;
579
580/// Convenience typedef for the Module analysis manager.
582
583extern template class LLVM_TEMPLATE_ABI AnalysisManager<Function>;
584
585/// Convenience typedef for the Function analysis manager.
587
588/// An analysis over an "outer" IR unit that provides access to an
589/// analysis manager over an "inner" IR unit. The inner unit must be contained
590/// in the outer unit.
591///
592/// For example, InnerAnalysisManagerProxy<FunctionAnalysisManager, Module> is
593/// an analysis over Modules (the "outer" unit) that provides access to a
594/// Function analysis manager. The FunctionAnalysisManager is the "inner"
595/// manager being proxied, and Functions are the "inner" unit. The inner/outer
596/// relationship is valid because each Function is contained in one Module.
597///
598/// If you're (transitively) within a pass manager for an IR unit U that
599/// contains IR unit V, you should never use an analysis manager over V, except
600/// via one of these proxies.
601///
602/// Note that the proxy's result is a move-only RAII object. The validity of
603/// the analyses in the inner analysis manager is tied to its lifetime.
604template <typename AnalysisManagerT, typename IRUnitT, typename... ExtraArgTs>
606 : public AnalysisInfoMixin<
607 InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT>> {
608public:
609 class Result {
610 public:
611 explicit Result(AnalysisManagerT &InnerAM) : InnerAM(&InnerAM) {}
612
613 Result(Result &&Arg) : InnerAM(std::move(Arg.InnerAM)) {
614 // We have to null out the analysis manager in the moved-from state
615 // because we are taking ownership of the responsibility to clear the
616 // analysis state.
617 Arg.InnerAM = nullptr;
618 }
619
621 // InnerAM is cleared in a moved from state where there is nothing to do.
622 if (!InnerAM)
623 return;
624
625 // Clear out the analysis manager if we're being destroyed -- it means we
626 // didn't even see an invalidate call when we got invalidated.
627 InnerAM->clear();
628 }
629
631 InnerAM = RHS.InnerAM;
632 // We have to null out the analysis manager in the moved-from state
633 // because we are taking ownership of the responsibility to clear the
634 // analysis state.
635 RHS.InnerAM = nullptr;
636 return *this;
637 }
638
639 /// Accessor for the analysis manager.
640 AnalysisManagerT &getManager() { return *InnerAM; }
641
642 /// Handler for invalidation of the outer IR unit, \c IRUnitT.
643 ///
644 /// If the proxy analysis itself is not preserved, we assume that the set of
645 /// inner IR objects contained in IRUnit may have changed. In this case,
646 /// we have to call \c clear() on the inner analysis manager, as it may now
647 /// have stale pointers to its inner IR objects.
648 ///
649 /// Regardless of whether the proxy analysis is marked as preserved, all of
650 /// the analyses in the inner analysis manager are potentially invalidated
651 /// based on the set of preserved analyses.
653 IRUnitT &IR, const PreservedAnalyses &PA,
655
656 private:
657 AnalysisManagerT *InnerAM;
658 };
659
660 explicit InnerAnalysisManagerProxy(AnalysisManagerT &InnerAM)
661 : InnerAM(&InnerAM) {}
662
663 /// Run the analysis pass and create our proxy result object.
664 ///
665 /// This doesn't do any interesting work; it is primarily used to insert our
666 /// proxy result object into the outer analysis cache so that we can proxy
667 /// invalidation to the inner analysis manager.
669 ExtraArgTs...) {
670 return Result(*InnerAM);
671 }
672
673private:
674 friend AnalysisInfoMixin<
676
677 static AnalysisKey Key;
678
679 AnalysisManagerT *InnerAM;
680};
681
682// NOTE: The LLVM_ABI annotation cannot be used here because MSVC disallows
683// storage-class specifiers on class members outside of the class declaration
684// (C2720). LLVM_ATTRIBUTE_VISIBILITY_DEFAULT only applies to non-Windows
685// targets so it is used instead. Without this annotation, compiling LLVM as a
686// shared library with -fvisibility=hidden using GCC fails to export the symbol
687// even though InnerAnalysisManagerProxy is already annotated with LLVM_ABI.
688template <typename AnalysisManagerT, typename IRUnitT, typename... ExtraArgTs>
690 InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT, ExtraArgTs...>::Key;
691
692/// Provide the \c FunctionAnalysisManager to \c Module proxy.
695
696/// Specialization of the invalidate method for the \c
697/// FunctionAnalysisManagerModuleProxy's result.
698template <>
699LLVM_ABI bool FunctionAnalysisManagerModuleProxy::Result::invalidate(
700 Module &M, const PreservedAnalyses &PA,
701 ModuleAnalysisManager::Invalidator &Inv);
702
703// Ensure the \c FunctionAnalysisManagerModuleProxy is provided as an extern
704// template.
706 Module>;
707
708/// An analysis over an "inner" IR unit that provides access to an
709/// analysis manager over a "outer" IR unit. The inner unit must be contained
710/// in the outer unit.
711///
712/// For example OuterAnalysisManagerProxy<ModuleAnalysisManager, Function> is an
713/// analysis over Functions (the "inner" unit) which provides access to a Module
714/// analysis manager. The ModuleAnalysisManager is the "outer" manager being
715/// proxied, and Modules are the "outer" IR unit. The inner/outer relationship
716/// is valid because each Function is contained in one Module.
717///
718/// This proxy only exposes the const interface of the outer analysis manager,
719/// to indicate that you cannot cause an outer analysis to run from within an
720/// inner pass. Instead, you must rely on the \c getCachedResult API. This is
721/// due to keeping potential future concurrency in mind. To give an example,
722/// running a module analysis before any function passes may give a different
723/// result than running it in a function pass. Both may be valid, but it would
724/// produce non-deterministic results. GlobalsAA is a good analysis example,
725/// because the cached information has the mod/ref info for all memory for each
726/// function at the time the analysis was computed. The information is still
727/// valid after a function transformation, but it may be *different* if
728/// recomputed after that transform. GlobalsAA is never invalidated.
729
730///
731/// This proxy doesn't manage invalidation in any way -- that is handled by the
732/// recursive return path of each layer of the pass manager. A consequence of
733/// this is the outer analyses may be stale. We invalidate the outer analyses
734/// only when we're done running passes over the inner IR units.
735template <typename AnalysisManagerT, typename IRUnitT, typename... ExtraArgTs>
737 : public AnalysisInfoMixin<
738 OuterAnalysisManagerProxy<AnalysisManagerT, IRUnitT, ExtraArgTs...>> {
739public:
740 /// Result proxy object for \c OuterAnalysisManagerProxy.
741 class Result {
742 public:
743 explicit Result(const AnalysisManagerT &OuterAM) : OuterAM(&OuterAM) {}
744
745 /// Get a cached analysis. If the analysis can be invalidated, this will
746 /// assert.
747 template <typename PassT, typename IRUnitTParam>
748 typename PassT::Result *getCachedResult(IRUnitTParam &IR) const {
749 typename PassT::Result *Res =
750 OuterAM->template getCachedResult<PassT>(IR);
751 if (Res)
752 OuterAM->template verifyNotInvalidated<PassT>(IR, Res);
753 return Res;
754 }
755
756 /// Method provided for unit testing, not intended for general use.
757 template <typename PassT, typename IRUnitTParam>
758 bool cachedResultExists(IRUnitTParam &IR) const {
759 typename PassT::Result *Res =
760 OuterAM->template getCachedResult<PassT>(IR);
761 return Res != nullptr;
762 }
763
764 /// When invalidation occurs, remove any registered invalidation events.
766 IRUnitT &IRUnit, const PreservedAnalyses &PA,
768 // Loop over the set of registered outer invalidation mappings and if any
769 // of them map to an analysis that is now invalid, clear it out.
771 for (auto &KeyValuePair : OuterAnalysisInvalidationMap) {
772 AnalysisKey *OuterID = KeyValuePair.first;
773 auto &InnerIDs = KeyValuePair.second;
774 llvm::erase_if(InnerIDs, [&](AnalysisKey *InnerID) {
775 return Inv.invalidate(InnerID, IRUnit, PA);
776 });
777 if (InnerIDs.empty())
778 DeadKeys.push_back(OuterID);
779 }
780
781 for (auto *OuterID : DeadKeys)
782 OuterAnalysisInvalidationMap.erase(OuterID);
783
784 // The proxy itself remains valid regardless of anything else.
785 return false;
786 }
787
788 /// Register a deferred invalidation event for when the outer analysis
789 /// manager processes its invalidations.
790 template <typename OuterAnalysisT, typename InvalidatedAnalysisT>
792 AnalysisKey *OuterID = OuterAnalysisT::ID();
793 AnalysisKey *InvalidatedID = InvalidatedAnalysisT::ID();
794
795 auto &InvalidatedIDList = OuterAnalysisInvalidationMap[OuterID];
796 // Note, this is a linear scan. If we end up with large numbers of
797 // analyses that all trigger invalidation on the same outer analysis,
798 // this entire system should be changed to some other deterministic
799 // data structure such as a `SetVector` of a pair of pointers.
800 if (!llvm::is_contained(InvalidatedIDList, InvalidatedID))
801 InvalidatedIDList.push_back(InvalidatedID);
802 }
803
804 /// Access the map from outer analyses to deferred invalidation requiring
805 /// analyses.
808 return OuterAnalysisInvalidationMap;
809 }
810
811 private:
812 const AnalysisManagerT *OuterAM;
813
814 /// A map from an outer analysis ID to the set of this IR-unit's analyses
815 /// which need to be invalidated.
817 OuterAnalysisInvalidationMap;
818 };
819
820 OuterAnalysisManagerProxy(const AnalysisManagerT &OuterAM)
821 : OuterAM(&OuterAM) {}
822
823 /// Run the analysis pass and create our proxy result object.
824 /// Nothing to see here, it just forwards the \c OuterAM reference into the
825 /// result.
827 ExtraArgTs...) {
828 return Result(*OuterAM);
829 }
830
831private:
832 friend AnalysisInfoMixin<
833 OuterAnalysisManagerProxy<AnalysisManagerT, IRUnitT, ExtraArgTs...>>;
834
835 static AnalysisKey Key;
836
837 const AnalysisManagerT *OuterAM;
838};
839
840template <typename AnalysisManagerT, typename IRUnitT, typename... ExtraArgTs>
841AnalysisKey
842 OuterAnalysisManagerProxy<AnalysisManagerT, IRUnitT, ExtraArgTs...>::Key;
843
844extern template class LLVM_TEMPLATE_ABI
846/// Provide the \c ModuleAnalysisManager to \c Function proxy.
849
850/// Trivial adaptor that maps from a module to its functions.
851///
852/// Designed to allow composition of a FunctionPass(Manager) and
853/// a ModulePassManager, by running the FunctionPass(Manager) over every
854/// function in the module.
855///
856/// Function passes run within this adaptor can rely on having exclusive access
857/// to the function they are run over. They should not read or modify any other
858/// functions! Other threads or systems may be manipulating other functions in
859/// the module, and so their state should never be relied on.
860/// FIXME: Make the above true for all of LLVM's actual passes, some still
861/// violate this principle.
862///
863/// Function passes can also read the module containing the function, but they
864/// should not modify that module outside of the use lists of various globals.
865/// For example, a function pass is not permitted to add functions to the
866/// module.
867/// FIXME: Make the above true for all of LLVM's actual passes, some still
868/// violate this principle.
869///
870/// Note that although function passes can access module analyses, module
871/// analyses are not invalidated while the function passes are running, so they
872/// may be stale. Function analyses will not be stale.
875public:
877
878 explicit ModuleToFunctionPassAdaptor(std::unique_ptr<PassConceptT> Pass,
879 bool EagerlyInvalidate)
880 : Pass(std::move(Pass)), EagerlyInvalidate(EagerlyInvalidate) {}
881
882 /// Runs the function pass across every function in the module.
884 LLVM_ABI void
885 printPipeline(raw_ostream &OS,
886 function_ref<StringRef(StringRef)> MapClassName2PassName);
887
888private:
889 std::unique_ptr<PassConceptT> Pass;
890 bool EagerlyInvalidate;
891};
892
893/// A function to deduce a function pass type and wrap it in the
894/// templated adaptor.
895template <typename FunctionPassT>
896ModuleToFunctionPassAdaptor
898 bool EagerlyInvalidate = false) {
899 using PassModelT =
901 // Do not use make_unique, it causes too many template instantiations,
902 // causing terrible compile times.
904 std::unique_ptr<ModuleToFunctionPassAdaptor::PassConceptT>(
905 new PassModelT(std::forward<FunctionPassT>(Pass))),
906 EagerlyInvalidate);
907}
908
909/// A utility pass template to force an analysis result to be available.
910///
911/// If there are extra arguments at the pass's run level there may also be
912/// extra arguments to the analysis manager's \c getResult routine. We can't
913/// guess how to effectively map the arguments from one to the other, and so
914/// this specialization just ignores them.
915///
916/// Specific patterns of run-method extra arguments and analysis manager extra
917/// arguments will have to be defined as appropriate specializations.
918template <typename AnalysisT, typename IRUnitT,
919 typename AnalysisManagerT = AnalysisManager<IRUnitT>,
920 typename... ExtraArgTs>
922 : RequiredPassInfoMixin<RequireAnalysisPass<
923 AnalysisT, IRUnitT, AnalysisManagerT, ExtraArgTs...>> {
924 /// Run this pass over some unit of IR.
925 ///
926 /// This pass can be run over any unit of IR and use any analysis manager
927 /// provided they satisfy the basic API requirements. When this pass is
928 /// created, these methods can be instantiated to satisfy whatever the
929 /// context requires.
930 PreservedAnalyses run(IRUnitT &Arg, AnalysisManagerT &AM,
931 ExtraArgTs &&... Args) {
932 (void)AM.template getResult<AnalysisT>(Arg,
933 std::forward<ExtraArgTs>(Args)...);
934
935 return PreservedAnalyses::all();
936 }
938 function_ref<StringRef(StringRef)> MapClassName2PassName) {
939 auto ClassName = AnalysisT::name();
940 auto PassName = MapClassName2PassName(ClassName);
941 OS << "require<" << PassName << '>';
942 }
943};
944
945/// A no-op pass template which simply forces a specific analysis result
946/// to be invalidated.
947template <typename AnalysisT>
949 : RequiredPassInfoMixin<InvalidateAnalysisPass<AnalysisT>> {
950 /// Run this pass over some unit of IR.
951 ///
952 /// This pass can be run over any unit of IR and use any analysis manager,
953 /// provided they satisfy the basic API requirements. When this pass is
954 /// created, these methods can be instantiated to satisfy whatever the
955 /// context requires.
956 template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
957 PreservedAnalyses run(IRUnitT &Arg, AnalysisManagerT &AM, ExtraArgTs &&...) {
958 auto PA = PreservedAnalyses::all();
959 PA.abandon<AnalysisT>();
960 return PA;
961 }
963 function_ref<StringRef(StringRef)> MapClassName2PassName) {
964 auto ClassName = AnalysisT::name();
965 auto PassName = MapClassName2PassName(ClassName);
966 OS << "invalidate<" << PassName << '>';
967 }
968};
969
970/// A utility pass that does nothing, but preserves no analyses.
971///
972/// Because this preserves no analyses, any analysis passes queried after this
973/// pass runs will recompute fresh results.
975 : OptionalPassInfoMixin<InvalidateAllAnalysesPass> {
976 /// Run this pass over some unit of IR.
977 template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
978 PreservedAnalyses run(IRUnitT &, AnalysisManagerT &, ExtraArgTs &&...) {
980 }
981};
982
983} // end namespace llvm
984
985#endif // LLVM_IR_PASSMANAGER_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Function Alias Analysis Results
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_ABI
Definition Compiler.h:213
#define LLVM_TEMPLATE_ABI
Definition Compiler.h:214
#define LLVM_ATTRIBUTE_MINSIZE
Definition Compiler.h:328
#define LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
Definition Compiler.h:126
This file defines the DenseMap class.
Legalize the Machine IR a function s Machine IR
Definition Legalizer.cpp:81
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
#define P(N)
This header provides internal APIs and implementation details used by the pass management interfaces ...
This file contains some templates that are useful if you are working with the STL at all.
This file contains some functions that are useful when dealing with strings.
static const char PassName[]
Value * RHS
API to communicate dependencies between analyses during invalidation.
bool invalidate(AnalysisKey *ID, IRUnitT &IR, const PreservedAnalyses &PA)
A type-erased variant of the above invalidate method with the same core API other than passing an ana...
bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA)
Trigger the invalidation of some other analysis pass if not already handled and return whether it was...
A container for analyses that lazily runs them and caches their results.
bool isPassRegistered() const
Returns true if the specified analysis pass is registered.
AnalysisManager()
Construct an empty analysis manager.
void clear()
Clear all analysis results cached by this AnalysisManager.
AnalysisManager(AnalysisManager &&)
void verifyNotInvalidated(IRUnitT &IR, typename PassT::Result *Result) const
Verify that the given Result cannot be invalidated, assert otherwise.
AnalysisManager & operator=(AnalysisManager &&)
void clear(IRUnitT &IR, llvm::StringRef Name)
Clear any cached analysis results for a single unit of IR.
void invalidate(IRUnitT &IR, const PreservedAnalyses &PA)
Invalidate cached analyses for an IR unit.
void clearAnalysis(IRUnitT &IR)
Directly clear a cached analysis for an IR unit.
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
bool registerPass(PassBuilderT &&PassBuilder)
Register an analysis pass with the manager.
bool empty() const
Returns true if the analysis manager has an empty results cache.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA, typename AnalysisManager< IRUnitT, ExtraArgTs... >::Invalidator &Inv)
Handler for invalidation of the outer IR unit, IRUnitT.
Result(AnalysisManagerT &InnerAM)
AnalysisManagerT & getManager()
Accessor for the analysis manager.
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
Result run(IRUnitT &IR, AnalysisManager< IRUnitT, ExtraArgTs... > &AM, ExtraArgTs...)
Run the analysis pass and create our proxy result object.
InnerAnalysisManagerProxy(AnalysisManagerT &InnerAM)
A helper class to return the specified delimiter string after the first invocation of operator String...
Trivial adaptor that maps from a module to its functions.
detail::PassConcept< Function, FunctionAnalysisManager > PassConceptT
ModuleToFunctionPassAdaptor(std::unique_ptr< PassConceptT > Pass, bool EagerlyInvalidate)
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
Result(const AnalysisManagerT &OuterAM)
PassT::Result * getCachedResult(IRUnitTParam &IR) const
Get a cached analysis.
bool invalidate(IRUnitT &IRUnit, const PreservedAnalyses &PA, typename AnalysisManager< IRUnitT, ExtraArgTs... >::Invalidator &Inv)
When invalidation occurs, remove any registered invalidation events.
bool cachedResultExists(IRUnitTParam &IR) const
Method provided for unit testing, not intended for general use.
const SmallDenseMap< AnalysisKey *, TinyPtrVector< AnalysisKey * >, 2 > & getOuterInvalidations() const
Access the map from outer analyses to deferred invalidation requiring analyses.
void registerOuterAnalysisInvalidation()
Register a deferred invalidation event for when the outer analysis manager processes its invalidation...
An analysis over an "inner" IR unit that provides access to an analysis manager over a "outer" IR uni...
Result run(IRUnitT &, AnalysisManager< IRUnitT, ExtraArgTs... > &, ExtraArgTs...)
Run the analysis pass and create our proxy result object.
OuterAnalysisManagerProxy(const AnalysisManagerT &OuterAM)
This class provides access to building LLVM's passes.
Manages a sequence of passes over a particular unit of IR.
PassManager(PassManager &&Arg)
PassManager & operator=(PassManager &&RHS)
LLVM_ATTRIBUTE_MINSIZE std::enable_if_t<!std::is_same_v< PassT, PassManager > > addPass(PassT &&Pass)
void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
PassManager()=default
Construct a pass manager.
detail::PassConcept< LazyCallGraph::SCC, CGSCCAnalysisManager, ExtraArgTs... > PassConceptT
LLVM_ATTRIBUTE_MINSIZE std::enable_if_t< std::is_same_v< PassT, PassManager > > addPass(PassT &&Pass)
When adding a pass manager pass that has the same type as this pass manager, simply move the passes o...
PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs)
Run all of the passes in this manager over the given unit of IR.
bool isEmpty() const
Returns if the pass manager contains any passes.
Pass interface - Implemented by all 'passes'.
Definition Pass.h:99
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & abandon()
Mark an analysis as abandoned.
Definition Analysis.h:171
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
An efficient, type-erasing, non-owning reference to a callable.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
Pass manager infrastructure for declaring and invalidating analyses.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
A self-contained host- and target-independent arbitrary-precision floating-point software implementat...
Definition ADL.h:123
PassT::Result getAnalysisResultUnpackTuple(AnalysisManagerT &AM, IRUnitT &IR, std::tuple< ArgTs... > Args, std::index_sequence< Ns... >)
Actual unpacker of extra arguments in getAnalysisResult, passes only those tuple arguments that are m...
PassT::Result getAnalysisResult(AnalysisManager< IRUnitT, AnalysisArgTs... > &AM, IRUnitT &IR, std::tuple< MainArgTs... > Args)
Helper for partial unpacking of extra arguments in getAnalysisResult.
This is an optimization pass for GlobalISel generic memory operations.
ModuleToFunctionPassAdaptor createModuleToFunctionPassAdaptor(FunctionPassT &&Pass, bool EagerlyInvalidate=false)
A function to deduce a function pass type and wrap it in the templated adaptor.
OuterAnalysisManagerProxy< ModuleAnalysisManager, Function > ModuleAnalysisManagerFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
LLVM_GET_TYPE_NAME_CONSTEXPR StringRef getTypeName()
We provide a function which tries to compute the (demangled) name of a type statically.
Definition TypeName.h:40
LLVM_ABI void printIRUnitNameForStackTrace< Function >(raw_ostream &OS, const Function &IR)
void printIRUnitNameForStackTrace(raw_ostream &OS, const IRUnitT &IR)
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
LLVM_ABI void printIRUnitNameForStackTrace< Module >(raw_ostream &OS, const Module &IR)
PassManager< Module > ModulePassManager
Convenience typedef for a pass manager over modules.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
PassManager< Function > FunctionPassManager
Convenience typedef for a pass manager over functions.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1916
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1771
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
Definition STLExtras.h:2191
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1946
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:874
A CRTP mix-in that provides informational APIs needed for analysis passes.
static AnalysisKey * ID()
Returns an opaque, unique ID for this analysis type.
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition Analysis.h:29
A utility pass that does nothing, but preserves no analyses.
PreservedAnalyses run(IRUnitT &, AnalysisManagerT &, ExtraArgTs &&...)
Run this pass over some unit of IR.
A no-op pass template which simply forces a specific analysis result to be invalidated.
void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
PreservedAnalyses run(IRUnitT &Arg, AnalysisManagerT &AM, ExtraArgTs &&...)
Run this pass over some unit of IR.
A CRTP mix-in for passes that can be skipped.
A CRTP mix-in to automatically provide informational APIs needed for passes.
Definition PassManager.h:89
static bool isRequired()
Definition PassManager.h:98
void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
Definition PassManager.h:90
A utility pass template to force an analysis result to be available.
void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
PreservedAnalyses run(IRUnitT &Arg, AnalysisManagerT &AM, ExtraArgTs &&... Args)
Run this pass over some unit of IR.
A CRTP mix-in for passes that should not be skipped.
Abstract concept of an analysis pass.
Wrapper to model the analysis pass concept.
Abstract concept of an analysis result.
Wrapper to model the analysis result concept.
static StringRef name()
Gets the name of the pass we are mixed into.
Definition PassManager.h:63
Template for the abstract base class used to dispatch polymorphically over pass objects.
A template wrapper used to implement the polymorphic API.