diff --git a/llvm/include/llvm/Analysis/CGSCCPassManager.h b/llvm/include/llvm/Analysis/CGSCCPassManager.h index 0264b36a1d12f..5654ad46d6eab 100644 --- a/llvm/include/llvm/Analysis/CGSCCPassManager.h +++ b/llvm/include/llvm/Analysis/CGSCCPassManager.h @@ -371,9 +371,9 @@ class ModuleToPostOrderCGSCCPassAdaptor template ModuleToPostOrderCGSCCPassAdaptor createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT &&Pass) { - using PassModelT = detail::PassModel; + using PassModelT = + detail::PassModel; // Do not use make_unique, it causes too many template instantiations, // causing terrible compile times. return ModuleToPostOrderCGSCCPassAdaptor( @@ -518,8 +518,7 @@ createCGSCCToFunctionPassAdaptor(FunctionPassT &&Pass, bool EagerlyInvalidate = false, bool NoRerun = false) { using PassModelT = - detail::PassModel; + detail::PassModel; // Do not use make_unique, it causes too many template instantiations, // causing terrible compile times. return CGSCCToFunctionPassAdaptor( @@ -588,9 +587,9 @@ class DevirtSCCRepeatedPass : public PassInfoMixin { template DevirtSCCRepeatedPass createDevirtSCCRepeatedPass(CGSCCPassT &&Pass, int MaxIterations) { - using PassModelT = detail::PassModel; + using PassModelT = + detail::PassModel; // Do not use make_unique, it causes too many template instantiations, // causing terrible compile times. return DevirtSCCRepeatedPass( diff --git a/llvm/include/llvm/CodeGen/MachinePassManager.h b/llvm/include/llvm/CodeGen/MachinePassManager.h index 662b7e8689717..a0ad7d7a95a28 100644 --- a/llvm/include/llvm/CodeGen/MachinePassManager.h +++ b/llvm/include/llvm/CodeGen/MachinePassManager.h @@ -183,9 +183,8 @@ class MachineFunctionPassManager template std::enable_if_t::value> addDoInitialization(PassConceptT *Pass) { - using PassModelT = - detail::PassModel; + using PassModelT = detail::PassModel; auto *P = static_cast(Pass); InitializationFuncs.emplace_back( [=](Module &M, MachineFunctionAnalysisManager &MFAM) { @@ -205,9 +204,8 @@ class MachineFunctionPassManager template std::enable_if_t::value> addDoFinalization(PassConceptT *Pass) { - using PassModelT = - detail::PassModel; + using PassModelT = detail::PassModel; auto *P = static_cast(Pass); FinalizationFuncs.emplace_back( [=](Module &M, MachineFunctionAnalysisManager &MFAM) { @@ -236,9 +234,8 @@ class MachineFunctionPassManager "machine module pass needs to define machine function pass " "api. sorry."); - using PassModelT = - detail::PassModel; + using PassModelT = detail::PassModel; auto *P = static_cast(Pass); MachineModulePasses.emplace( Passes.size() - 1, diff --git a/llvm/include/llvm/IR/Analysis.h b/llvm/include/llvm/IR/Analysis.h new file mode 100644 index 0000000000000..a7005285dd9bf --- /dev/null +++ b/llvm/include/llvm/IR/Analysis.h @@ -0,0 +1,319 @@ +//===- Analysis.h --------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// Pass manager infrastructure for declaring and invalidating analyses. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_ANALYSIS_H +#define LLVM_IR_ANALYSIS_H + +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" + +namespace llvm { +/// A special type used by analysis passes to provide an address that +/// identifies that particular analysis pass type. +/// +/// Analysis passes should have a static data member of this type and derive +/// from the \c AnalysisInfoMixin to get a static ID method used to identify +/// the analysis in the pass management infrastructure. +struct alignas(8) AnalysisKey {}; + +/// A special type used to provide an address that identifies a set of related +/// analyses. These sets are primarily used below to mark sets of analyses as +/// preserved. +/// +/// For example, a transformation can indicate that it preserves the CFG of a +/// function by preserving the appropriate AnalysisSetKey. An analysis that +/// depends only on the CFG can then check if that AnalysisSetKey is preserved; +/// if it is, the analysis knows that it itself is preserved. +struct alignas(8) AnalysisSetKey {}; + +/// This templated class represents "all analyses that operate over \" (e.g. a Function or a Module) in instances of +/// PreservedAnalysis. +/// +/// This lets a transformation say e.g. "I preserved all function analyses". +/// +/// Note that you must provide an explicit instantiation declaration and +/// definition for this template in order to get the correct behavior on +/// Windows. Otherwise, the address of SetKey will not be stable. +template class AllAnalysesOn { +public: + static AnalysisSetKey *ID() { return &SetKey; } + +private: + static AnalysisSetKey SetKey; +}; + +template AnalysisSetKey AllAnalysesOn::SetKey; + +extern template class AllAnalysesOn; +extern template class AllAnalysesOn; + +/// Represents analyses that only rely on functions' control flow. +/// +/// This can be used with \c PreservedAnalyses to mark the CFG as preserved and +/// to query whether it has been preserved. +/// +/// The CFG of a function is defined as the set of basic blocks and the edges +/// between them. Changing the set of basic blocks in a function is enough to +/// mutate the CFG. Mutating the condition of a branch or argument of an +/// invoked function does not mutate the CFG, but changing the successor labels +/// of those instructions does. +class CFGAnalyses { +public: + static AnalysisSetKey *ID() { return &SetKey; } + +private: + static AnalysisSetKey SetKey; +}; + +/// A set of analyses that are preserved following a run of a transformation +/// pass. +/// +/// Transformation passes build and return these objects to communicate which +/// analyses are still valid after the transformation. For most passes this is +/// fairly simple: if they don't change anything all analyses are preserved, +/// otherwise only a short list of analyses that have been explicitly updated +/// are preserved. +/// +/// This class also lets transformation passes mark abstract *sets* of analyses +/// as preserved. A transformation that (say) does not alter the CFG can +/// indicate such by marking a particular AnalysisSetKey as preserved, and +/// then analyses can query whether that AnalysisSetKey is preserved. +/// +/// Finally, this class can represent an "abandoned" analysis, which is +/// not preserved even if it would be covered by some abstract set of analyses. +/// +/// Given a `PreservedAnalyses` object, an analysis will typically want to +/// figure out whether it is preserved. In the example below, MyAnalysisType is +/// preserved if it's not abandoned, and (a) it's explicitly marked as +/// preserved, (b), the set AllAnalysesOn is preserved, or (c) both +/// AnalysisSetA and AnalysisSetB are preserved. +/// +/// ``` +/// auto PAC = PA.getChecker(); +/// if (PAC.preserved() || PAC.preservedSet>() || +/// (PAC.preservedSet() && +/// PAC.preservedSet())) { +/// // The analysis has been successfully preserved ... +/// } +/// ``` +class PreservedAnalyses { +public: + /// Convenience factory function for the empty preserved set. + static PreservedAnalyses none() { return PreservedAnalyses(); } + + /// Construct a special preserved set that preserves all passes. + static PreservedAnalyses all() { + PreservedAnalyses PA; + PA.PreservedIDs.insert(&AllAnalysesKey); + return PA; + } + + /// Construct a preserved analyses object with a single preserved set. + template static PreservedAnalyses allInSet() { + PreservedAnalyses PA; + PA.preserveSet(); + return PA; + } + + /// Mark an analysis as preserved. + template void preserve() { preserve(AnalysisT::ID()); } + + /// Given an analysis's ID, mark the analysis as preserved, adding it + /// to the set. + void preserve(AnalysisKey *ID) { + // Clear this ID from the explicit not-preserved set if present. + NotPreservedAnalysisIDs.erase(ID); + + // If we're not already preserving all analyses (other than those in + // NotPreservedAnalysisIDs). + if (!areAllPreserved()) + PreservedIDs.insert(ID); + } + + /// Mark an analysis set as preserved. + template void preserveSet() { + preserveSet(AnalysisSetT::ID()); + } + + /// Mark an analysis set as preserved using its ID. + void preserveSet(AnalysisSetKey *ID) { + // If we're not already in the saturated 'all' state, add this set. + if (!areAllPreserved()) + PreservedIDs.insert(ID); + } + + /// Mark an analysis as abandoned. + /// + /// An abandoned analysis is not preserved, even if it is nominally covered + /// by some other set or was previously explicitly marked as preserved. + /// + /// Note that you can only abandon a specific analysis, not a *set* of + /// analyses. + template void abandon() { abandon(AnalysisT::ID()); } + + /// Mark an analysis as abandoned using its ID. + /// + /// An abandoned analysis is not preserved, even if it is nominally covered + /// by some other set or was previously explicitly marked as preserved. + /// + /// Note that you can only abandon a specific analysis, not a *set* of + /// analyses. + void abandon(AnalysisKey *ID) { + PreservedIDs.erase(ID); + NotPreservedAnalysisIDs.insert(ID); + } + + /// Intersect this set with another in place. + /// + /// This is a mutating operation on this preserved set, removing all + /// preserved passes which are not also preserved in the argument. + void intersect(const PreservedAnalyses &Arg) { + if (Arg.areAllPreserved()) + return; + if (areAllPreserved()) { + *this = Arg; + return; + } + // The intersection requires the *union* of the explicitly not-preserved + // IDs and the *intersection* of the preserved IDs. + for (auto *ID : Arg.NotPreservedAnalysisIDs) { + PreservedIDs.erase(ID); + NotPreservedAnalysisIDs.insert(ID); + } + for (auto *ID : PreservedIDs) + if (!Arg.PreservedIDs.count(ID)) + PreservedIDs.erase(ID); + } + + /// Intersect this set with a temporary other set in place. + /// + /// This is a mutating operation on this preserved set, removing all + /// preserved passes which are not also preserved in the argument. + void intersect(PreservedAnalyses &&Arg) { + if (Arg.areAllPreserved()) + return; + if (areAllPreserved()) { + *this = std::move(Arg); + return; + } + // The intersection requires the *union* of the explicitly not-preserved + // IDs and the *intersection* of the preserved IDs. + for (auto *ID : Arg.NotPreservedAnalysisIDs) { + PreservedIDs.erase(ID); + NotPreservedAnalysisIDs.insert(ID); + } + for (auto *ID : PreservedIDs) + if (!Arg.PreservedIDs.count(ID)) + PreservedIDs.erase(ID); + } + + /// A checker object that makes it easy to query for whether an analysis or + /// some set covering it is preserved. + class PreservedAnalysisChecker { + friend class PreservedAnalyses; + + const PreservedAnalyses &PA; + AnalysisKey *const ID; + const bool IsAbandoned; + + /// A PreservedAnalysisChecker is tied to a particular Analysis because + /// `preserved()` and `preservedSet()` both return false if the Analysis + /// was abandoned. + PreservedAnalysisChecker(const PreservedAnalyses &PA, AnalysisKey *ID) + : PA(PA), ID(ID), IsAbandoned(PA.NotPreservedAnalysisIDs.count(ID)) {} + + public: + /// Returns true if the checker's analysis was not abandoned and either + /// - the analysis is explicitly preserved or + /// - all analyses are preserved. + bool preserved() { + return !IsAbandoned && (PA.PreservedIDs.count(&AllAnalysesKey) || + PA.PreservedIDs.count(ID)); + } + + /// Return true if the checker's analysis was not abandoned, i.e. it was not + /// explicitly invalidated. Even if the analysis is not explicitly + /// preserved, if the analysis is known stateless, then it is preserved. + bool preservedWhenStateless() { return !IsAbandoned; } + + /// Returns true if the checker's analysis was not abandoned and either + /// - \p AnalysisSetT is explicitly preserved or + /// - all analyses are preserved. + template bool preservedSet() { + AnalysisSetKey *SetID = AnalysisSetT::ID(); + return !IsAbandoned && (PA.PreservedIDs.count(&AllAnalysesKey) || + PA.PreservedIDs.count(SetID)); + } + }; + + /// Build a checker for this `PreservedAnalyses` and the specified analysis + /// type. + /// + /// You can use the returned object to query whether an analysis was + /// preserved. See the example in the comment on `PreservedAnalysis`. + template PreservedAnalysisChecker getChecker() const { + return PreservedAnalysisChecker(*this, AnalysisT::ID()); + } + + /// Build a checker for this `PreservedAnalyses` and the specified analysis + /// ID. + /// + /// You can use the returned object to query whether an analysis was + /// preserved. See the example in the comment on `PreservedAnalysis`. + PreservedAnalysisChecker getChecker(AnalysisKey *ID) const { + return PreservedAnalysisChecker(*this, ID); + } + + /// Test whether all analyses are preserved (and none are abandoned). + /// + /// This is used primarily to optimize for the common case of a transformation + /// which makes no changes to the IR. + bool areAllPreserved() const { + return NotPreservedAnalysisIDs.empty() && + PreservedIDs.count(&AllAnalysesKey); + } + + /// Directly test whether a set of analyses is preserved. + /// + /// This is only true when no analyses have been explicitly abandoned. + template bool allAnalysesInSetPreserved() const { + return allAnalysesInSetPreserved(AnalysisSetT::ID()); + } + + /// Directly test whether a set of analyses is preserved. + /// + /// This is only true when no analyses have been explicitly abandoned. + bool allAnalysesInSetPreserved(AnalysisSetKey *SetID) const { + return NotPreservedAnalysisIDs.empty() && + (PreservedIDs.count(&AllAnalysesKey) || PreservedIDs.count(SetID)); + } + +private: + /// A special key used to indicate all analyses. + static AnalysisSetKey AllAnalysesKey; + + /// The IDs of analyses and analysis sets that are preserved. + SmallPtrSet PreservedIDs; + + /// The IDs of explicitly not-preserved analyses. + /// + /// If an analysis in this set is covered by a set in `PreservedIDs`, we + /// consider it not-preserved. That is, `NotPreservedAnalysisIDs` always + /// "wins" over analysis sets in `PreservedIDs`. + /// + /// Also, a given ID should never occur both here and in `PreservedIDs`. + SmallPtrSet NotPreservedAnalysisIDs; +}; +} // namespace llvm + +#endif \ No newline at end of file diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h index df548fbe9e458..c03d49c3b7b97 100644 --- a/llvm/include/llvm/IR/PassManager.h +++ b/llvm/include/llvm/IR/PassManager.h @@ -42,6 +42,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/TinyPtrVector.h" +#include "llvm/IR/Analysis.h" #include "llvm/IR/Function.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassInstrumentation.h" @@ -80,307 +81,6 @@ template <> inline void doConvertDebugInfoToOld(Module &IR) { IR.convertFromNewDbgValues(); } -/// A special type used by analysis passes to provide an address that -/// identifies that particular analysis pass type. -/// -/// Analysis passes should have a static data member of this type and derive -/// from the \c AnalysisInfoMixin to get a static ID method used to identify -/// the analysis in the pass management infrastructure. -struct alignas(8) AnalysisKey {}; - -/// A special type used to provide an address that identifies a set of related -/// analyses. These sets are primarily used below to mark sets of analyses as -/// preserved. -/// -/// For example, a transformation can indicate that it preserves the CFG of a -/// function by preserving the appropriate AnalysisSetKey. An analysis that -/// depends only on the CFG can then check if that AnalysisSetKey is preserved; -/// if it is, the analysis knows that it itself is preserved. -struct alignas(8) AnalysisSetKey {}; - -/// This templated class represents "all analyses that operate over \" (e.g. a Function or a Module) in instances of -/// PreservedAnalysis. -/// -/// This lets a transformation say e.g. "I preserved all function analyses". -/// -/// Note that you must provide an explicit instantiation declaration and -/// definition for this template in order to get the correct behavior on -/// Windows. Otherwise, the address of SetKey will not be stable. -template class AllAnalysesOn { -public: - static AnalysisSetKey *ID() { return &SetKey; } - -private: - static AnalysisSetKey SetKey; -}; - -template AnalysisSetKey AllAnalysesOn::SetKey; - -extern template class AllAnalysesOn; -extern template class AllAnalysesOn; - -/// Represents analyses that only rely on functions' control flow. -/// -/// This can be used with \c PreservedAnalyses to mark the CFG as preserved and -/// to query whether it has been preserved. -/// -/// The CFG of a function is defined as the set of basic blocks and the edges -/// between them. Changing the set of basic blocks in a function is enough to -/// mutate the CFG. Mutating the condition of a branch or argument of an -/// invoked function does not mutate the CFG, but changing the successor labels -/// of those instructions does. -class CFGAnalyses { -public: - static AnalysisSetKey *ID() { return &SetKey; } - -private: - static AnalysisSetKey SetKey; -}; - -/// A set of analyses that are preserved following a run of a transformation -/// pass. -/// -/// Transformation passes build and return these objects to communicate which -/// analyses are still valid after the transformation. For most passes this is -/// fairly simple: if they don't change anything all analyses are preserved, -/// otherwise only a short list of analyses that have been explicitly updated -/// are preserved. -/// -/// This class also lets transformation passes mark abstract *sets* of analyses -/// as preserved. A transformation that (say) does not alter the CFG can -/// indicate such by marking a particular AnalysisSetKey as preserved, and -/// then analyses can query whether that AnalysisSetKey is preserved. -/// -/// Finally, this class can represent an "abandoned" analysis, which is -/// not preserved even if it would be covered by some abstract set of analyses. -/// -/// Given a `PreservedAnalyses` object, an analysis will typically want to -/// figure out whether it is preserved. In the example below, MyAnalysisType is -/// preserved if it's not abandoned, and (a) it's explicitly marked as -/// preserved, (b), the set AllAnalysesOn is preserved, or (c) both -/// AnalysisSetA and AnalysisSetB are preserved. -/// -/// ``` -/// auto PAC = PA.getChecker(); -/// if (PAC.preserved() || PAC.preservedSet>() || -/// (PAC.preservedSet() && -/// PAC.preservedSet())) { -/// // The analysis has been successfully preserved ... -/// } -/// ``` -class PreservedAnalyses { -public: - /// Convenience factory function for the empty preserved set. - static PreservedAnalyses none() { return PreservedAnalyses(); } - - /// Construct a special preserved set that preserves all passes. - static PreservedAnalyses all() { - PreservedAnalyses PA; - PA.PreservedIDs.insert(&AllAnalysesKey); - return PA; - } - - /// Construct a preserved analyses object with a single preserved set. - template - static PreservedAnalyses allInSet() { - PreservedAnalyses PA; - PA.preserveSet(); - return PA; - } - - /// Mark an analysis as preserved. - template void preserve() { preserve(AnalysisT::ID()); } - - /// Given an analysis's ID, mark the analysis as preserved, adding it - /// to the set. - void preserve(AnalysisKey *ID) { - // Clear this ID from the explicit not-preserved set if present. - NotPreservedAnalysisIDs.erase(ID); - - // If we're not already preserving all analyses (other than those in - // NotPreservedAnalysisIDs). - if (!areAllPreserved()) - PreservedIDs.insert(ID); - } - - /// Mark an analysis set as preserved. - template void preserveSet() { - preserveSet(AnalysisSetT::ID()); - } - - /// Mark an analysis set as preserved using its ID. - void preserveSet(AnalysisSetKey *ID) { - // If we're not already in the saturated 'all' state, add this set. - if (!areAllPreserved()) - PreservedIDs.insert(ID); - } - - /// Mark an analysis as abandoned. - /// - /// An abandoned analysis is not preserved, even if it is nominally covered - /// by some other set or was previously explicitly marked as preserved. - /// - /// Note that you can only abandon a specific analysis, not a *set* of - /// analyses. - template void abandon() { abandon(AnalysisT::ID()); } - - /// Mark an analysis as abandoned using its ID. - /// - /// An abandoned analysis is not preserved, even if it is nominally covered - /// by some other set or was previously explicitly marked as preserved. - /// - /// Note that you can only abandon a specific analysis, not a *set* of - /// analyses. - void abandon(AnalysisKey *ID) { - PreservedIDs.erase(ID); - NotPreservedAnalysisIDs.insert(ID); - } - - /// Intersect this set with another in place. - /// - /// This is a mutating operation on this preserved set, removing all - /// preserved passes which are not also preserved in the argument. - void intersect(const PreservedAnalyses &Arg) { - if (Arg.areAllPreserved()) - return; - if (areAllPreserved()) { - *this = Arg; - return; - } - // The intersection requires the *union* of the explicitly not-preserved - // IDs and the *intersection* of the preserved IDs. - for (auto *ID : Arg.NotPreservedAnalysisIDs) { - PreservedIDs.erase(ID); - NotPreservedAnalysisIDs.insert(ID); - } - for (auto *ID : PreservedIDs) - if (!Arg.PreservedIDs.count(ID)) - PreservedIDs.erase(ID); - } - - /// Intersect this set with a temporary other set in place. - /// - /// This is a mutating operation on this preserved set, removing all - /// preserved passes which are not also preserved in the argument. - void intersect(PreservedAnalyses &&Arg) { - if (Arg.areAllPreserved()) - return; - if (areAllPreserved()) { - *this = std::move(Arg); - return; - } - // The intersection requires the *union* of the explicitly not-preserved - // IDs and the *intersection* of the preserved IDs. - for (auto *ID : Arg.NotPreservedAnalysisIDs) { - PreservedIDs.erase(ID); - NotPreservedAnalysisIDs.insert(ID); - } - for (auto *ID : PreservedIDs) - if (!Arg.PreservedIDs.count(ID)) - PreservedIDs.erase(ID); - } - - /// A checker object that makes it easy to query for whether an analysis or - /// some set covering it is preserved. - class PreservedAnalysisChecker { - friend class PreservedAnalyses; - - const PreservedAnalyses &PA; - AnalysisKey *const ID; - const bool IsAbandoned; - - /// A PreservedAnalysisChecker is tied to a particular Analysis because - /// `preserved()` and `preservedSet()` both return false if the Analysis - /// was abandoned. - PreservedAnalysisChecker(const PreservedAnalyses &PA, AnalysisKey *ID) - : PA(PA), ID(ID), IsAbandoned(PA.NotPreservedAnalysisIDs.count(ID)) {} - - public: - /// Returns true if the checker's analysis was not abandoned and either - /// - the analysis is explicitly preserved or - /// - all analyses are preserved. - bool preserved() { - return !IsAbandoned && (PA.PreservedIDs.count(&AllAnalysesKey) || - PA.PreservedIDs.count(ID)); - } - - /// Return true if the checker's analysis was not abandoned, i.e. it was not - /// explicitly invalidated. Even if the analysis is not explicitly - /// preserved, if the analysis is known stateless, then it is preserved. - bool preservedWhenStateless() { - return !IsAbandoned; - } - - /// Returns true if the checker's analysis was not abandoned and either - /// - \p AnalysisSetT is explicitly preserved or - /// - all analyses are preserved. - template bool preservedSet() { - AnalysisSetKey *SetID = AnalysisSetT::ID(); - return !IsAbandoned && (PA.PreservedIDs.count(&AllAnalysesKey) || - PA.PreservedIDs.count(SetID)); - } - }; - - /// Build a checker for this `PreservedAnalyses` and the specified analysis - /// type. - /// - /// You can use the returned object to query whether an analysis was - /// preserved. See the example in the comment on `PreservedAnalysis`. - template PreservedAnalysisChecker getChecker() const { - return PreservedAnalysisChecker(*this, AnalysisT::ID()); - } - - /// Build a checker for this `PreservedAnalyses` and the specified analysis - /// ID. - /// - /// You can use the returned object to query whether an analysis was - /// preserved. See the example in the comment on `PreservedAnalysis`. - PreservedAnalysisChecker getChecker(AnalysisKey *ID) const { - return PreservedAnalysisChecker(*this, ID); - } - - /// Test whether all analyses are preserved (and none are abandoned). - /// - /// This is used primarily to optimize for the common case of a transformation - /// which makes no changes to the IR. - bool areAllPreserved() const { - return NotPreservedAnalysisIDs.empty() && - PreservedIDs.count(&AllAnalysesKey); - } - - /// Directly test whether a set of analyses is preserved. - /// - /// This is only true when no analyses have been explicitly abandoned. - template bool allAnalysesInSetPreserved() const { - return allAnalysesInSetPreserved(AnalysisSetT::ID()); - } - - /// Directly test whether a set of analyses is preserved. - /// - /// This is only true when no analyses have been explicitly abandoned. - bool allAnalysesInSetPreserved(AnalysisSetKey *SetID) const { - return NotPreservedAnalysisIDs.empty() && - (PreservedIDs.count(&AllAnalysesKey) || PreservedIDs.count(SetID)); - } - -private: - /// A special key used to indicate all analyses. - static AnalysisSetKey AllAnalysesKey; - - /// The IDs of analyses and analysis sets that are preserved. - SmallPtrSet PreservedIDs; - - /// The IDs of explicitly not-preserved analyses. - /// - /// If an analysis in this set is covered by a set in `PreservedIDs`, we - /// consider it not-preserved. That is, `NotPreservedAnalysisIDs` always - /// "wins" over analysis sets in `PreservedIDs`. - /// - /// Also, a given ID should never occur both here and in `PreservedIDs`. - SmallPtrSet NotPreservedAnalysisIDs; -}; - // Forward declare the analysis manager template. template class AnalysisManager; @@ -572,8 +272,7 @@ class PassManager : public PassInfoMixin< std::enable_if_t::value> addPass(PassT &&Pass) { using PassModelT = - detail::PassModel; + detail::PassModel; // Do not use make_unique or emplace_back, they cause too many template // instantiations, causing terrible compile times. Passes.push_back(std::unique_ptr( @@ -652,11 +351,9 @@ template class AnalysisManager { private: // Now that we've defined our invalidator, we can define the concept types. - using ResultConceptT = - detail::AnalysisResultConcept; + using ResultConceptT = detail::AnalysisResultConcept; using PassConceptT = - detail::AnalysisPassConcept; + detail::AnalysisPassConcept; /// List of analysis pass IDs and associated concept pointers. /// @@ -708,7 +405,7 @@ template class AnalysisManager { bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA) { using ResultModelT = detail::AnalysisResultModel; + Invalidator>; return invalidateImpl(PassT::ID(), IR, PA); } @@ -808,7 +505,7 @@ template class AnalysisManager { using ResultModelT = detail::AnalysisResultModel; + Invalidator>; return static_cast(ResultConcept).Result; } @@ -829,7 +526,7 @@ template class AnalysisManager { using ResultModelT = detail::AnalysisResultModel; + Invalidator>; return &static_cast(ResultConcept)->Result; } @@ -865,8 +562,7 @@ template class AnalysisManager { bool registerPass(PassBuilderT &&PassBuilder) { using PassT = decltype(PassBuilder()); using PassModelT = - detail::AnalysisPassModel; + detail::AnalysisPassModel; auto &PassPtr = AnalysisPasses[PassT::ID()]; if (PassPtr) @@ -1247,8 +943,7 @@ ModuleToFunctionPassAdaptor createModuleToFunctionPassAdaptor(FunctionPassT &&Pass, bool EagerlyInvalidate = false) { using PassModelT = - detail::PassModel; + detail::PassModel; // Do not use make_unique, it causes too many template instantiations, // causing terrible compile times. return ModuleToFunctionPassAdaptor( diff --git a/llvm/include/llvm/IR/PassManagerInternal.h b/llvm/include/llvm/IR/PassManagerInternal.h index bcfdcb8206c45..4ada6ee5dd683 100644 --- a/llvm/include/llvm/IR/PassManagerInternal.h +++ b/llvm/include/llvm/IR/PassManagerInternal.h @@ -19,6 +19,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/IR/Analysis.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -65,8 +66,8 @@ struct PassConcept { /// Can be instantiated for any object which provides a \c run method accepting /// an \c IRUnitT& and an \c AnalysisManager&. It requires the pass to /// be a copyable object. -template +template struct PassModel : PassConcept { explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} // We have to explicitly define all the special member functions because MSVC @@ -84,8 +85,8 @@ struct PassModel : PassConcept { return *this; } - PreservedAnalysesT run(IRUnitT &IR, AnalysisManagerT &AM, - ExtraArgTs... ExtraArgs) override { + PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, + ExtraArgTs... ExtraArgs) override { return Pass.run(IR, AM, ExtraArgs...); } @@ -120,7 +121,7 @@ struct PassModel : PassConcept { /// /// This concept is parameterized over the IR unit that this result pertains /// to. -template +template struct AnalysisResultConcept { virtual ~AnalysisResultConcept() = default; @@ -139,7 +140,7 @@ struct AnalysisResultConcept { /// them. See the documentation in the \c AnalysisManager for more details. /// /// \returns true if the result is indeed invalid (the default). - virtual bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA, + virtual bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA, InvalidatorT &Inv) = 0; }; @@ -186,7 +187,7 @@ template class ResultHasInvalidateMethod { /// an invalidation handler. It is only selected when the invalidation handler /// is not part of the ResultT's interface. template ::Value> struct AnalysisResultModel; @@ -194,10 +195,9 @@ struct AnalysisResultModel; /// Specialization of \c AnalysisResultModel which provides the default /// invalidate functionality. template -struct AnalysisResultModel - : AnalysisResultConcept { + typename InvalidatorT> +struct AnalysisResultModel + : AnalysisResultConcept { explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. @@ -220,7 +220,7 @@ struct AnalysisResultModel(); return !PAC.preserved() && @@ -233,10 +233,9 @@ struct AnalysisResultModel -struct AnalysisResultModel - : AnalysisResultConcept { + typename InvalidatorT> +struct AnalysisResultModel + : AnalysisResultConcept { explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. @@ -255,7 +254,7 @@ struct AnalysisResultModel +template struct AnalysisPassConcept { virtual ~AnalysisPassConcept() = default; /// Method to run this analysis over a unit of IR. /// \returns A unique_ptr to the analysis result object to be queried by /// users. - virtual std::unique_ptr< - AnalysisResultConcept> + virtual std::unique_ptr> run(IRUnitT &IR, AnalysisManager &AM, ExtraArgTs... ExtraArgs) = 0; @@ -289,10 +286,10 @@ struct AnalysisPassConcept { /// Can wrap any type which implements a suitable \c run method. The method /// must accept an \c IRUnitT& and an \c AnalysisManager& as arguments /// and produce an object which can be wrapped in a \c AnalysisResultModel. -template -struct AnalysisPassModel : AnalysisPassConcept { +template +struct AnalysisPassModel + : AnalysisPassConcept { explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. @@ -311,14 +308,12 @@ struct AnalysisPassModel : AnalysisPassConcept; + AnalysisResultModel; /// The model delegates to the \c PassT::run method. /// /// The return is wrapped in an \c AnalysisResultModel. - std::unique_ptr< - AnalysisResultConcept> + std::unique_ptr> run(IRUnitT &IR, AnalysisManager &AM, ExtraArgTs... ExtraArgs) override { return std::make_unique( diff --git a/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h b/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h index c8c4d5e9a5392..6aab1f98e6781 100644 --- a/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h +++ b/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h @@ -106,7 +106,7 @@ class PassManager::value> addPass(PassT &&Pass) { using LoopPassModelT = - detail::PassModel; IsLoopNestPass.push_back(false); // Do not use make_unique or emplace_back, they cause too many template @@ -120,9 +120,8 @@ class PassManager::value> addPass(PassT &&Pass) { using LoopNestPassModelT = - detail::PassModel; + detail::PassModel; IsLoopNestPass.push_back(true); // Do not use make_unique or emplace_back, they cause too many template // instantiations, causing terrible compile times. @@ -138,9 +137,8 @@ class PassManager::value> addPass(RepeatedPass &&Pass) { using RepeatedLoopPassModelT = - detail::PassModel, PreservedAnalyses, - LoopAnalysisManager, LoopStandardAnalysisResults &, - LPMUpdater &>; + detail::PassModel, LoopAnalysisManager, + LoopStandardAnalysisResults &, LPMUpdater &>; IsLoopNestPass.push_back(false); // Do not use make_unique or emplace_back, they cause too many template // instantiations, causing terrible compile times. @@ -153,9 +151,8 @@ class PassManager::value> addPass(RepeatedPass &&Pass) { using RepeatedLoopNestPassModelT = - detail::PassModel, PreservedAnalyses, - LoopAnalysisManager, LoopStandardAnalysisResults &, - LPMUpdater &>; + detail::PassModel, LoopAnalysisManager, + LoopStandardAnalysisResults &, LPMUpdater &>; IsLoopNestPass.push_back(true); // Do not use make_unique or emplace_back, they cause too many template // instantiations, causing terrible compile times. @@ -482,7 +479,7 @@ createFunctionToLoopPassAdaptor(LoopPassT &&Pass, bool UseMemorySSA = false, bool UseBlockFrequencyInfo = false, bool UseBranchProbabilityInfo = false) { using PassModelT = - detail::PassModel; // Do not use make_unique, it causes too many template instantiations, // causing terrible compile times. @@ -503,9 +500,8 @@ createFunctionToLoopPassAdaptor(LoopNestPassT &&Pass, bool UseMemorySSA = false, LoopPassManager LPM; LPM.addPass(std::forward(Pass)); using PassModelT = - detail::PassModel; + detail::PassModel; // Do not use make_unique, it causes too many template instantiations, // causing terrible compile times. return FunctionToLoopPassAdaptor( @@ -524,9 +520,8 @@ createFunctionToLoopPassAdaptor( // Check if LPM contains any loop pass and if it does not, returns an adaptor // in loop-nest mode. using PassModelT = - detail::PassModel; + detail::PassModel; bool LoopNestMode = (LPM.getNumLoopPasses() == 0); // Do not use make_unique, it causes too many template instantiations, // causing terrible compile times.