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