1f88287fdSHans Wennborg //===- PassManager.cpp - Infrastructure for managing & running IR passes --===//
274015a70SChandler Carruth //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
674015a70SChandler Carruth //
774015a70SChandler Carruth //===----------------------------------------------------------------------===//
874015a70SChandler Carruth 
974a8a221SChandler Carruth #include "llvm/IR/PassManager.h"
10*e188aae4Sserge-sans-paille #include "llvm/ADT/DenseMapInfo.h"
11*e188aae4Sserge-sans-paille #include "llvm/ADT/Optional.h"
12105642afSReid Kleckner #include "llvm/IR/PassManagerImpl.h"
1374015a70SChandler Carruth 
1474015a70SChandler Carruth using namespace llvm;
15a13f27ccSChandler Carruth 
16b8ce9737SArthur Eubanks namespace llvm {
176b981647SChandler Carruth // Explicit template instantiations and specialization defininitions for core
186b981647SChandler Carruth // template typedefs.
198abdf75dSChandler Carruth template class AllAnalysesOn<Module>;
208abdf75dSChandler Carruth template class AllAnalysesOn<Function>;
21afcec4c5SChandler Carruth template class PassManager<Module>;
22afcec4c5SChandler Carruth template class PassManager<Function>;
23afcec4c5SChandler Carruth template class AnalysisManager<Module>;
24afcec4c5SChandler Carruth template class AnalysisManager<Function>;
252a54094dSChandler Carruth template class InnerAnalysisManagerProxy<FunctionAnalysisManager, Module>;
262a54094dSChandler Carruth template class OuterAnalysisManagerProxy<ModuleAnalysisManager, Function>;
276b981647SChandler Carruth 
286b981647SChandler Carruth template <>
invalidate(Module & M,const PreservedAnalyses & PA,ModuleAnalysisManager::Invalidator & Inv)296b981647SChandler Carruth bool FunctionAnalysisManagerModuleProxy::Result::invalidate(
306b981647SChandler Carruth     Module &M, const PreservedAnalyses &PA,
316b981647SChandler Carruth     ModuleAnalysisManager::Invalidator &Inv) {
32ba90ae96SChandler Carruth   // If literally everything is preserved, we're done.
33ba90ae96SChandler Carruth   if (PA.areAllPreserved())
34ba90ae96SChandler Carruth     return false; // This is still a valid proxy.
35ba90ae96SChandler Carruth 
366b981647SChandler Carruth   // If this proxy isn't marked as preserved, then even if the result remains
376b981647SChandler Carruth   // valid, the key itself may no longer be valid, so we clear everything.
386b981647SChandler Carruth   //
396b981647SChandler Carruth   // Note that in order to preserve this proxy, a module pass must ensure that
406b981647SChandler Carruth   // the FAM has been completely updated to handle the deletion of functions.
416b981647SChandler Carruth   // Specifically, any FAM-cached results for those functions need to have been
426b981647SChandler Carruth   // forcibly cleared. When preserved, this proxy will only invalidate results
436b981647SChandler Carruth   // cached on functions *still in the module* at the end of the module pass.
44ba90ae96SChandler Carruth   auto PAC = PA.getChecker<FunctionAnalysisManagerModuleProxy>();
45ba90ae96SChandler Carruth   if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Module>>()) {
466b981647SChandler Carruth     InnerAM->clear();
476b981647SChandler Carruth     return true;
486b981647SChandler Carruth   }
496b981647SChandler Carruth 
50ba90ae96SChandler Carruth   // Directly check if the relevant set is preserved.
51ba90ae96SChandler Carruth   bool AreFunctionAnalysesPreserved =
52ba90ae96SChandler Carruth       PA.allAnalysesInSetPreserved<AllAnalysesOn<Function>>();
53ba90ae96SChandler Carruth 
54ba90ae96SChandler Carruth   // Now walk all the functions to see if any inner analysis invalidation is
55ba90ae96SChandler Carruth   // necessary.
56ba90ae96SChandler Carruth   for (Function &F : M) {
57ba90ae96SChandler Carruth     Optional<PreservedAnalyses> FunctionPA;
58ba90ae96SChandler Carruth 
59ba90ae96SChandler Carruth     // Check to see whether the preserved set needs to be pruned based on
60ba90ae96SChandler Carruth     // module-level analysis invalidation that triggers deferred invalidation
61ba90ae96SChandler Carruth     // registered with the outer analysis manager proxy for this function.
62ba90ae96SChandler Carruth     if (auto *OuterProxy =
63ba90ae96SChandler Carruth             InnerAM->getCachedResult<ModuleAnalysisManagerFunctionProxy>(F))
64ba90ae96SChandler Carruth       for (const auto &OuterInvalidationPair :
65ba90ae96SChandler Carruth            OuterProxy->getOuterInvalidations()) {
66ba90ae96SChandler Carruth         AnalysisKey *OuterAnalysisID = OuterInvalidationPair.first;
67ba90ae96SChandler Carruth         const auto &InnerAnalysisIDs = OuterInvalidationPair.second;
68ba90ae96SChandler Carruth         if (Inv.invalidate(OuterAnalysisID, M, PA)) {
69ba90ae96SChandler Carruth           if (!FunctionPA)
70ba90ae96SChandler Carruth             FunctionPA = PA;
71ba90ae96SChandler Carruth           for (AnalysisKey *InnerAnalysisID : InnerAnalysisIDs)
72ba90ae96SChandler Carruth             FunctionPA->abandon(InnerAnalysisID);
73ba90ae96SChandler Carruth         }
74ba90ae96SChandler Carruth       }
75ba90ae96SChandler Carruth 
76ba90ae96SChandler Carruth     // Check if we needed a custom PA set, and if so we'll need to run the
77ba90ae96SChandler Carruth     // inner invalidation.
78ba90ae96SChandler Carruth     if (FunctionPA) {
79ba90ae96SChandler Carruth       InnerAM->invalidate(F, *FunctionPA);
80ba90ae96SChandler Carruth       continue;
81ba90ae96SChandler Carruth     }
82ba90ae96SChandler Carruth 
83ba90ae96SChandler Carruth     // Otherwise we only need to do invalidation if the original PA set didn't
84ba90ae96SChandler Carruth     // preserve all function analyses.
85ba90ae96SChandler Carruth     if (!AreFunctionAnalysesPreserved)
866b981647SChandler Carruth       InnerAM->invalidate(F, PA);
87ba90ae96SChandler Carruth   }
886b981647SChandler Carruth 
896b981647SChandler Carruth   // Return false to indicate that this result is still a valid proxy.
906b981647SChandler Carruth   return false;
916b981647SChandler Carruth }
928b52037cSSimon Pilgrim } // namespace llvm
93dab4eae2SChandler Carruth 
printPipeline(raw_ostream & OS,function_ref<StringRef (StringRef)> MapClassName2PassName)94304f2bd2SMarkus Lavin void ModuleToFunctionPassAdaptor::printPipeline(
95304f2bd2SMarkus Lavin     raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
967175886aSArthur Eubanks   OS << "function";
977175886aSArthur Eubanks   if (EagerlyInvalidate)
987175886aSArthur Eubanks     OS << "<eager-inv>";
997175886aSArthur Eubanks   OS << "(";
100304f2bd2SMarkus Lavin   Pass->printPipeline(OS, MapClassName2PassName);
101304f2bd2SMarkus Lavin   OS << ")";
102304f2bd2SMarkus Lavin }
103304f2bd2SMarkus Lavin 
run(Module & M,ModuleAnalysisManager & AM)1047f6f9f4cSArthur Eubanks PreservedAnalyses ModuleToFunctionPassAdaptor::run(Module &M,
1057f6f9f4cSArthur Eubanks                                                    ModuleAnalysisManager &AM) {
1067f6f9f4cSArthur Eubanks   FunctionAnalysisManager &FAM =
1077f6f9f4cSArthur Eubanks       AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
1087f6f9f4cSArthur Eubanks 
1097f6f9f4cSArthur Eubanks   // Request PassInstrumentation from analysis manager, will use it to run
1107f6f9f4cSArthur Eubanks   // instrumenting callbacks for the passes later.
1117f6f9f4cSArthur Eubanks   PassInstrumentation PI = AM.getResult<PassInstrumentationAnalysis>(M);
1127f6f9f4cSArthur Eubanks 
1137f6f9f4cSArthur Eubanks   PreservedAnalyses PA = PreservedAnalyses::all();
1147f6f9f4cSArthur Eubanks   for (Function &F : M) {
1157f6f9f4cSArthur Eubanks     if (F.isDeclaration())
1167f6f9f4cSArthur Eubanks       continue;
1177f6f9f4cSArthur Eubanks 
1187f6f9f4cSArthur Eubanks     // Check the PassInstrumentation's BeforePass callbacks before running the
1197f6f9f4cSArthur Eubanks     // pass, skip its execution completely if asked to (callback returns
1207f6f9f4cSArthur Eubanks     // false).
1217f6f9f4cSArthur Eubanks     if (!PI.runBeforePass<Function>(*Pass, F))
1227f6f9f4cSArthur Eubanks       continue;
1237f6f9f4cSArthur Eubanks 
1247f6f9f4cSArthur Eubanks     PreservedAnalyses PassPA;
1257f6f9f4cSArthur Eubanks     {
1267f6f9f4cSArthur Eubanks       TimeTraceScope TimeScope(Pass->name(), F.getName());
1277f6f9f4cSArthur Eubanks       PassPA = Pass->run(F, FAM);
1287f6f9f4cSArthur Eubanks     }
1297f6f9f4cSArthur Eubanks 
1307f6f9f4cSArthur Eubanks     PI.runAfterPass(*Pass, F, PassPA);
1317f6f9f4cSArthur Eubanks 
1327f6f9f4cSArthur Eubanks     // We know that the function pass couldn't have invalidated any other
1337f6f9f4cSArthur Eubanks     // function's analyses (that's the contract of a function pass), so
1347f6f9f4cSArthur Eubanks     // directly handle the function analysis manager's invalidation here.
1357175886aSArthur Eubanks     FAM.invalidate(F, EagerlyInvalidate ? PreservedAnalyses::none() : PassPA);
1367f6f9f4cSArthur Eubanks 
1377f6f9f4cSArthur Eubanks     // Then intersect the preserved set so that invalidation of module
1387f6f9f4cSArthur Eubanks     // analyses will eventually occur when the module pass completes.
1397f6f9f4cSArthur Eubanks     PA.intersect(std::move(PassPA));
1407f6f9f4cSArthur Eubanks   }
1417f6f9f4cSArthur Eubanks 
1427f6f9f4cSArthur Eubanks   // The FunctionAnalysisManagerModuleProxy is preserved because (we assume)
1437f6f9f4cSArthur Eubanks   // the function passes we ran didn't add or remove any functions.
1447f6f9f4cSArthur Eubanks   //
1457f6f9f4cSArthur Eubanks   // We also preserve all analyses on Functions, because we did all the
1467f6f9f4cSArthur Eubanks   // invalidation we needed to do above.
1477f6f9f4cSArthur Eubanks   PA.preserveSet<AllAnalysesOn<Function>>();
1487f6f9f4cSArthur Eubanks   PA.preserve<FunctionAnalysisManagerModuleProxy>();
1497f6f9f4cSArthur Eubanks   return PA;
1507f6f9f4cSArthur Eubanks }
1517f6f9f4cSArthur Eubanks 
152ca68a3ecSChandler Carruth AnalysisSetKey CFGAnalyses::SetKey;
153ca68a3ecSChandler Carruth 
154ba90ae96SChandler Carruth AnalysisSetKey PreservedAnalyses::AllAnalysesKey;
155