1 //===- Analysis.h --------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// Pass manager infrastructure for declaring and invalidating analyses. 10 //===----------------------------------------------------------------------===// 11 12 #ifndef LLVM_IR_ANALYSIS_H 13 #define LLVM_IR_ANALYSIS_H 14 15 #include "llvm/ADT/SmallPtrSet.h" 16 #include "llvm/IR/Function.h" 17 #include "llvm/IR/Module.h" 18 19 namespace llvm { 20 /// A special type used by analysis passes to provide an address that 21 /// identifies that particular analysis pass type. 22 /// 23 /// Analysis passes should have a static data member of this type and derive 24 /// from the \c AnalysisInfoMixin to get a static ID method used to identify 25 /// the analysis in the pass management infrastructure. 26 struct alignas(8) AnalysisKey {}; 27 28 /// A special type used to provide an address that identifies a set of related 29 /// analyses. These sets are primarily used below to mark sets of analyses as 30 /// preserved. 31 /// 32 /// For example, a transformation can indicate that it preserves the CFG of a 33 /// function by preserving the appropriate AnalysisSetKey. An analysis that 34 /// depends only on the CFG can then check if that AnalysisSetKey is preserved; 35 /// if it is, the analysis knows that it itself is preserved. 36 struct alignas(8) AnalysisSetKey {}; 37 38 /// This templated class represents "all analyses that operate over \<a 39 /// particular IR unit\>" (e.g. a Function or a Module) in instances of 40 /// PreservedAnalysis. 41 /// 42 /// This lets a transformation say e.g. "I preserved all function analyses". 43 /// 44 /// Note that you must provide an explicit instantiation declaration and 45 /// definition for this template in order to get the correct behavior on 46 /// Windows. Otherwise, the address of SetKey will not be stable. 47 template <typename IRUnitT> class AllAnalysesOn { 48 public: ID()49 static AnalysisSetKey *ID() { return &SetKey; } 50 51 private: 52 static AnalysisSetKey SetKey; 53 }; 54 55 template <typename IRUnitT> AnalysisSetKey AllAnalysesOn<IRUnitT>::SetKey; 56 57 extern template class AllAnalysesOn<Module>; 58 extern template class AllAnalysesOn<Function>; 59 60 /// Represents analyses that only rely on functions' control flow. 61 /// 62 /// This can be used with \c PreservedAnalyses to mark the CFG as preserved and 63 /// to query whether it has been preserved. 64 /// 65 /// The CFG of a function is defined as the set of basic blocks and the edges 66 /// between them. Changing the set of basic blocks in a function is enough to 67 /// mutate the CFG. Mutating the condition of a branch or argument of an 68 /// invoked function does not mutate the CFG, but changing the successor labels 69 /// of those instructions does. 70 class CFGAnalyses { 71 public: ID()72 static AnalysisSetKey *ID() { return &SetKey; } 73 74 private: 75 static AnalysisSetKey SetKey; 76 }; 77 78 /// A set of analyses that are preserved following a run of a transformation 79 /// pass. 80 /// 81 /// Transformation passes build and return these objects to communicate which 82 /// analyses are still valid after the transformation. For most passes this is 83 /// fairly simple: if they don't change anything all analyses are preserved, 84 /// otherwise only a short list of analyses that have been explicitly updated 85 /// are preserved. 86 /// 87 /// This class also lets transformation passes mark abstract *sets* of analyses 88 /// as preserved. A transformation that (say) does not alter the CFG can 89 /// indicate such by marking a particular AnalysisSetKey as preserved, and 90 /// then analyses can query whether that AnalysisSetKey is preserved. 91 /// 92 /// Finally, this class can represent an "abandoned" analysis, which is 93 /// not preserved even if it would be covered by some abstract set of analyses. 94 /// 95 /// Given a `PreservedAnalyses` object, an analysis will typically want to 96 /// figure out whether it is preserved. In the example below, MyAnalysisType is 97 /// preserved if it's not abandoned, and (a) it's explicitly marked as 98 /// preserved, (b), the set AllAnalysesOn<MyIRUnit> is preserved, or (c) both 99 /// AnalysisSetA and AnalysisSetB are preserved. 100 /// 101 /// ``` 102 /// auto PAC = PA.getChecker<MyAnalysisType>(); 103 /// if (PAC.preserved() || PAC.preservedSet<AllAnalysesOn<MyIRUnit>>() || 104 /// (PAC.preservedSet<AnalysisSetA>() && 105 /// PAC.preservedSet<AnalysisSetB>())) { 106 /// // The analysis has been successfully preserved ... 107 /// } 108 /// ``` 109 class PreservedAnalyses { 110 public: 111 /// Convenience factory function for the empty preserved set. none()112 static PreservedAnalyses none() { return PreservedAnalyses(); } 113 114 /// Construct a special preserved set that preserves all passes. all()115 static PreservedAnalyses all() { 116 PreservedAnalyses PA; 117 PA.PreservedIDs.insert(&AllAnalysesKey); 118 return PA; 119 } 120 121 /// Construct a preserved analyses object with a single preserved set. allInSet()122 template <typename AnalysisSetT> static PreservedAnalyses allInSet() { 123 PreservedAnalyses PA; 124 PA.preserveSet<AnalysisSetT>(); 125 return PA; 126 } 127 128 /// Mark an analysis as preserved. preserve()129 template <typename AnalysisT> void preserve() { preserve(AnalysisT::ID()); } 130 131 /// Given an analysis's ID, mark the analysis as preserved, adding it 132 /// to the set. preserve(AnalysisKey * ID)133 void preserve(AnalysisKey *ID) { 134 // Clear this ID from the explicit not-preserved set if present. 135 NotPreservedAnalysisIDs.erase(ID); 136 137 // If we're not already preserving all analyses (other than those in 138 // NotPreservedAnalysisIDs). 139 if (!areAllPreserved()) 140 PreservedIDs.insert(ID); 141 } 142 143 /// Mark an analysis set as preserved. preserveSet()144 template <typename AnalysisSetT> void preserveSet() { 145 preserveSet(AnalysisSetT::ID()); 146 } 147 148 /// Mark an analysis set as preserved using its ID. preserveSet(AnalysisSetKey * ID)149 void preserveSet(AnalysisSetKey *ID) { 150 // If we're not already in the saturated 'all' state, add this set. 151 if (!areAllPreserved()) 152 PreservedIDs.insert(ID); 153 } 154 155 /// Mark an analysis as abandoned. 156 /// 157 /// An abandoned analysis is not preserved, even if it is nominally covered 158 /// by some other set or was previously explicitly marked as preserved. 159 /// 160 /// Note that you can only abandon a specific analysis, not a *set* of 161 /// analyses. abandon()162 template <typename AnalysisT> void abandon() { abandon(AnalysisT::ID()); } 163 164 /// Mark an analysis as abandoned using its ID. 165 /// 166 /// An abandoned analysis is not preserved, even if it is nominally covered 167 /// by some other set or was previously explicitly marked as preserved. 168 /// 169 /// Note that you can only abandon a specific analysis, not a *set* of 170 /// analyses. abandon(AnalysisKey * ID)171 void abandon(AnalysisKey *ID) { 172 PreservedIDs.erase(ID); 173 NotPreservedAnalysisIDs.insert(ID); 174 } 175 176 /// Intersect this set with another in place. 177 /// 178 /// This is a mutating operation on this preserved set, removing all 179 /// preserved passes which are not also preserved in the argument. intersect(const PreservedAnalyses & Arg)180 void intersect(const PreservedAnalyses &Arg) { 181 if (Arg.areAllPreserved()) 182 return; 183 if (areAllPreserved()) { 184 *this = Arg; 185 return; 186 } 187 // The intersection requires the *union* of the explicitly not-preserved 188 // IDs and the *intersection* of the preserved IDs. 189 for (auto *ID : Arg.NotPreservedAnalysisIDs) { 190 PreservedIDs.erase(ID); 191 NotPreservedAnalysisIDs.insert(ID); 192 } 193 for (auto *ID : PreservedIDs) 194 if (!Arg.PreservedIDs.count(ID)) 195 PreservedIDs.erase(ID); 196 } 197 198 /// Intersect this set with a temporary other set in place. 199 /// 200 /// This is a mutating operation on this preserved set, removing all 201 /// preserved passes which are not also preserved in the argument. intersect(PreservedAnalyses && Arg)202 void intersect(PreservedAnalyses &&Arg) { 203 if (Arg.areAllPreserved()) 204 return; 205 if (areAllPreserved()) { 206 *this = std::move(Arg); 207 return; 208 } 209 // The intersection requires the *union* of the explicitly not-preserved 210 // IDs and the *intersection* of the preserved IDs. 211 for (auto *ID : Arg.NotPreservedAnalysisIDs) { 212 PreservedIDs.erase(ID); 213 NotPreservedAnalysisIDs.insert(ID); 214 } 215 for (auto *ID : PreservedIDs) 216 if (!Arg.PreservedIDs.count(ID)) 217 PreservedIDs.erase(ID); 218 } 219 220 /// A checker object that makes it easy to query for whether an analysis or 221 /// some set covering it is preserved. 222 class PreservedAnalysisChecker { 223 friend class PreservedAnalyses; 224 225 const PreservedAnalyses &PA; 226 AnalysisKey *const ID; 227 const bool IsAbandoned; 228 229 /// A PreservedAnalysisChecker is tied to a particular Analysis because 230 /// `preserved()` and `preservedSet()` both return false if the Analysis 231 /// was abandoned. PreservedAnalysisChecker(const PreservedAnalyses & PA,AnalysisKey * ID)232 PreservedAnalysisChecker(const PreservedAnalyses &PA, AnalysisKey *ID) 233 : PA(PA), ID(ID), IsAbandoned(PA.NotPreservedAnalysisIDs.count(ID)) {} 234 235 public: 236 /// Returns true if the checker's analysis was not abandoned and either 237 /// - the analysis is explicitly preserved or 238 /// - all analyses are preserved. preserved()239 bool preserved() { 240 return !IsAbandoned && (PA.PreservedIDs.count(&AllAnalysesKey) || 241 PA.PreservedIDs.count(ID)); 242 } 243 244 /// Return true if the checker's analysis was not abandoned, i.e. it was not 245 /// explicitly invalidated. Even if the analysis is not explicitly 246 /// preserved, if the analysis is known stateless, then it is preserved. preservedWhenStateless()247 bool preservedWhenStateless() { return !IsAbandoned; } 248 249 /// Returns true if the checker's analysis was not abandoned and either 250 /// - \p AnalysisSetT is explicitly preserved or 251 /// - all analyses are preserved. preservedSet()252 template <typename AnalysisSetT> bool preservedSet() { 253 AnalysisSetKey *SetID = AnalysisSetT::ID(); 254 return !IsAbandoned && (PA.PreservedIDs.count(&AllAnalysesKey) || 255 PA.PreservedIDs.count(SetID)); 256 } 257 }; 258 259 /// Build a checker for this `PreservedAnalyses` and the specified analysis 260 /// type. 261 /// 262 /// You can use the returned object to query whether an analysis was 263 /// preserved. See the example in the comment on `PreservedAnalysis`. getChecker()264 template <typename AnalysisT> PreservedAnalysisChecker getChecker() const { 265 return PreservedAnalysisChecker(*this, AnalysisT::ID()); 266 } 267 268 /// Build a checker for this `PreservedAnalyses` and the specified analysis 269 /// ID. 270 /// 271 /// You can use the returned object to query whether an analysis was 272 /// preserved. See the example in the comment on `PreservedAnalysis`. getChecker(AnalysisKey * ID)273 PreservedAnalysisChecker getChecker(AnalysisKey *ID) const { 274 return PreservedAnalysisChecker(*this, ID); 275 } 276 277 /// Test whether all analyses are preserved (and none are abandoned). 278 /// 279 /// This is used primarily to optimize for the common case of a transformation 280 /// which makes no changes to the IR. areAllPreserved()281 bool areAllPreserved() const { 282 return NotPreservedAnalysisIDs.empty() && 283 PreservedIDs.count(&AllAnalysesKey); 284 } 285 286 /// Directly test whether a set of analyses is preserved. 287 /// 288 /// This is only true when no analyses have been explicitly abandoned. allAnalysesInSetPreserved()289 template <typename AnalysisSetT> bool allAnalysesInSetPreserved() const { 290 return allAnalysesInSetPreserved(AnalysisSetT::ID()); 291 } 292 293 /// Directly test whether a set of analyses is preserved. 294 /// 295 /// This is only true when no analyses have been explicitly abandoned. allAnalysesInSetPreserved(AnalysisSetKey * SetID)296 bool allAnalysesInSetPreserved(AnalysisSetKey *SetID) const { 297 return NotPreservedAnalysisIDs.empty() && 298 (PreservedIDs.count(&AllAnalysesKey) || PreservedIDs.count(SetID)); 299 } 300 301 private: 302 /// A special key used to indicate all analyses. 303 static AnalysisSetKey AllAnalysesKey; 304 305 /// The IDs of analyses and analysis sets that are preserved. 306 SmallPtrSet<void *, 2> PreservedIDs; 307 308 /// The IDs of explicitly not-preserved analyses. 309 /// 310 /// If an analysis in this set is covered by a set in `PreservedIDs`, we 311 /// consider it not-preserved. That is, `NotPreservedAnalysisIDs` always 312 /// "wins" over analysis sets in `PreservedIDs`. 313 /// 314 /// Also, a given ID should never occur both here and in `PreservedIDs`. 315 SmallPtrSet<AnalysisKey *, 2> NotPreservedAnalysisIDs; 316 }; 317 } // namespace llvm 318 319 #endif