1 //===- PassManagerImpl.h - Pass management infrastructure -------*- 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 /// Provides implementations for PassManager and AnalysisManager template 10 /// methods. These classes should be explicitly instantiated for any IR unit, 11 /// and files doing the explicit instantiation should include this header. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_IR_PASSMANAGERIMPL_H 16 #define LLVM_IR_PASSMANAGERIMPL_H 17 18 #include "llvm/IR/Function.h" 19 #include "llvm/IR/PassInstrumentation.h" 20 #include "llvm/IR/PassManager.h" 21 #include "llvm/Support/CommandLine.h" 22 #include "llvm/Support/PrettyStackTrace.h" 23 24 extern llvm::cl::opt<bool> UseNewDbgInfoFormat; 25 26 namespace llvm { 27 28 template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs> 29 PreservedAnalyses PassManager<IRUnitT, AnalysisManagerT, ExtraArgTs...>::run( 30 IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs) { 31 class StackTraceEntry : public PrettyStackTraceEntry { 32 const PassInstrumentation &PI; 33 IRUnitT &IR; 34 PassConceptT *Pass = nullptr; 35 36 public: 37 explicit StackTraceEntry(const PassInstrumentation &PI, IRUnitT &IR) 38 : PI(PI), IR(IR) {} 39 40 void setPass(PassConceptT *P) { Pass = P; } 41 42 void print(raw_ostream &OS) const override { 43 OS << "Running pass \""; 44 if (Pass) 45 Pass->printPipeline(OS, [this](StringRef ClassName) { 46 auto PassName = PI.getPassNameForClassName(ClassName); 47 return PassName.empty() ? ClassName : PassName; 48 }); 49 else 50 OS << "unknown"; 51 OS << "\" on "; 52 printIRUnitNameForStackTrace(OS, IR); 53 OS << "\n"; 54 } 55 }; 56 57 PreservedAnalyses PA = PreservedAnalyses::all(); 58 59 // Request PassInstrumentation from analysis manager, will use it to run 60 // instrumenting callbacks for the passes later. 61 // Here we use std::tuple wrapper over getResult which helps to extract 62 // AnalysisManager's arguments out of the whole ExtraArgs set. 63 PassInstrumentation PI = 64 detail::getAnalysisResult<PassInstrumentationAnalysis>( 65 AM, IR, std::tuple<ExtraArgTs...>(ExtraArgs...)); 66 67 // RemoveDIs: if requested, convert debug-info to DbgRecord representation 68 // for duration of these passes. 69 ScopedDbgInfoFormatSetter FormatSetter(IR, UseNewDbgInfoFormat); 70 71 StackTraceEntry Entry(PI, IR); 72 for (auto &Pass : Passes) { 73 Entry.setPass(&*Pass); 74 75 // Check the PassInstrumentation's BeforePass callbacks before running the 76 // pass, skip its execution completely if asked to (callback returns 77 // false). 78 if (!PI.runBeforePass<IRUnitT>(*Pass, IR)) 79 continue; 80 81 PreservedAnalyses PassPA = Pass->run(IR, AM, ExtraArgs...); 82 83 // Update the analysis manager as each pass runs and potentially 84 // invalidates analyses. 85 AM.invalidate(IR, PassPA); 86 87 // Call onto PassInstrumentation's AfterPass callbacks immediately after 88 // running the pass. 89 PI.runAfterPass<IRUnitT>(*Pass, IR, PassPA); 90 91 // Finally, intersect the preserved analyses to compute the aggregate 92 // preserved set for this pass manager. 93 PA.intersect(std::move(PassPA)); 94 } 95 96 // Invalidation was handled after each pass in the above loop for the 97 // current unit of IR. Therefore, the remaining analysis results in the 98 // AnalysisManager are preserved. We mark this with a set so that we don't 99 // need to inspect each one individually. 100 PA.preserveSet<AllAnalysesOn<IRUnitT>>(); 101 102 return PA; 103 } 104 105 template <typename IRUnitT, typename... ExtraArgTs> 106 inline AnalysisManager<IRUnitT, ExtraArgTs...>::AnalysisManager() = default; 107 108 template <typename IRUnitT, typename... ExtraArgTs> 109 inline AnalysisManager<IRUnitT, ExtraArgTs...>::AnalysisManager( 110 AnalysisManager &&) = default; 111 112 template <typename IRUnitT, typename... ExtraArgTs> 113 inline AnalysisManager<IRUnitT, ExtraArgTs...> & 114 AnalysisManager<IRUnitT, ExtraArgTs...>::operator=(AnalysisManager &&) = 115 default; 116 117 template <typename IRUnitT, typename... ExtraArgTs> 118 inline void 119 AnalysisManager<IRUnitT, ExtraArgTs...>::clear(IRUnitT &IR, 120 llvm::StringRef Name) { 121 if (auto *PI = getCachedResult<PassInstrumentationAnalysis>(IR)) 122 PI->runAnalysesCleared(Name); 123 124 auto ResultsListI = AnalysisResultLists.find(&IR); 125 if (ResultsListI == AnalysisResultLists.end()) 126 return; 127 // Delete the map entries that point into the results list. 128 for (auto &IDAndResult : ResultsListI->second) 129 AnalysisResults.erase({IDAndResult.first, &IR}); 130 131 // And actually destroy and erase the results associated with this IR. 132 AnalysisResultLists.erase(ResultsListI); 133 } 134 135 template <typename IRUnitT, typename... ExtraArgTs> 136 inline typename AnalysisManager<IRUnitT, ExtraArgTs...>::ResultConceptT & 137 AnalysisManager<IRUnitT, ExtraArgTs...>::getResultImpl( 138 AnalysisKey *ID, IRUnitT &IR, ExtraArgTs... ExtraArgs) { 139 typename AnalysisResultMapT::iterator RI; 140 bool Inserted; 141 std::tie(RI, Inserted) = AnalysisResults.insert(std::make_pair( 142 std::make_pair(ID, &IR), typename AnalysisResultListT::iterator())); 143 144 // If we don't have a cached result for this function, look up the pass and 145 // run it to produce a result, which we then add to the cache. 146 if (Inserted) { 147 auto &P = this->lookUpPass(ID); 148 149 PassInstrumentation PI; 150 if (ID != PassInstrumentationAnalysis::ID()) { 151 PI = getResult<PassInstrumentationAnalysis>(IR, ExtraArgs...); 152 PI.runBeforeAnalysis(P, IR); 153 } 154 155 AnalysisResultListT &ResultList = AnalysisResultLists[&IR]; 156 ResultList.emplace_back(ID, P.run(IR, *this, ExtraArgs...)); 157 158 PI.runAfterAnalysis(P, IR); 159 160 // P.run may have inserted elements into AnalysisResults and invalidated 161 // RI. 162 RI = AnalysisResults.find({ID, &IR}); 163 assert(RI != AnalysisResults.end() && "we just inserted it!"); 164 165 RI->second = std::prev(ResultList.end()); 166 } 167 168 return *RI->second->second; 169 } 170 171 template <typename IRUnitT, typename... ExtraArgTs> 172 inline void AnalysisManager<IRUnitT, ExtraArgTs...>::invalidate( 173 IRUnitT &IR, const PreservedAnalyses &PA) { 174 // We're done if all analyses on this IR unit are preserved. 175 if (PA.allAnalysesInSetPreserved<AllAnalysesOn<IRUnitT>>()) 176 return; 177 178 // Track whether each analysis's result is invalidated in 179 // IsResultInvalidated. 180 SmallDenseMap<AnalysisKey *, bool, 8> IsResultInvalidated; 181 Invalidator Inv(IsResultInvalidated, AnalysisResults); 182 AnalysisResultListT &ResultsList = AnalysisResultLists[&IR]; 183 for (auto &AnalysisResultPair : ResultsList) { 184 // This is basically the same thing as Invalidator::invalidate, but we 185 // can't call it here because we're operating on the type-erased result. 186 // Moreover if we instead called invalidate() directly, it would do an 187 // unnecessary look up in ResultsList. 188 AnalysisKey *ID = AnalysisResultPair.first; 189 auto &Result = *AnalysisResultPair.second; 190 191 auto IMapI = IsResultInvalidated.find(ID); 192 if (IMapI != IsResultInvalidated.end()) 193 // This result was already handled via the Invalidator. 194 continue; 195 196 // Try to invalidate the result, giving it the Invalidator so it can 197 // recursively query for any dependencies it has and record the result. 198 // Note that we cannot reuse 'IMapI' here or pre-insert the ID, as 199 // Result.invalidate may insert things into the map, invalidating our 200 // iterator. 201 bool Inserted = 202 IsResultInvalidated.insert({ID, Result.invalidate(IR, PA, Inv)}).second; 203 (void)Inserted; 204 assert(Inserted && "Should never have already inserted this ID, likely " 205 "indicates a cycle!"); 206 } 207 208 // Now erase the results that were marked above as invalidated. 209 if (!IsResultInvalidated.empty()) { 210 for (auto I = ResultsList.begin(), E = ResultsList.end(); I != E;) { 211 AnalysisKey *ID = I->first; 212 if (!IsResultInvalidated.lookup(ID)) { 213 ++I; 214 continue; 215 } 216 217 if (auto *PI = getCachedResult<PassInstrumentationAnalysis>(IR)) 218 PI->runAnalysisInvalidated(this->lookUpPass(ID), IR); 219 220 I = ResultsList.erase(I); 221 AnalysisResults.erase({ID, &IR}); 222 } 223 } 224 225 if (ResultsList.empty()) 226 AnalysisResultLists.erase(&IR); 227 } 228 } // end namespace llvm 229 230 #endif // LLVM_IR_PASSMANAGERIMPL_H 231