38 #ifndef LLVM_IR_PASSMANAGER_H
39 #define LLVM_IR_PASSMANAGER_H
115 PA.PreservedIDs.
insert(&AllAnalysesKey);
126 NotPreservedAnalysisIDs.erase(ID);
163 PreservedIDs.
erase(ID);
164 NotPreservedAnalysisIDs.insert(ID);
180 for (
auto ID : Arg.NotPreservedAnalysisIDs) {
182 NotPreservedAnalysisIDs.insert(
ID);
184 for (
auto ID : PreservedIDs)
185 if (!Arg.PreservedIDs.
count(
ID))
186 PreservedIDs.erase(
ID);
194 if (Arg.areAllPreserved())
197 *
this = std::move(Arg);
202 for (
auto ID : Arg.NotPreservedAnalysisIDs) {
204 NotPreservedAnalysisIDs.insert(
ID);
206 for (
auto ID : PreservedIDs)
207 if (!Arg.PreservedIDs.count(
ID))
208 PreservedIDs.erase(
ID);
218 const bool IsAbandoned;
224 : PA(PA), ID(ID), IsAbandoned(PA.NotPreservedAnalysisIDs.
count(ID)) {}
231 return !IsAbandoned && (PA.PreservedIDs.
count(&AllAnalysesKey) ||
240 return !IsAbandoned && (PA.PreservedIDs.
count(&AllAnalysesKey) ||
241 PA.PreservedIDs.
count(SetID));
268 return NotPreservedAnalysisIDs.empty() &&
269 PreservedIDs.
count(&AllAnalysesKey);
283 return NotPreservedAnalysisIDs.empty() &&
284 (PreservedIDs.
count(&AllAnalysesKey) || PreservedIDs.
count(SetID));
305 template <
typename IRUnitT,
typename... ExtraArgTs>
class AnalysisManager;
314 static_assert(std::is_base_of<PassInfoMixin, DerivedT>::value,
315 "Must pass the derived type as the template argument!");
327 template <
typename DerivedT>
345 static_assert(std::is_base_of<AnalysisInfoMixin, DerivedT>::value,
346 "Must pass the derived type as the template argument!");
347 return &DerivedT::Key;
360 template <
typename IRUnitT>
369 template <
typename IRUnitT> AnalysisSetKey AllAnalysesOn<IRUnitT>::SetKey;
371 extern template class AllAnalysesOn<Module>;
372 extern template class AllAnalysesOn<Function>;
386 template <
typename IRUnitT,
387 typename AnalysisManagerT = AnalysisManager<IRUnitT>,
388 typename... ExtraArgTs>
390 PassManager<IRUnitT, AnalysisManagerT, ExtraArgTs...>> {
395 explicit PassManager(
bool DebugLogging =
false) : DebugLogging(DebugLogging) {}
402 : Passes(std::move(Arg.Passes)),
403 DebugLogging(std::move(Arg.DebugLogging)) {}
406 Passes = std::move(RHS.Passes);
407 DebugLogging = std::move(RHS.DebugLogging);
414 ExtraArgTs... ExtraArgs) {
418 dbgs() <<
"Starting " << getTypeName<IRUnitT>() <<
" pass manager run.\n";
420 for (
unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) {
422 dbgs() <<
"Running pass: " << Passes[Idx]->name() <<
" on "
423 << IR.getName() <<
"\n";
429 AM.invalidate(IR, PassPA);
449 dbgs() <<
"Finished " << getTypeName<IRUnitT>() <<
" pass manager run.\n";
456 AnalysisManagerT, ExtraArgTs...>
458 Passes.emplace_back(
new PassModelT(std::move(Pass)));
465 std::vector<std::unique_ptr<PassConceptT>> Passes;
471 extern template class PassManager<Module>;
484 template <
typename IRUnitT,
typename... ExtraArgTs>
class AnalysisManager {
502 typedef std::list<std::pair<AnalysisKey *, std::unique_ptr<ResultConceptT>>>
512 typename AnalysisResultListT::iterator>
542 template <
typename PassT>
545 typename PassT::Result,
548 return invalidateImpl<ResultModelT>(
PassT::ID(),
IR, PA);
558 return invalidateImpl<>(
ID,
IR, PA);
564 template <
typename ResultT = ResultConceptT>
569 auto IMapI = IsResultInvalidated.find(ID);
570 if (IMapI != IsResultInvalidated.end())
571 return IMapI->second;
574 auto RI =
Results.find({ID, &IR});
576 "Trying to invalidate a dependent result that isn't in the "
577 "manager's cache is always an error, likely due to a stale result "
580 auto &Result =
static_cast<ResultT &
>(*RI->second->second);
587 std::tie(IMapI, Inserted) =
588 IsResultInvalidated.insert({
ID, Result.invalidate(IR, PA, *
this)});
590 assert(Inserted &&
"Should not have already inserted this ID, likely "
591 "indicates a dependency cycle!");
592 return IMapI->second;
595 Invalidator(SmallDenseMap<AnalysisKey *, bool, 8> &IsResultInvalidated,
596 const AnalysisResultMapT &
Results)
597 : IsResultInvalidated(IsResultInvalidated), Results(Results) {}
599 SmallDenseMap<AnalysisKey *, bool, 8> &IsResultInvalidated;
600 const AnalysisResultMapT &
Results;
612 assert(AnalysisResults.empty() == AnalysisResultLists.empty() &&
613 "The storage and index of analysis results disagree on how many "
615 return AnalysisResults.empty();
625 dbgs() <<
"Clearing all analysis results for: " << IR.getName() <<
"\n";
627 auto ResultsListI = AnalysisResultLists.find(&IR);
628 if (ResultsListI == AnalysisResultLists.end())
631 for (
auto &IDAndResult : ResultsListI->second)
632 AnalysisResults.erase({IDAndResult.first, &IR});
635 AnalysisResultLists.erase(ResultsListI);
645 AnalysisResults.clear();
646 AnalysisResultLists.clear();
652 template <
typename PassT>
653 typename PassT::Result &
getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs) {
655 "This analysis pass was not registered prior to being queried");
657 getResultImpl(
PassT::ID(), IR, ExtraArgs...);
661 return static_cast<ResultModelT &
>(ResultConcept).Result;
669 template <
typename PassT>
672 "This analysis pass was not registered prior to being queried");
681 return &
static_cast<ResultModelT *
>(ResultConcept)->Result;
701 template <
typename PassBuilderT>
708 auto &PassPtr = AnalysisPasses[
PassT::ID()];
724 "This analysis pass was not registered prior to being invalidated");
738 dbgs() <<
"Invalidating all non-preserved analyses for: " << IR.getName()
744 Invalidator Inv(IsResultInvalidated, AnalysisResults);
745 AnalysisResultListT &ResultsList = AnalysisResultLists[&
IR];
746 for (
auto &AnalysisResultPair : ResultsList) {
752 auto &Result = *AnalysisResultPair.second;
754 auto IMapI = IsResultInvalidated.
find(ID);
755 if (IMapI != IsResultInvalidated.
end())
765 IsResultInvalidated.
insert({
ID, Result.invalidate(IR, PA, Inv)})
768 assert(Inserted &&
"Should never have already inserted this ID, likely "
769 "indicates a cycle!");
773 if (!IsResultInvalidated.
empty()) {
774 for (
auto I = ResultsList.begin(),
E = ResultsList.end();
I !=
E;) {
776 if (!IsResultInvalidated.
lookup(ID)) {
782 dbgs() <<
"Invalidating analysis: " << this->lookUpPass(ID).name()
785 I = ResultsList.erase(
I);
786 AnalysisResults.erase({
ID, &IR});
790 if (ResultsList.empty())
791 AnalysisResultLists.erase(&IR);
797 typename AnalysisPassMapT::iterator PI = AnalysisPasses.find(ID);
798 assert(PI != AnalysisPasses.end() &&
799 "Analysis passes must be registered prior to being queried!");
804 const PassConceptT &lookUpPass(AnalysisKey *ID)
const {
805 typename AnalysisPassMapT::const_iterator PI = AnalysisPasses.find(ID);
806 assert(PI != AnalysisPasses.end() &&
807 "Analysis passes must be registered prior to being queried!");
812 ResultConceptT &getResultImpl(AnalysisKey *ID, IRUnitT &IR,
813 ExtraArgTs... ExtraArgs) {
814 typename AnalysisResultMapT::iterator RI;
816 std::tie(RI, Inserted) = AnalysisResults.insert(std::make_pair(
817 std::make_pair(ID, &IR),
typename AnalysisResultListT::iterator()));
822 auto &
P = this->lookUpPass(ID);
824 dbgs() <<
"Running analysis: " <<
P.name() <<
"\n";
825 AnalysisResultListT &ResultList = AnalysisResultLists[&
IR];
826 ResultList.emplace_back(ID,
P.run(IR, *
this, ExtraArgs...));
830 RI = AnalysisResults.find({
ID, &IR});
831 assert(RI != AnalysisResults.end() &&
"we just inserted it!");
833 RI->second = std::prev(ResultList.end());
836 return *RI->second->second;
840 ResultConceptT *getCachedResultImpl(AnalysisKey *ID, IRUnitT &IR)
const {
841 typename AnalysisResultMapT::const_iterator RI =
842 AnalysisResults.find({
ID, &IR});
843 return RI == AnalysisResults.end() ?
nullptr : &*RI->second->second;
847 void invalidateImpl(AnalysisKey *ID, IRUnitT &IR) {
848 typename AnalysisResultMapT::iterator RI =
849 AnalysisResults.find({
ID, &IR});
850 if (RI == AnalysisResults.end())
854 dbgs() <<
"Invalidating analysis: " << this->lookUpPass(ID).name()
856 AnalysisResultLists[&
IR].erase(RI->second);
857 AnalysisResults.erase(RI);
861 typedef DenseMap<AnalysisKey *, std::unique_ptr<PassConceptT>> AnalysisPassMapT;
864 AnalysisPassMapT AnalysisPasses;
870 AnalysisResultListMapT AnalysisResultLists;
874 AnalysisResultMapT AnalysisResults;
880 extern template class AnalysisManager<Module>;
904 template <
typename AnalysisManagerT,
typename IRUnitT,
typename... ExtraArgTs>
907 InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT>> {
911 explicit Result(AnalysisManagerT &InnerAM) : InnerAM(&InnerAM) {}
916 Arg.InnerAM =
nullptr;
919 InnerAM = RHS.InnerAM;
923 RHS.InnerAM =
nullptr;
954 AnalysisManagerT *InnerAM;
958 : InnerAM(&InnerAM) {}
975 AnalysisManagerT *InnerAM;
978 template <
typename AnalysisManagerT,
typename IRUnitT,
typename... ExtraArgTs>
980 InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT, ExtraArgTs...>::Key;
983 typedef InnerAnalysisManagerProxy<FunctionAnalysisManager, Module>
989 bool FunctionAnalysisManagerModuleProxy::Result::invalidate(
1016 template <
typename AnalysisManagerT,
typename IRUnitT,
typename... ExtraArgTs>
1019 OuterAnalysisManagerProxy<AnalysisManagerT, IRUnitT, ExtraArgTs...>> {
1024 explicit Result(
const AnalysisManagerT &AM) : AM(&AM) {}
1037 template <
typename OuterAnalysisT,
typename Inval
idatedAnalysisT>
1042 auto &InvalidatedIDList = OuterAnalysisInvalidationMap[OuterID];
1047 auto InvalidatedIt =
std::find(InvalidatedIDList.begin(),
1048 InvalidatedIDList.end(), InvalidatedID);
1049 if (InvalidatedIt == InvalidatedIDList.end())
1050 InvalidatedIDList.push_back(InvalidatedID);
1057 return OuterAnalysisInvalidationMap;
1061 const AnalysisManagerT *AM;
1066 OuterAnalysisInvalidationMap;
1084 const AnalysisManagerT *AM;
1087 template <
typename AnalysisManagerT,
typename IRUnitT,
typename... ExtraArgTs>
1089 OuterAnalysisManagerProxy<AnalysisManagerT, IRUnitT, ExtraArgTs...>::Key;
1094 typedef OuterAnalysisManagerProxy<ModuleAnalysisManager, Function>
1120 template <
typename FunctionPassT>
1122 :
public PassInfoMixin<ModuleToFunctionPassAdaptor<FunctionPassT>> {
1125 : Pass(std::move(Pass)) {}
1129 FunctionAnalysisManager &FAM =
1133 for (Function &
F : M) {
1134 if (
F.isDeclaration())
1165 template <
typename FunctionPassT>
1166 ModuleToFunctionPassAdaptor<FunctionPassT>
1180 template <
typename AnalysisT,
typename IRUnitT,
1181 typename AnalysisManagerT = AnalysisManager<IRUnitT>,
1182 typename... ExtraArgTs>
1184 :
PassInfoMixin<RequireAnalysisPass<AnalysisT, IRUnitT, AnalysisManagerT,
1193 ExtraArgTs &&...
Args) {
1194 (void)AM.template getResult<AnalysisT>(Arg,
1195 std::forward<ExtraArgTs>(
Args)...);
1197 return PreservedAnalyses::all();
1203 template <
typename AnalysisT>
1212 template <
typename IRUnitT,
typename AnalysisManagerT,
typename... ExtraArgTs>
1214 auto PA = PreservedAnalyses::all();
1226 template <
typename IRUnitT,
typename AnalysisManagerT,
typename... ExtraArgTs>
1228 return PreservedAnalyses::none();
1236 template <
typename PassT>
1241 template <
typename IRUnitT,
typename AnalysisManagerT,
typename... Ts>
1243 auto PA = PreservedAnalyses::all();
1244 for (
int i = 0;
i < Count; ++
i)
1254 template <
typename PassT>
Pass interface - Implemented by all 'passes'.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
void abandon()
Mark an analysis as abandoned.
PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs...ExtraArgs)
Run all of the passes in this manager over the given unit of IR.
bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA)
Trigger the invalidation of some other analysis pass if not already handled and return whether it was...
Wrapper to model the analysis pass concept.
const SmallDenseMap< AnalysisKey *, TinyPtrVector< AnalysisKey * >, 2 > & getOuterInvalidations() const
Access the map from outer analyses to deferred invalidation requiring analyses.
ValueT lookup(const KeyT &Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
void intersect(const PreservedAnalyses &Arg)
Intersect this set with another in place.
Trivial adaptor that maps from a module to its functions.
A Module instance is used to store all the information related to an LLVM module. ...
aarch64 AArch64 CCMP Pass
PassManager(bool DebugLogging=false)
Construct a pass manager.
RepeatedPass< PassT > createRepeatedPass(int Count, PassT P)
size_type count(PtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
RepeatedPass(int Count, PassT P)
Function Alias Analysis Results
Template for the abstract base class used to dispatch polymorphically over pass objects.
A utility pass template that simply runs another pass multiple times.
A utility pass template to force an analysis result to be available.
Abstract concept of an analysis pass.
OuterAnalysisManagerProxy(const AnalysisManagerT &AM)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
static AnalysisKey * ID()
Returns an opaque, unique ID for this analysis type.
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
bool registerPass(PassBuilderT &&PassBuilder)
Register an analysis pass with the manager.
This class provides access to building LLVM's passes.
AnalysisManagerT & getManager()
Accessor for the analysis manager.
bool allAnalysesInSetPreserved(AnalysisSetKey *SetID) const
Directly test whether a set of analyses is preserved.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
PassManager(PassManager &&Arg)
AnalysisManager(bool DebugLogging=false)
Construct an empty analysis manager.
A CRTP mix-in to automatically provide informational APIs needed for passes.
PreservedAnalyses run(IRUnitT &Arg, AnalysisManagerT &AM, Ts &&...Args)
Result run(IRUnitT &IR, AnalysisManager< IRUnitT, ExtraArgTs...> &AM, ExtraArgTs...)
Run the analysis pass and create our proxy result object.
auto count(R &&Range, const E &Element) -> typename std::iterator_traits< decltype(std::begin(Range))>::difference_type
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Result run(IRUnitT &, AnalysisManager< IRUnitT, ExtraArgTs...> &, ExtraArgTs...)
Run the analysis pass and create our proxy result object.
void registerOuterAnalysisInvalidation()
Register a deferred invalidation event for when the outer analysis manager processes its invalidation...
const AnalysisManagerT & getManager() const
PreservedAnalyses run(IRUnitT &Arg, AnalysisManagerT &AM, ExtraArgTs &&...Args)
Run this pass over some unit of IR.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
A checker object that makes it easy to query for whether an analysis or some set covering it is prese...
A set of analyses that are preserved following a run of a transformation pass.
InnerAnalysisManagerProxy(AnalysisManagerT &InnerAM)
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs...ExtraArgs)
Get the result of an analysis pass for a given IR unit.
ModuleToFunctionPassAdaptor< FunctionPassT > createModuleToFunctionPassAdaptor(FunctionPassT Pass)
A function to deduce a function pass type and wrap it in the templated adaptor.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
A CRTP mix-in that provides informational APIs needed for analysis passes.
Wrapper to model the analysis result concept.
bool preservedSet()
Returns true if the checker's analysis was not abandoned and either.
void clear()
Clear all analysis results cached by this AnalysisManager.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
PreservedAnalyses run(IRUnitT &, AnalysisManagerT &, ExtraArgTs &&...)
Run this pass over some unit of IR.
static StringRef name()
Gets the name of the pass we are mixed into.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void intersect(PreservedAnalyses &&Arg)
Intersect this set with a temporary other set in place.
bool areAllPreserved() const
Test whether all analyses are preserved (and none are abandoned).
PassManager & operator=(PassManager &&RHS)
Result proxy object for OuterAnalysisManagerProxy.
ModuleToFunctionPassAdaptor(FunctionPassT Pass)
void clear(IRUnitT &IR)
Clear any cached analysis results for a single unit of IR.
auto find(R &&Range, const T &Val) -> decltype(std::begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
bool erase(PtrType Ptr)
erase - If the set contains the specified pointer, remove it and return true, otherwise return false...
An analysis over an "inner" IR unit that provides access to an analysis manager over a "outer" IR uni...
A template wrapper used to implement the polymorphic API.
Module.h This file contains the declarations for the Module class.
void invalidate(IRUnitT &IR)
Invalidate a specific analysis pass for an IR module.
Abstract concept of an analysis result.
A utility pass that does nothing, but preserves no analyses.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
OuterAnalysisManagerProxy< ModuleAnalysisManager, Function > ModuleAnalysisManagerFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
Result(AnalysisManagerT &InnerAM)
static AnalysisSetKey * ID()
This header provides internal APIs and implementation details used by the pass management interfaces ...
PassManager< Function > FunctionPassManager
Convenience typedef for a pass manager over functions.
void abandon(AnalysisKey *ID)
Mark an analysis as abandoned using its ID.
Result & operator=(Result &&RHS)
void preserveSet(AnalysisSetKey *ID)
Mark an analysis set as preserved using its ID.
A special type used to provide an address that identifies a set of related analyses.
Manages a sequence of passes over a particular unit of IR.
bool invalidate(IRUnitT &, const PreservedAnalyses &, typename AnalysisManager< IRUnitT, ExtraArgTs...>::Invalidator &)
Handle invalidation by ignoring it; this pass is immutable.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Runs the function pass across every function in the module.
void preserveSet()
Mark an analysis set as preserved.
iterator find(const KeyT &Val)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
void preserve()
Mark an analysis as preserved.
A no-op pass template which simply forces a specific analysis result to be invalidated.
LLVM_NODISCARD bool empty() const
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...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This templated class represents "all analyses that operate over \<a particular IR unit\>" (e...
void preserve(AnalysisKey *ID)
Given an analysis's ID, mark the analysis as preserved, adding it to the set.
bool preserved()
Returns true if the checker's analysis was not abandoned and either.
bool allAnalysesInSetPreserved() const
Directly test whether a set of analyses is preserved.
Result(const AnalysisManagerT &AM)
StringRef - Represent a constant reference to a string, i.e.
A container for analyses that lazily runs them and caches their results.
PreservedAnalysisChecker getChecker(AnalysisKey *ID) const
Build a checker for this PreservedAnalyses and the specified analysis ID.
PreservedAnalyses run(IRUnitT &Arg, AnalysisManagerT &AM, ExtraArgTs &&...)
Run this pass over some unit of IR.
void invalidate(IRUnitT &IR, const PreservedAnalyses &PA)
Invalidate cached analyses for an IR unit.
bool empty() const
Returns true if the analysis manager has an empty results cache.
A special type used by analysis passes to provide an address that identifies that particular analysis...
Statically lint checks LLVM IR
PassManager< Module > ModulePassManager
Convenience typedef for a pass manager over modules.
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...