|
|
|||
File indexing completed on 2026-05-10 08:43:56
0001 //===- Analysis.h --------------------------------------------*- C++ -*-===// 0002 // 0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 0004 // See https://llvm.org/LICENSE.txt for license information. 0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 0006 // 0007 //===----------------------------------------------------------------------===// 0008 /// \file 0009 /// Pass manager infrastructure for declaring and invalidating analyses. 0010 //===----------------------------------------------------------------------===// 0011 0012 #ifndef LLVM_IR_ANALYSIS_H 0013 #define LLVM_IR_ANALYSIS_H 0014 0015 #include "llvm/ADT/SmallPtrSet.h" 0016 0017 namespace llvm { 0018 0019 class Function; 0020 class Module; 0021 0022 /// A special type used by analysis passes to provide an address that 0023 /// identifies that particular analysis pass type. 0024 /// 0025 /// Analysis passes should have a static data member of this type and derive 0026 /// from the \c AnalysisInfoMixin to get a static ID method used to identify 0027 /// the analysis in the pass management infrastructure. 0028 struct alignas(8) AnalysisKey {}; 0029 0030 /// A special type used to provide an address that identifies a set of related 0031 /// analyses. These sets are primarily used below to mark sets of analyses as 0032 /// preserved. 0033 /// 0034 /// For example, a transformation can indicate that it preserves the CFG of a 0035 /// function by preserving the appropriate AnalysisSetKey. An analysis that 0036 /// depends only on the CFG can then check if that AnalysisSetKey is preserved; 0037 /// if it is, the analysis knows that it itself is preserved. 0038 struct alignas(8) AnalysisSetKey {}; 0039 0040 /// This templated class represents "all analyses that operate over \<a 0041 /// particular IR unit\>" (e.g. a Function or a Module) in instances of 0042 /// PreservedAnalysis. 0043 /// 0044 /// This lets a transformation say e.g. "I preserved all function analyses". 0045 /// 0046 /// Note that you must provide an explicit instantiation declaration and 0047 /// definition for this template in order to get the correct behavior on 0048 /// Windows. Otherwise, the address of SetKey will not be stable. 0049 template <typename IRUnitT> class AllAnalysesOn { 0050 public: 0051 static AnalysisSetKey *ID() { return &SetKey; } 0052 0053 private: 0054 static AnalysisSetKey SetKey; 0055 }; 0056 0057 template <typename IRUnitT> AnalysisSetKey AllAnalysesOn<IRUnitT>::SetKey; 0058 0059 extern template class AllAnalysesOn<Module>; 0060 extern template class AllAnalysesOn<Function>; 0061 0062 /// Represents analyses that only rely on functions' control flow. 0063 /// 0064 /// This can be used with \c PreservedAnalyses to mark the CFG as preserved and 0065 /// to query whether it has been preserved. 0066 /// 0067 /// The CFG of a function is defined as the set of basic blocks and the edges 0068 /// between them. Changing the set of basic blocks in a function is enough to 0069 /// mutate the CFG. Mutating the condition of a branch or argument of an 0070 /// invoked function does not mutate the CFG, but changing the successor labels 0071 /// of those instructions does. 0072 class CFGAnalyses { 0073 public: 0074 static AnalysisSetKey *ID() { return &SetKey; } 0075 0076 private: 0077 static AnalysisSetKey SetKey; 0078 }; 0079 0080 /// A set of analyses that are preserved following a run of a transformation 0081 /// pass. 0082 /// 0083 /// Transformation passes build and return these objects to communicate which 0084 /// analyses are still valid after the transformation. For most passes this is 0085 /// fairly simple: if they don't change anything all analyses are preserved, 0086 /// otherwise only a short list of analyses that have been explicitly updated 0087 /// are preserved. 0088 /// 0089 /// This class also lets transformation passes mark abstract *sets* of analyses 0090 /// as preserved. A transformation that (say) does not alter the CFG can 0091 /// indicate such by marking a particular AnalysisSetKey as preserved, and 0092 /// then analyses can query whether that AnalysisSetKey is preserved. 0093 /// 0094 /// Finally, this class can represent an "abandoned" analysis, which is 0095 /// not preserved even if it would be covered by some abstract set of analyses. 0096 /// 0097 /// Given a `PreservedAnalyses` object, an analysis will typically want to 0098 /// figure out whether it is preserved. In the example below, MyAnalysisType is 0099 /// preserved if it's not abandoned, and (a) it's explicitly marked as 0100 /// preserved, (b), the set AllAnalysesOn<MyIRUnit> is preserved, or (c) both 0101 /// AnalysisSetA and AnalysisSetB are preserved. 0102 /// 0103 /// ``` 0104 /// auto PAC = PA.getChecker<MyAnalysisType>(); 0105 /// if (PAC.preserved() || PAC.preservedSet<AllAnalysesOn<MyIRUnit>>() || 0106 /// (PAC.preservedSet<AnalysisSetA>() && 0107 /// PAC.preservedSet<AnalysisSetB>())) { 0108 /// // The analysis has been successfully preserved ... 0109 /// } 0110 /// ``` 0111 class PreservedAnalyses { 0112 public: 0113 /// Convenience factory function for the empty preserved set. 0114 static PreservedAnalyses none() { return PreservedAnalyses(); } 0115 0116 /// Construct a special preserved set that preserves all passes. 0117 static PreservedAnalyses all() { 0118 PreservedAnalyses PA; 0119 PA.PreservedIDs.insert(&AllAnalysesKey); 0120 return PA; 0121 } 0122 0123 /// Construct a preserved analyses object with a single preserved set. 0124 template <typename AnalysisSetT> static PreservedAnalyses allInSet() { 0125 PreservedAnalyses PA; 0126 PA.preserveSet<AnalysisSetT>(); 0127 return PA; 0128 } 0129 0130 /// Mark an analysis as preserved. 0131 template <typename AnalysisT> void preserve() { preserve(AnalysisT::ID()); } 0132 0133 /// Given an analysis's ID, mark the analysis as preserved, adding it 0134 /// to the set. 0135 void preserve(AnalysisKey *ID) { 0136 // Clear this ID from the explicit not-preserved set if present. 0137 NotPreservedAnalysisIDs.erase(ID); 0138 0139 // If we're not already preserving all analyses (other than those in 0140 // NotPreservedAnalysisIDs). 0141 if (!areAllPreserved()) 0142 PreservedIDs.insert(ID); 0143 } 0144 0145 /// Mark an analysis set as preserved. 0146 template <typename AnalysisSetT> void preserveSet() { 0147 preserveSet(AnalysisSetT::ID()); 0148 } 0149 0150 /// Mark an analysis set as preserved using its ID. 0151 void preserveSet(AnalysisSetKey *ID) { 0152 // If we're not already in the saturated 'all' state, add this set. 0153 if (!areAllPreserved()) 0154 PreservedIDs.insert(ID); 0155 } 0156 0157 /// Mark an analysis as abandoned. 0158 /// 0159 /// An abandoned analysis is not preserved, even if it is nominally covered 0160 /// by some other set or was previously explicitly marked as preserved. 0161 /// 0162 /// Note that you can only abandon a specific analysis, not a *set* of 0163 /// analyses. 0164 template <typename AnalysisT> void abandon() { abandon(AnalysisT::ID()); } 0165 0166 /// Mark an analysis as abandoned using its ID. 0167 /// 0168 /// An abandoned analysis is not preserved, even if it is nominally covered 0169 /// by some other set or was previously explicitly marked as preserved. 0170 /// 0171 /// Note that you can only abandon a specific analysis, not a *set* of 0172 /// analyses. 0173 void abandon(AnalysisKey *ID) { 0174 PreservedIDs.erase(ID); 0175 NotPreservedAnalysisIDs.insert(ID); 0176 } 0177 0178 /// Intersect this set with another in place. 0179 /// 0180 /// This is a mutating operation on this preserved set, removing all 0181 /// preserved passes which are not also preserved in the argument. 0182 void intersect(const PreservedAnalyses &Arg) { 0183 if (Arg.areAllPreserved()) 0184 return; 0185 if (areAllPreserved()) { 0186 *this = Arg; 0187 return; 0188 } 0189 // The intersection requires the *union* of the explicitly not-preserved 0190 // IDs and the *intersection* of the preserved IDs. 0191 for (auto *ID : Arg.NotPreservedAnalysisIDs) { 0192 PreservedIDs.erase(ID); 0193 NotPreservedAnalysisIDs.insert(ID); 0194 } 0195 PreservedIDs.remove_if( 0196 [&](void *ID) { return !Arg.PreservedIDs.contains(ID); }); 0197 } 0198 0199 /// Intersect this set with a temporary other set in place. 0200 /// 0201 /// This is a mutating operation on this preserved set, removing all 0202 /// preserved passes which are not also preserved in the argument. 0203 void intersect(PreservedAnalyses &&Arg) { 0204 if (Arg.areAllPreserved()) 0205 return; 0206 if (areAllPreserved()) { 0207 *this = std::move(Arg); 0208 return; 0209 } 0210 // The intersection requires the *union* of the explicitly not-preserved 0211 // IDs and the *intersection* of the preserved IDs. 0212 for (auto *ID : Arg.NotPreservedAnalysisIDs) { 0213 PreservedIDs.erase(ID); 0214 NotPreservedAnalysisIDs.insert(ID); 0215 } 0216 PreservedIDs.remove_if( 0217 [&](void *ID) { return !Arg.PreservedIDs.contains(ID); }); 0218 } 0219 0220 /// A checker object that makes it easy to query for whether an analysis or 0221 /// some set covering it is preserved. 0222 class PreservedAnalysisChecker { 0223 friend class PreservedAnalyses; 0224 0225 const PreservedAnalyses &PA; 0226 AnalysisKey *const ID; 0227 const bool IsAbandoned; 0228 0229 /// A PreservedAnalysisChecker is tied to a particular Analysis because 0230 /// `preserved()` and `preservedSet()` both return false if the Analysis 0231 /// was abandoned. 0232 PreservedAnalysisChecker(const PreservedAnalyses &PA, AnalysisKey *ID) 0233 : PA(PA), ID(ID), IsAbandoned(PA.NotPreservedAnalysisIDs.count(ID)) {} 0234 0235 public: 0236 /// Returns true if the checker's analysis was not abandoned and either 0237 /// - the analysis is explicitly preserved or 0238 /// - all analyses are preserved. 0239 bool preserved() { 0240 return !IsAbandoned && (PA.PreservedIDs.count(&AllAnalysesKey) || 0241 PA.PreservedIDs.count(ID)); 0242 } 0243 0244 /// Return true if the checker's analysis was not abandoned, i.e. it was not 0245 /// explicitly invalidated. Even if the analysis is not explicitly 0246 /// preserved, if the analysis is known stateless, then it is preserved. 0247 bool preservedWhenStateless() { return !IsAbandoned; } 0248 0249 /// Returns true if the checker's analysis was not abandoned and either 0250 /// - \p AnalysisSetT is explicitly preserved or 0251 /// - all analyses are preserved. 0252 template <typename AnalysisSetT> bool preservedSet() { 0253 AnalysisSetKey *SetID = AnalysisSetT::ID(); 0254 return !IsAbandoned && (PA.PreservedIDs.count(&AllAnalysesKey) || 0255 PA.PreservedIDs.count(SetID)); 0256 } 0257 }; 0258 0259 /// Build a checker for this `PreservedAnalyses` and the specified analysis 0260 /// type. 0261 /// 0262 /// You can use the returned object to query whether an analysis was 0263 /// preserved. See the example in the comment on `PreservedAnalysis`. 0264 template <typename AnalysisT> PreservedAnalysisChecker getChecker() const { 0265 return PreservedAnalysisChecker(*this, AnalysisT::ID()); 0266 } 0267 0268 /// Build a checker for this `PreservedAnalyses` and the specified analysis 0269 /// ID. 0270 /// 0271 /// You can use the returned object to query whether an analysis was 0272 /// preserved. See the example in the comment on `PreservedAnalysis`. 0273 PreservedAnalysisChecker getChecker(AnalysisKey *ID) const { 0274 return PreservedAnalysisChecker(*this, ID); 0275 } 0276 0277 /// Test whether all analyses are preserved (and none are abandoned). 0278 /// 0279 /// This is used primarily to optimize for the common case of a transformation 0280 /// which makes no changes to the IR. 0281 bool areAllPreserved() const { 0282 return NotPreservedAnalysisIDs.empty() && 0283 PreservedIDs.count(&AllAnalysesKey); 0284 } 0285 0286 /// Directly test whether a set of analyses is preserved. 0287 /// 0288 /// This is only true when no analyses have been explicitly abandoned. 0289 template <typename AnalysisSetT> bool allAnalysesInSetPreserved() const { 0290 return allAnalysesInSetPreserved(AnalysisSetT::ID()); 0291 } 0292 0293 /// Directly test whether a set of analyses is preserved. 0294 /// 0295 /// This is only true when no analyses have been explicitly abandoned. 0296 bool allAnalysesInSetPreserved(AnalysisSetKey *SetID) const { 0297 return NotPreservedAnalysisIDs.empty() && 0298 (PreservedIDs.count(&AllAnalysesKey) || PreservedIDs.count(SetID)); 0299 } 0300 0301 private: 0302 /// A special key used to indicate all analyses. 0303 static AnalysisSetKey AllAnalysesKey; 0304 0305 /// The IDs of analyses and analysis sets that are preserved. 0306 SmallPtrSet<void *, 2> PreservedIDs; 0307 0308 /// The IDs of explicitly not-preserved analyses. 0309 /// 0310 /// If an analysis in this set is covered by a set in `PreservedIDs`, we 0311 /// consider it not-preserved. That is, `NotPreservedAnalysisIDs` always 0312 /// "wins" over analysis sets in `PreservedIDs`. 0313 /// 0314 /// Also, a given ID should never occur both here and in `PreservedIDs`. 0315 SmallPtrSet<AnalysisKey *, 2> NotPreservedAnalysisIDs; 0316 }; 0317 } // namespace llvm 0318 0319 #endif
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|