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