| //===- PassManager.cpp - Infrastructure for managing & running IR passes --===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/IR/PassManager.h" | |
| #include "llvm/ADT/STLExtras.h" | |
| #include "llvm/IR/LLVMContext.h" | |
| using namespace llvm; | |
| // Explicit template instantiations and specialization defininitions for core | |
| // template typedefs. | |
| namespace llvm { | |
| template class AllAnalysesOn<Module>; | |
| template class AllAnalysesOn<Function>; | |
| template class PassManager<Module>; | |
| template class PassManager<Function>; | |
| template class AnalysisManager<Module>; | |
| template class AnalysisManager<Function>; | |
| template class InnerAnalysisManagerProxy<FunctionAnalysisManager, Module>; | |
| template class OuterAnalysisManagerProxy<ModuleAnalysisManager, Function>; | |
| template <> | |
| bool FunctionAnalysisManagerModuleProxy::Result::invalidate( | |
| Module &M, const PreservedAnalyses &PA, | |
| ModuleAnalysisManager::Invalidator &Inv) { | |
| // If literally everything is preserved, we're done. | |
| if (PA.areAllPreserved()) | |
| return false; // This is still a valid proxy. | |
| // If this proxy isn't marked as preserved, then even if the result remains | |
| // valid, the key itself may no longer be valid, so we clear everything. | |
| // | |
| // Note that in order to preserve this proxy, a module pass must ensure that | |
| // the FAM has been completely updated to handle the deletion of functions. | |
| // Specifically, any FAM-cached results for those functions need to have been | |
| // forcibly cleared. When preserved, this proxy will only invalidate results | |
| // cached on functions *still in the module* at the end of the module pass. | |
| auto PAC = PA.getChecker<FunctionAnalysisManagerModuleProxy>(); | |
| if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Module>>()) { | |
| InnerAM->clear(); | |
| return true; | |
| } | |
| // Directly check if the relevant set is preserved. | |
| bool AreFunctionAnalysesPreserved = | |
| PA.allAnalysesInSetPreserved<AllAnalysesOn<Function>>(); | |
| // Now walk all the functions to see if any inner analysis invalidation is | |
| // necessary. | |
| for (Function &F : M) { | |
| Optional<PreservedAnalyses> FunctionPA; | |
| // Check to see whether the preserved set needs to be pruned based on | |
| // module-level analysis invalidation that triggers deferred invalidation | |
| // registered with the outer analysis manager proxy for this function. | |
| if (auto *OuterProxy = | |
| InnerAM->getCachedResult<ModuleAnalysisManagerFunctionProxy>(F)) | |
| for (const auto &OuterInvalidationPair : | |
| OuterProxy->getOuterInvalidations()) { | |
| AnalysisKey *OuterAnalysisID = OuterInvalidationPair.first; | |
| const auto &InnerAnalysisIDs = OuterInvalidationPair.second; | |
| if (Inv.invalidate(OuterAnalysisID, M, PA)) { | |
| if (!FunctionPA) | |
| FunctionPA = PA; | |
| for (AnalysisKey *InnerAnalysisID : InnerAnalysisIDs) | |
| FunctionPA->abandon(InnerAnalysisID); | |
| } | |
| } | |
| // Check if we needed a custom PA set, and if so we'll need to run the | |
| // inner invalidation. | |
| if (FunctionPA) { | |
| InnerAM->invalidate(F, *FunctionPA); | |
| continue; | |
| } | |
| // Otherwise we only need to do invalidation if the original PA set didn't | |
| // preserve all function analyses. | |
| if (!AreFunctionAnalysesPreserved) | |
| InnerAM->invalidate(F, PA); | |
| } | |
| // Return false to indicate that this result is still a valid proxy. | |
| return false; | |
| } | |
| } | |
| AnalysisSetKey CFGAnalyses::SetKey; | |
| AnalysisSetKey PreservedAnalyses::AllAnalysesKey; |