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