| //===- PassManager.cpp - Infrastructure for managing & running IR passes --===// |
| // |
| // 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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #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; |