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 /// 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/PassManager.h" 19 20 namespace llvm { 21 22 template <typename IRUnitT, typename... ExtraArgTs> 23 inline AnalysisManager<IRUnitT, ExtraArgTs...>::AnalysisManager( 24 bool DebugLogging) 25 : DebugLogging(DebugLogging) {} 26 27 template <typename IRUnitT, typename... ExtraArgTs> 28 inline AnalysisManager<IRUnitT, ExtraArgTs...>::AnalysisManager( 29 AnalysisManager &&) = default; 30 31 template <typename IRUnitT, typename... ExtraArgTs> 32 inline AnalysisManager<IRUnitT, ExtraArgTs...> & 33 AnalysisManager<IRUnitT, ExtraArgTs...>::operator=(AnalysisManager &&) = 34 default; 35 36 template <typename IRUnitT, typename... ExtraArgTs> 37 inline void 38 AnalysisManager<IRUnitT, ExtraArgTs...>::clear(IRUnitT &IR, 39 llvm::StringRef Name) { 40 if (DebugLogging) 41 dbgs() << "Clearing all analysis results for: " << Name << "\n"; 42 43 auto ResultsListI = AnalysisResultLists.find(&IR); 44 if (ResultsListI == AnalysisResultLists.end()) 45 return; 46 // Delete the map entries that point into the results list. 47 for (auto &IDAndResult : ResultsListI->second) 48 AnalysisResults.erase({IDAndResult.first, &IR}); 49 50 // And actually destroy and erase the results associated with this IR. 51 AnalysisResultLists.erase(ResultsListI); 52 } 53 54 template <typename IRUnitT, typename... ExtraArgTs> 55 inline typename AnalysisManager<IRUnitT, ExtraArgTs...>::ResultConceptT & 56 AnalysisManager<IRUnitT, ExtraArgTs...>::getResultImpl( 57 AnalysisKey *ID, IRUnitT &IR, ExtraArgTs... ExtraArgs) { 58 typename AnalysisResultMapT::iterator RI; 59 bool Inserted; 60 std::tie(RI, Inserted) = AnalysisResults.insert(std::make_pair( 61 std::make_pair(ID, &IR), typename AnalysisResultListT::iterator())); 62 63 // If we don't have a cached result for this function, look up the pass and 64 // run it to produce a result, which we then add to the cache. 65 if (Inserted) { 66 auto &P = this->lookUpPass(ID); 67 if (DebugLogging) 68 dbgs() << "Running analysis: " << P.name() << " on " << IR.getName() 69 << "\n"; 70 71 PassInstrumentation PI; 72 if (ID != PassInstrumentationAnalysis::ID()) { 73 PI = getResult<PassInstrumentationAnalysis>(IR, ExtraArgs...); 74 PI.runBeforeAnalysis(P, IR); 75 } 76 77 AnalysisResultListT &ResultList = AnalysisResultLists[&IR]; 78 ResultList.emplace_back(ID, P.run(IR, *this, ExtraArgs...)); 79 80 PI.runAfterAnalysis(P, IR); 81 82 // P.run may have inserted elements into AnalysisResults and invalidated 83 // RI. 84 RI = AnalysisResults.find({ID, &IR}); 85 assert(RI != AnalysisResults.end() && "we just inserted it!"); 86 87 RI->second = std::prev(ResultList.end()); 88 } 89 90 return *RI->second->second; 91 } 92 93 template <typename IRUnitT, typename... ExtraArgTs> 94 inline void AnalysisManager<IRUnitT, ExtraArgTs...>::invalidate( 95 IRUnitT &IR, const PreservedAnalyses &PA) { 96 // We're done if all analyses on this IR unit are preserved. 97 if (PA.allAnalysesInSetPreserved<AllAnalysesOn<IRUnitT>>()) 98 return; 99 100 if (DebugLogging) 101 dbgs() << "Invalidating all non-preserved analyses for: " << IR.getName() 102 << "\n"; 103 104 // Track whether each analysis's result is invalidated in 105 // IsResultInvalidated. 106 SmallDenseMap<AnalysisKey *, bool, 8> IsResultInvalidated; 107 Invalidator Inv(IsResultInvalidated, AnalysisResults); 108 AnalysisResultListT &ResultsList = AnalysisResultLists[&IR]; 109 for (auto &AnalysisResultPair : ResultsList) { 110 // This is basically the same thing as Invalidator::invalidate, but we 111 // can't call it here because we're operating on the type-erased result. 112 // Moreover if we instead called invalidate() directly, it would do an 113 // unnecessary look up in ResultsList. 114 AnalysisKey *ID = AnalysisResultPair.first; 115 auto &Result = *AnalysisResultPair.second; 116 117 auto IMapI = IsResultInvalidated.find(ID); 118 if (IMapI != IsResultInvalidated.end()) 119 // This result was already handled via the Invalidator. 120 continue; 121 122 // Try to invalidate the result, giving it the Invalidator so it can 123 // recursively query for any dependencies it has and record the result. 124 // Note that we cannot reuse 'IMapI' here or pre-insert the ID, as 125 // Result.invalidate may insert things into the map, invalidating our 126 // iterator. 127 bool Inserted = 128 IsResultInvalidated.insert({ID, Result.invalidate(IR, PA, Inv)}).second; 129 (void)Inserted; 130 assert(Inserted && "Should never have already inserted this ID, likely " 131 "indicates a cycle!"); 132 } 133 134 // Now erase the results that were marked above as invalidated. 135 if (!IsResultInvalidated.empty()) { 136 for (auto I = ResultsList.begin(), E = ResultsList.end(); I != E;) { 137 AnalysisKey *ID = I->first; 138 if (!IsResultInvalidated.lookup(ID)) { 139 ++I; 140 continue; 141 } 142 143 if (DebugLogging) 144 dbgs() << "Invalidating analysis: " << this->lookUpPass(ID).name() 145 << " on " << IR.getName() << "\n"; 146 147 I = ResultsList.erase(I); 148 AnalysisResults.erase({ID, &IR}); 149 } 150 } 151 152 if (ResultsList.empty()) 153 AnalysisResultLists.erase(&IR); 154 } 155 } // end namespace llvm 156 157 #endif // LLVM_IR_PASSMANAGERIMPL_H 158