37#ifndef LLVM_IR_PASSMANAGER_H
38#define LLVM_IR_PASSMANAGER_H
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::");
81template <
typename DerivedT>
86 auto PassName = MapClassName2PassName(ClassName);
99template <
typename IRUnitT,
typename... ExtraArgTs>
class AnalysisManager;
102template <
typename DerivedT>
113template <
typename DerivedT>
122template <
typename DerivedT>
140 static_assert(std::is_base_of<AnalysisInfoMixin, DerivedT>::value,
141 "Must pass the derived type as the template argument!");
142 return &DerivedT::Key;
150template <
typename PassT,
typename IRUnitT,
typename AnalysisManagerT,
151 typename... ArgTs,
size_t... Ns>
152typename PassT::Result
154 std::tuple<ArgTs...> Args,
155 std::index_sequence<Ns...>) {
157 return AM.template getResult<PassT>(
IR, std::get<Ns>(Args)...);
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...>{});
189template <
typename IRUnitT,
190 typename AnalysisManagerT = AnalysisManager<IRUnitT>,
191 typename... ExtraArgTs>
193 PassManager<IRUnitT, AnalysisManagerT, ExtraArgTs...>> {
214 P->printPipeline(OS, MapClassName2PassName);
221 ExtraArgTs... ExtraArgs);
223 template <
typename PassT>
228 Passes.push_back(PassModelT::create(std::move(
Pass)));
236 template <
typename PassT>
239 for (
auto &
P :
Pass.Passes)
240 Passes.push_back(std::move(
P));
250 std::vector<typename PassConceptT::unique_ptr>
Passes;
253template <
typename IRUnitT>
295 using AnalysisResultListT =
305 using AnalysisResultMapT =
335 template <
typename PassT>
341 return invalidateImpl<ResultModelT>(PassT::ID(),
IR, PA);
351 return invalidateImpl<>(ID,
IR, PA);
357 template <
typename ResultT = ResultConceptT>
362 auto IMapI = IsResultInvalidated.find(ID);
363 if (IMapI != IsResultInvalidated.end())
364 return IMapI->second;
367 auto RI = Results.find({ID, &
IR});
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 "
373 auto &Result =
static_cast<ResultT &
>(*RI->second);
380 std::tie(IMapI, Inserted) =
381 IsResultInvalidated.insert({ID, Result.invalidate(
IR, PA, *
this)});
383 assert(Inserted &&
"Should not have already inserted this ID, likely "
384 "indicates a dependency cycle!");
385 return IMapI->second;
388 Invalidator(SmallDenseMap<AnalysisKey *, bool, 8> &IsResultInvalidated,
389 const AnalysisResultMapT &
Results)
392 SmallDenseMap<AnalysisKey *, bool, 8> &IsResultInvalidated;
393 const AnalysisResultMapT &Results;
403 assert(AnalysisResults.empty() == AnalysisResultLists.empty() &&
404 "The storage and index of analysis results disagree on how many "
406 return AnalysisResults.empty();
423 AnalysisResults.clear();
424 AnalysisResultLists.clear();
429 return AnalysisPasses.count(PassT::ID());
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...);
446 return static_cast<ResultModelT &
>(ResultConcept).Result;
454 template <
typename PassT>
456 assert(AnalysisPasses.count(PassT::ID()) &&
457 "This analysis pass was not registered prior to being queried");
459 ResultConceptT *ResultConcept = getCachedResultImpl(PassT::ID(),
IR);
467 return &
static_cast<ResultModelT *
>(ResultConcept)->Result;
471 template <
typename PassT>
475 Invalidator Inv(IsResultInvalidated, AnalysisResults);
476 assert(!Result->invalidate(
IR, PA, Inv) &&
477 "Cached result cannot be invalidated");
496 template <
typename PassBuilderT>
502 auto &PassPtr = AnalysisPasses[PassT::ID()];
524 auto ResultsListI = AnalysisResultLists.find(&
IR);
525 assert(ResultsListI != AnalysisResultLists.end() &&
526 "Analysis must be available");
527 AnalysisResultListT &ResultsList = ResultsListI->second;
532 assert(
I != ResultsList.
end() &&
"Analysis must be available");
534 AnalysisResults.erase({ID, &
IR});
542 "Analysis passes must be registered prior to being queried!");
547 const PassConceptT &lookUpPass(AnalysisKey *ID)
const {
550 "Analysis passes must be registered prior to being queried!");
555 ResultConceptT &getResultImpl(AnalysisKey *ID, IRUnitT &
IR,
556 ExtraArgTs... ExtraArgs);
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;
566 using AnalysisPassMapT =
567 DenseMap<AnalysisKey *, typename PassConceptT::unique_ptr>;
570 AnalysisPassMapT AnalysisPasses;
576 AnalysisResultListMapT AnalysisResultLists;
580 AnalysisResultMapT AnalysisResults;
609template <
typename AnalysisManagerT,
typename IRUnitT,
typename... ExtraArgTs>
612 InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT>> {
616 explicit Result(AnalysisManagerT &InnerAM) : InnerAM(&InnerAM) {}
622 Arg.InnerAM =
nullptr;
636 InnerAM =
RHS.InnerAM;
640 RHS.InnerAM =
nullptr;
662 AnalysisManagerT *InnerAM;
666 : InnerAM(&InnerAM) {}
675 return Result(*InnerAM);
684 AnalysisManagerT *InnerAM;
693template <
typename AnalysisManagerT,
typename IRUnitT,
typename... ExtraArgTs>
704LLVM_ABI bool FunctionAnalysisManagerModuleProxy::Result::invalidate(
706 ModuleAnalysisManager::Invalidator &Inv);
740template <
typename AnalysisManagerT,
typename IRUnitT,
typename... ExtraArgTs>
743 OuterAnalysisManagerProxy<AnalysisManagerT, IRUnitT, ExtraArgTs...>> {
748 explicit Result(
const AnalysisManagerT &OuterAM) : OuterAM(&OuterAM) {}
752 template <
typename PassT,
typename IRUnitTParam>
754 typename PassT::Result *Res =
757 OuterAM->template verifyNotInvalidated<PassT>(
IR, Res);
762 template <
typename PassT,
typename IRUnitTParam>
764 typename PassT::Result *Res =
766 return Res !=
nullptr;
776 for (
auto &KeyValuePair : OuterAnalysisInvalidationMap) {
778 auto &InnerIDs = KeyValuePair.second;
782 if (InnerIDs.empty())
786 for (
auto *OuterID : DeadKeys)
787 OuterAnalysisInvalidationMap.
erase(OuterID);
795 template <
typename OuterAnalysisT,
typename Inval
idatedAnalysisT>
798 AnalysisKey *InvalidatedID = InvalidatedAnalysisT::ID();
800 auto &InvalidatedIDList = OuterAnalysisInvalidationMap[OuterID];
806 InvalidatedIDList.push_back(InvalidatedID);
813 return OuterAnalysisInvalidationMap;
817 const AnalysisManagerT *OuterAM;
822 OuterAnalysisInvalidationMap;
826 : OuterAM(&OuterAM) {}
833 return Result(*OuterAM);
842 const AnalysisManagerT *OuterAM;
845template <
typename AnalysisManagerT,
typename IRUnitT,
typename... ExtraArgTs>
884 bool EagerlyInvalidate)
885 : Pass(
std::
move(Pass)), EagerlyInvalidate(EagerlyInvalidate) {}
894 PassConceptT::unique_ptr
Pass;
895 bool EagerlyInvalidate;
900template <
typename FunctionPassT>
901ModuleToFunctionPassAdaptor
903 bool EagerlyInvalidate =
false) {
919template <
typename AnalysisT,
typename IRUnitT,
920 typename AnalysisManagerT = AnalysisManager<IRUnitT>,
921 typename... ExtraArgTs>
924 AnalysisT, IRUnitT, AnalysisManagerT, ExtraArgTs...>> {
932 ExtraArgTs &&... Args) {
933 (void)AM.template getResult<AnalysisT>(Arg,
934 std::forward<ExtraArgTs>(Args)...);
940 auto ClassName = AnalysisT::name();
941 auto PassName = MapClassName2PassName(ClassName);
942 OS <<
"require<" <<
PassName <<
'>';
948template <
typename AnalysisT>
957 template <
typename IRUnitT,
typename AnalysisManagerT,
typename... ExtraArgTs>
965 auto ClassName = AnalysisT::name();
966 auto PassName = MapClassName2PassName(ClassName);
967 OS <<
"invalidate<" <<
PassName <<
'>';
978 template <
typename IRUnitT,
typename AnalysisManagerT,
typename... ExtraArgTs>
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Function Alias Analysis Results
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_TEMPLATE_ABI
#define LLVM_ATTRIBUTE_MINSIZE
#define LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
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
Machine Check Debug Module
This header provides internal APIs and implementation details used by the pass management interfaces ...
This file defines the SmallVector class.
static const char PassName[]
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...
friend class AnalysisManager
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)
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT, true > const_iterator
A type-erased reference to the IR unit a pass or analysis is running on, together with the kind of IR...
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)
Result & operator=(Result &&RHS)
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.
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...
std::vector< typename PassConceptT::unique_ptr > Passes
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'.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & abandon()
Mark an analysis as abandoned.
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.
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.
std::unique_ptr< PassConcept, Deleter > unique_ptr
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.
Pass manager infrastructure for declaring and invalidating analyses.
A self-contained host- and target-independent arbitrary-precision floating-point software implementat...
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.
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.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Implement std::hash so that hash_code can be used in STL containers.
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...
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.
A CRTP mix-in to automatically provide informational APIs needed for passes.
void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)