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