37#ifndef LLVM_IR_PASSMANAGER_H
38#define LLVM_IR_PASSMANAGER_H
63template <
typename IRUnitT,
typename... ExtraArgTs>
class AnalysisManager;
72 static_assert(std::is_base_of<PassInfoMixin, DerivedT>::value,
73 "Must pass the derived type as the template argument!");
75 Name.consume_front(
"llvm::");
82 auto PassName = MapClassName2PassName(ClassName);
91template <
typename DerivedT>
109 static_assert(std::is_base_of<AnalysisInfoMixin, DerivedT>::value,
110 "Must pass the derived type as the template argument!");
111 return &DerivedT::Key;
119template <
typename PassT,
typename IRUnitT,
typename AnalysisManagerT,
120 typename... ArgTs,
size_t... Ns>
121typename PassT::Result
123 std::tuple<ArgTs...> Args,
124 std::index_sequence<Ns...>) {
126 return AM.template getResult<PassT>(
IR, std::get<Ns>(Args)...);
134template <
typename PassT,
typename IRUnitT,
typename... AnalysisArgTs,
135 typename... MainArgTs>
136typename PassT::Result
138 std::tuple<MainArgTs...> Args) {
140 PassT, IRUnitT>)(AM,
IR, Args,
141 std::index_sequence_for<AnalysisArgTs...>{});
158template <
typename IRUnitT,
159 typename AnalysisManagerT = AnalysisManager<IRUnitT>,
160 typename... ExtraArgTs>
162 PassManager<IRUnitT, AnalysisManagerT, ExtraArgTs...>> {
180 for (
unsigned Idx = 0,
Size =
Passes.size(); Idx !=
Size; ++Idx) {
182 P->printPipeline(OS, MapClassName2PassName);
191 ExtraArgTs... ExtraArgs);
193 template <
typename PassT>
200 Passes.push_back(std::unique_ptr<PassConceptT>(
201 new PassModelT(std::forward<PassT>(
Pass))));
209 template <
typename PassT>
212 for (
auto &
P :
Pass.Passes)
213 Passes.push_back(std::move(
P));
225 std::vector<std::unique_ptr<PassConceptT>>
Passes;
228template <
typename IRUnitT>
270 using AnalysisResultListT =
271 std::list<std::pair<AnalysisKey *, std::unique_ptr<ResultConceptT>>>;
279 using AnalysisResultMapT =
281 typename AnalysisResultListT::iterator>;
310 template <
typename PassT>
316 return invalidateImpl<ResultModelT>(PassT::ID(),
IR, PA);
326 return invalidateImpl<>(
ID,
IR, PA);
332 template <
typename ResultT = ResultConceptT>
337 auto IMapI = IsResultInvalidated.find(
ID);
338 if (IMapI != IsResultInvalidated.end())
339 return IMapI->second;
342 auto RI = Results.find({
ID, &
IR});
344 "Trying to invalidate a dependent result that isn't in the "
345 "manager's cache is always an error, likely due to a stale result "
348 auto &Result =
static_cast<ResultT &
>(*RI->second->second);
355 std::tie(IMapI, Inserted) =
356 IsResultInvalidated.insert({
ID, Result.invalidate(
IR, PA, *
this)});
358 assert(Inserted &&
"Should not have already inserted this ID, likely "
359 "indicates a dependency cycle!");
360 return IMapI->second;
363 Invalidator(SmallDenseMap<AnalysisKey *, bool, 8> &IsResultInvalidated,
364 const AnalysisResultMapT &
Results)
367 SmallDenseMap<AnalysisKey *, bool, 8> &IsResultInvalidated;
368 const AnalysisResultMapT &Results;
378 assert(AnalysisResults.empty() == AnalysisResultLists.empty() &&
379 "The storage and index of analysis results disagree on how many "
381 return AnalysisResults.empty();
398 AnalysisResults.clear();
399 AnalysisResultLists.clear();
404 return AnalysisPasses.count(PassT::ID());
410 template <
typename PassT>
411 typename PassT::Result &
getResult(IRUnitT &
IR, ExtraArgTs... ExtraArgs) {
412 assert(AnalysisPasses.count(PassT::ID()) &&
413 "This analysis pass was not registered prior to being queried");
414 ResultConceptT &ResultConcept =
415 getResultImpl(PassT::ID(),
IR, ExtraArgs...);
421 return static_cast<ResultModelT &
>(ResultConcept).Result;
429 template <
typename PassT>
431 assert(AnalysisPasses.count(PassT::ID()) &&
432 "This analysis pass was not registered prior to being queried");
434 ResultConceptT *ResultConcept = getCachedResultImpl(PassT::ID(),
IR);
442 return &
static_cast<ResultModelT *
>(ResultConcept)->Result;
446 template <
typename PassT>
450 Invalidator Inv(IsResultInvalidated, AnalysisResults);
451 assert(!Result->invalidate(
IR, PA, Inv) &&
452 "Cached result cannot be invalidated");
471 template <
typename PassBuilderT>
477 auto &PassPtr = AnalysisPasses[PassT::ID()];
499 AnalysisResultListT &ResultsList = AnalysisResultLists[&
IR];
504 assert(
I != ResultsList.end() &&
"Analysis must be available");
505 ResultsList.erase(
I);
506 AnalysisResults.erase({
ID, &
IR});
512 typename AnalysisPassMapT::iterator PI = AnalysisPasses.find(
ID);
513 assert(PI != AnalysisPasses.end() &&
514 "Analysis passes must be registered prior to being queried!");
519 const PassConceptT &lookUpPass(AnalysisKey *
ID)
const {
520 typename AnalysisPassMapT::const_iterator PI = AnalysisPasses.find(
ID);
521 assert(PI != AnalysisPasses.end() &&
522 "Analysis passes must be registered prior to being queried!");
527 ResultConceptT &getResultImpl(AnalysisKey *
ID, IRUnitT &
IR,
528 ExtraArgTs... ExtraArgs);
531 ResultConceptT *getCachedResultImpl(AnalysisKey *
ID, IRUnitT &
IR)
const {
532 typename AnalysisResultMapT::const_iterator RI =
533 AnalysisResults.find({
ID, &
IR});
534 return RI == AnalysisResults.end() ? nullptr : &*RI->second->second;
538 using AnalysisPassMapT =
539 DenseMap<AnalysisKey *, std::unique_ptr<PassConceptT>>;
542 AnalysisPassMapT AnalysisPasses;
548 AnalysisResultListMapT AnalysisResultLists;
552 AnalysisResultMapT AnalysisResults;
581template <
typename AnalysisManagerT,
typename IRUnitT,
typename... ExtraArgTs>
584 InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT>> {
588 explicit Result(AnalysisManagerT &InnerAM) : InnerAM(&InnerAM) {}
594 Arg.InnerAM =
nullptr;
608 InnerAM =
RHS.InnerAM;
612 RHS.InnerAM =
nullptr;
634 AnalysisManagerT *InnerAM;
638 : InnerAM(&InnerAM) {}
647 return Result(*InnerAM);
656 AnalysisManagerT *InnerAM;
665template <
typename AnalysisManagerT,
typename IRUnitT,
typename... ExtraArgTs>
676LLVM_ABI bool FunctionAnalysisManagerModuleProxy::Result::invalidate(
678 ModuleAnalysisManager::Invalidator &Inv);
712template <
typename AnalysisManagerT,
typename IRUnitT,
typename... ExtraArgTs>
715 OuterAnalysisManagerProxy<AnalysisManagerT, IRUnitT, ExtraArgTs...>> {
720 explicit Result(
const AnalysisManagerT &OuterAM) : OuterAM(&OuterAM) {}
724 template <
typename PassT,
typename IRUnitTParam>
726 typename PassT::Result *Res =
729 OuterAM->template verifyNotInvalidated<PassT>(
IR, Res);
734 template <
typename PassT,
typename IRUnitTParam>
736 typename PassT::Result *Res =
738 return Res !=
nullptr;
748 for (
auto &KeyValuePair : OuterAnalysisInvalidationMap) {
750 auto &InnerIDs = KeyValuePair.second;
754 if (InnerIDs.empty())
758 for (
auto *OuterID : DeadKeys)
759 OuterAnalysisInvalidationMap.
erase(OuterID);
767 template <
typename OuterAnalysisT,
typename Inval
idatedAnalysisT>
770 AnalysisKey *InvalidatedID = InvalidatedAnalysisT::ID();
772 auto &InvalidatedIDList = OuterAnalysisInvalidationMap[OuterID];
778 InvalidatedIDList.push_back(InvalidatedID);
785 return OuterAnalysisInvalidationMap;
789 const AnalysisManagerT *OuterAM;
794 OuterAnalysisInvalidationMap;
798 : OuterAM(&OuterAM) {}
805 return Result(*OuterAM);
814 const AnalysisManagerT *OuterAM;
817template <
typename AnalysisManagerT,
typename IRUnitT,
typename... ExtraArgTs>
856 bool EagerlyInvalidate)
857 : Pass(
std::
move(Pass)), EagerlyInvalidate(EagerlyInvalidate) {}
868 std::unique_ptr<PassConceptT>
Pass;
869 bool EagerlyInvalidate;
874template <
typename FunctionPassT>
875ModuleToFunctionPassAdaptor
877 bool EagerlyInvalidate =
false) {
883 std::unique_ptr<ModuleToFunctionPassAdaptor::PassConceptT>(
884 new PassModelT(std::forward<FunctionPassT>(
Pass))),
897template <
typename AnalysisT,
typename IRUnitT,
898 typename AnalysisManagerT = AnalysisManager<IRUnitT>,
899 typename... ExtraArgTs>
901 :
PassInfoMixin<RequireAnalysisPass<AnalysisT, IRUnitT, AnalysisManagerT,
910 ExtraArgTs &&... Args) {
911 (void)AM.template getResult<AnalysisT>(Arg,
912 std::forward<ExtraArgTs>(Args)...);
918 auto ClassName = AnalysisT::name();
919 auto PassName = MapClassName2PassName(ClassName);
920 OS <<
"require<" <<
PassName <<
'>';
927template <
typename AnalysisT>
936 template <
typename IRUnitT,
typename AnalysisManagerT,
typename... ExtraArgTs>
944 auto ClassName = AnalysisT::name();
945 auto PassName = MapClassName2PassName(ClassName);
946 OS <<
"invalidate<" <<
PassName <<
'>';
956 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.
Legalize the Machine IR a function s Machine IR
This header provides internal APIs and implementation details used by the pass management interfaces ...
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.
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)
Trivial adaptor that maps from a module to its functions.
detail::PassConcept< Function, FunctionAnalysisManager > PassConceptT
ModuleToFunctionPassAdaptor(std::unique_ptr< PassConceptT > Pass, bool EagerlyInvalidate)
A Module instance is used to store all the information related to an LLVM module.
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)
std::vector< std::unique_ptr< PassConceptT > > Passes
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'.
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.
StringRef - Represent a constant reference to a string, i.e.
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
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.
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 to automatically provide informational APIs needed for passes.
static StringRef name()
Gets the name of the pass we are mixed into.
void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
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.
Abstract concept of an analysis pass.
Wrapper to model the analysis pass concept.
Abstract concept of an analysis result.
Wrapper to model the analysis result concept.
Template for the abstract base class used to dispatch polymorphically over pass objects.
A template wrapper used to implement the polymorphic API.