#pragma once #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #endif //===- PassManagerImpl.h - Pass management infrastructure -------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// /// Provides implementations for PassManager and AnalysisManager template /// methods. These classes should be explicitly instantiated for any IR unit, /// and files doing the explicit instantiation should include this header. /// //===----------------------------------------------------------------------===// #ifndef LLVM_IR_PASSMANAGERIMPL_H #define LLVM_IR_PASSMANAGERIMPL_H #include "llvm/IR/PassManager.h" namespace llvm { template inline AnalysisManager::AnalysisManager( bool DebugLogging) : DebugLogging(DebugLogging) {} template inline AnalysisManager::AnalysisManager( AnalysisManager &&) = default; template inline AnalysisManager & AnalysisManager::operator=(AnalysisManager &&) = default; template inline void AnalysisManager::clear(IRUnitT &IR, llvm::StringRef Name) { if (DebugLogging) dbgs() << "Clearing all analysis results for: " << Name << "\n"; auto ResultsListI = AnalysisResultLists.find(&IR); if (ResultsListI == AnalysisResultLists.end()) return; // Delete the map entries that point into the results list. for (auto &IDAndResult : ResultsListI->second) AnalysisResults.erase({IDAndResult.first, &IR}); // And actually destroy and erase the results associated with this IR. AnalysisResultLists.erase(ResultsListI); } template inline typename AnalysisManager::ResultConceptT & AnalysisManager::getResultImpl( AnalysisKey *ID, IRUnitT &IR, ExtraArgTs... ExtraArgs) { typename AnalysisResultMapT::iterator RI; bool Inserted; std::tie(RI, Inserted) = AnalysisResults.insert(std::make_pair( std::make_pair(ID, &IR), typename AnalysisResultListT::iterator())); // If we don't have a cached result for this function, look up the pass and // run it to produce a result, which we then add to the cache. if (Inserted) { auto &P = this->lookUpPass(ID); PassInstrumentation PI; if (ID != PassInstrumentationAnalysis::ID()) { PI = getResult(IR, ExtraArgs...); PI.runBeforeAnalysis(P, IR); } AnalysisResultListT &ResultList = AnalysisResultLists[&IR]; ResultList.emplace_back(ID, P.run(IR, *this, ExtraArgs...)); PI.runAfterAnalysis(P, IR); // P.run may have inserted elements into AnalysisResults and invalidated // RI. RI = AnalysisResults.find({ID, &IR}); assert(RI != AnalysisResults.end() && "we just inserted it!"); RI->second = std::prev(ResultList.end()); } return *RI->second->second; } template inline void AnalysisManager::invalidate( IRUnitT &IR, const PreservedAnalyses &PA) { // We're done if all analyses on this IR unit are preserved. if (PA.allAnalysesInSetPreserved>()) return; // Track whether each analysis's result is invalidated in // IsResultInvalidated. SmallDenseMap IsResultInvalidated; Invalidator Inv(IsResultInvalidated, AnalysisResults); AnalysisResultListT &ResultsList = AnalysisResultLists[&IR]; for (auto &AnalysisResultPair : ResultsList) { // This is basically the same thing as Invalidator::invalidate, but we // can't call it here because we're operating on the type-erased result. // Moreover if we instead called invalidate() directly, it would do an // unnecessary look up in ResultsList. AnalysisKey *ID = AnalysisResultPair.first; auto &Result = *AnalysisResultPair.second; auto IMapI = IsResultInvalidated.find(ID); if (IMapI != IsResultInvalidated.end()) // This result was already handled via the Invalidator. continue; // Try to invalidate the result, giving it the Invalidator so it can // recursively query for any dependencies it has and record the result. // Note that we cannot reuse 'IMapI' here or pre-insert the ID, as // Result.invalidate may insert things into the map, invalidating our // iterator. bool Inserted = IsResultInvalidated.insert({ID, Result.invalidate(IR, PA, Inv)}).second; (void)Inserted; assert(Inserted && "Should never have already inserted this ID, likely " "indicates a cycle!"); } // Now erase the results that were marked above as invalidated. if (!IsResultInvalidated.empty()) { for (auto I = ResultsList.begin(), E = ResultsList.end(); I != E;) { AnalysisKey *ID = I->first; if (!IsResultInvalidated.lookup(ID)) { ++I; continue; } if (DebugLogging) dbgs() << "Invalidating analysis: " << this->lookUpPass(ID).name() << " on " << IR.getName() << "\n"; I = ResultsList.erase(I); AnalysisResults.erase({ID, &IR}); } } if (ResultsList.empty()) AnalysisResultLists.erase(&IR); } } // end namespace llvm #endif // LLVM_IR_PASSMANAGERIMPL_H #ifdef __GNUC__ #pragma GCC diagnostic pop #endif