10b57cec5SDimitry Andric //===- PassManager.cpp - Infrastructure for managing & running IR passes --===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/IR/PassManager.h" 10*0fca6ea1SDimitry Andric #include "llvm/IR/Module.h" 115ffd83dbSDimitry Andric #include "llvm/IR/PassManagerImpl.h" 12bdd1243dSDimitry Andric #include <optional> 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric using namespace llvm; 150b57cec5SDimitry Andric 16349cc55cSDimitry Andric namespace llvm { 170b57cec5SDimitry Andric // Explicit template instantiations and specialization defininitions for core 180b57cec5SDimitry Andric // template typedefs. 190b57cec5SDimitry Andric template class AllAnalysesOn<Module>; 200b57cec5SDimitry Andric template class AllAnalysesOn<Function>; 210b57cec5SDimitry Andric template class PassManager<Module>; 220b57cec5SDimitry Andric template class PassManager<Function>; 230b57cec5SDimitry Andric template class AnalysisManager<Module>; 240b57cec5SDimitry Andric template class AnalysisManager<Function>; 250b57cec5SDimitry Andric template class InnerAnalysisManagerProxy<FunctionAnalysisManager, Module>; 260b57cec5SDimitry Andric template class OuterAnalysisManagerProxy<ModuleAnalysisManager, Function>; 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric template <> 290b57cec5SDimitry Andric bool FunctionAnalysisManagerModuleProxy::Result::invalidate( 300b57cec5SDimitry Andric Module &M, const PreservedAnalyses &PA, 310b57cec5SDimitry Andric ModuleAnalysisManager::Invalidator &Inv) { 320b57cec5SDimitry Andric // If literally everything is preserved, we're done. 330b57cec5SDimitry Andric if (PA.areAllPreserved()) 340b57cec5SDimitry Andric return false; // This is still a valid proxy. 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric // If this proxy isn't marked as preserved, then even if the result remains 370b57cec5SDimitry Andric // valid, the key itself may no longer be valid, so we clear everything. 380b57cec5SDimitry Andric // 390b57cec5SDimitry Andric // Note that in order to preserve this proxy, a module pass must ensure that 400b57cec5SDimitry Andric // the FAM has been completely updated to handle the deletion of functions. 410b57cec5SDimitry Andric // Specifically, any FAM-cached results for those functions need to have been 420b57cec5SDimitry Andric // forcibly cleared. When preserved, this proxy will only invalidate results 430b57cec5SDimitry Andric // cached on functions *still in the module* at the end of the module pass. 440b57cec5SDimitry Andric auto PAC = PA.getChecker<FunctionAnalysisManagerModuleProxy>(); 450b57cec5SDimitry Andric if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Module>>()) { 460b57cec5SDimitry Andric InnerAM->clear(); 470b57cec5SDimitry Andric return true; 480b57cec5SDimitry Andric } 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric // Directly check if the relevant set is preserved. 510b57cec5SDimitry Andric bool AreFunctionAnalysesPreserved = 520b57cec5SDimitry Andric PA.allAnalysesInSetPreserved<AllAnalysesOn<Function>>(); 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric // Now walk all the functions to see if any inner analysis invalidation is 550b57cec5SDimitry Andric // necessary. 560b57cec5SDimitry Andric for (Function &F : M) { 57bdd1243dSDimitry Andric std::optional<PreservedAnalyses> FunctionPA; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric // Check to see whether the preserved set needs to be pruned based on 600b57cec5SDimitry Andric // module-level analysis invalidation that triggers deferred invalidation 610b57cec5SDimitry Andric // registered with the outer analysis manager proxy for this function. 620b57cec5SDimitry Andric if (auto *OuterProxy = 630b57cec5SDimitry Andric InnerAM->getCachedResult<ModuleAnalysisManagerFunctionProxy>(F)) 640b57cec5SDimitry Andric for (const auto &OuterInvalidationPair : 650b57cec5SDimitry Andric OuterProxy->getOuterInvalidations()) { 660b57cec5SDimitry Andric AnalysisKey *OuterAnalysisID = OuterInvalidationPair.first; 670b57cec5SDimitry Andric const auto &InnerAnalysisIDs = OuterInvalidationPair.second; 680b57cec5SDimitry Andric if (Inv.invalidate(OuterAnalysisID, M, PA)) { 690b57cec5SDimitry Andric if (!FunctionPA) 700b57cec5SDimitry Andric FunctionPA = PA; 710b57cec5SDimitry Andric for (AnalysisKey *InnerAnalysisID : InnerAnalysisIDs) 720b57cec5SDimitry Andric FunctionPA->abandon(InnerAnalysisID); 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric // Check if we needed a custom PA set, and if so we'll need to run the 770b57cec5SDimitry Andric // inner invalidation. 780b57cec5SDimitry Andric if (FunctionPA) { 790b57cec5SDimitry Andric InnerAM->invalidate(F, *FunctionPA); 800b57cec5SDimitry Andric continue; 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric // Otherwise we only need to do invalidation if the original PA set didn't 840b57cec5SDimitry Andric // preserve all function analyses. 850b57cec5SDimitry Andric if (!AreFunctionAnalysesPreserved) 860b57cec5SDimitry Andric InnerAM->invalidate(F, PA); 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric // Return false to indicate that this result is still a valid proxy. 900b57cec5SDimitry Andric return false; 910b57cec5SDimitry Andric } 925ffd83dbSDimitry Andric } // namespace llvm 930b57cec5SDimitry Andric 94349cc55cSDimitry Andric void ModuleToFunctionPassAdaptor::printPipeline( 95349cc55cSDimitry Andric raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) { 96349cc55cSDimitry Andric OS << "function"; 97349cc55cSDimitry Andric if (EagerlyInvalidate) 98349cc55cSDimitry Andric OS << "<eager-inv>"; 9906c3fb27SDimitry Andric OS << '('; 100349cc55cSDimitry Andric Pass->printPipeline(OS, MapClassName2PassName); 10106c3fb27SDimitry Andric OS << ')'; 102349cc55cSDimitry Andric } 103349cc55cSDimitry Andric 104e8d8bef9SDimitry Andric PreservedAnalyses ModuleToFunctionPassAdaptor::run(Module &M, 105e8d8bef9SDimitry Andric ModuleAnalysisManager &AM) { 106e8d8bef9SDimitry Andric FunctionAnalysisManager &FAM = 107e8d8bef9SDimitry Andric AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 108e8d8bef9SDimitry Andric 109e8d8bef9SDimitry Andric // Request PassInstrumentation from analysis manager, will use it to run 110e8d8bef9SDimitry Andric // instrumenting callbacks for the passes later. 111e8d8bef9SDimitry Andric PassInstrumentation PI = AM.getResult<PassInstrumentationAnalysis>(M); 112e8d8bef9SDimitry Andric 113e8d8bef9SDimitry Andric PreservedAnalyses PA = PreservedAnalyses::all(); 114e8d8bef9SDimitry Andric for (Function &F : M) { 115e8d8bef9SDimitry Andric if (F.isDeclaration()) 116e8d8bef9SDimitry Andric continue; 117e8d8bef9SDimitry Andric 118e8d8bef9SDimitry Andric // Check the PassInstrumentation's BeforePass callbacks before running the 119e8d8bef9SDimitry Andric // pass, skip its execution completely if asked to (callback returns 120e8d8bef9SDimitry Andric // false). 121e8d8bef9SDimitry Andric if (!PI.runBeforePass<Function>(*Pass, F)) 122e8d8bef9SDimitry Andric continue; 123e8d8bef9SDimitry Andric 124bdd1243dSDimitry Andric PreservedAnalyses PassPA = Pass->run(F, FAM); 125e8d8bef9SDimitry Andric 126e8d8bef9SDimitry Andric // We know that the function pass couldn't have invalidated any other 127e8d8bef9SDimitry Andric // function's analyses (that's the contract of a function pass), so 128e8d8bef9SDimitry Andric // directly handle the function analysis manager's invalidation here. 129349cc55cSDimitry Andric FAM.invalidate(F, EagerlyInvalidate ? PreservedAnalyses::none() : PassPA); 130e8d8bef9SDimitry Andric 13106c3fb27SDimitry Andric PI.runAfterPass(*Pass, F, PassPA); 13206c3fb27SDimitry Andric 133e8d8bef9SDimitry Andric // Then intersect the preserved set so that invalidation of module 134e8d8bef9SDimitry Andric // analyses will eventually occur when the module pass completes. 135e8d8bef9SDimitry Andric PA.intersect(std::move(PassPA)); 136e8d8bef9SDimitry Andric } 137e8d8bef9SDimitry Andric 138e8d8bef9SDimitry Andric // The FunctionAnalysisManagerModuleProxy is preserved because (we assume) 139e8d8bef9SDimitry Andric // the function passes we ran didn't add or remove any functions. 140e8d8bef9SDimitry Andric // 141e8d8bef9SDimitry Andric // We also preserve all analyses on Functions, because we did all the 142e8d8bef9SDimitry Andric // invalidation we needed to do above. 143e8d8bef9SDimitry Andric PA.preserveSet<AllAnalysesOn<Function>>(); 144e8d8bef9SDimitry Andric PA.preserve<FunctionAnalysisManagerModuleProxy>(); 145e8d8bef9SDimitry Andric return PA; 146e8d8bef9SDimitry Andric } 147e8d8bef9SDimitry Andric 148*0fca6ea1SDimitry Andric template <> 149*0fca6ea1SDimitry Andric void llvm::printIRUnitNameForStackTrace<Module>(raw_ostream &OS, 150*0fca6ea1SDimitry Andric const Module &IR) { 151*0fca6ea1SDimitry Andric OS << "module \"" << IR.getName() << "\""; 152*0fca6ea1SDimitry Andric } 153*0fca6ea1SDimitry Andric 154*0fca6ea1SDimitry Andric template <> 155*0fca6ea1SDimitry Andric void llvm::printIRUnitNameForStackTrace<Function>(raw_ostream &OS, 156*0fca6ea1SDimitry Andric const Function &IR) { 157*0fca6ea1SDimitry Andric OS << "function \"" << IR.getName() << "\""; 158*0fca6ea1SDimitry Andric } 159*0fca6ea1SDimitry Andric 1600b57cec5SDimitry Andric AnalysisSetKey CFGAnalyses::SetKey; 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric AnalysisSetKey PreservedAnalyses::AllAnalysesKey; 163