1 | //===- PassManager.cpp - Infrastructure for managing & running IR passes --===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "llvm/IR/PassManager.h" |
10 | #include "llvm/IR/PassManagerImpl.h" |
11 | #include <optional> |
12 | |
13 | using namespace llvm; |
14 | |
15 | namespace llvm { |
16 | // Explicit template instantiations and specialization defininitions for core |
17 | // template typedefs. |
18 | template class AllAnalysesOn<Module>; |
19 | template class AllAnalysesOn<Function>; |
20 | template class PassManager<Module>; |
21 | template class PassManager<Function>; |
22 | template class AnalysisManager<Module>; |
23 | template class AnalysisManager<Function>; |
24 | template class InnerAnalysisManagerProxy<FunctionAnalysisManager, Module>; |
25 | template class OuterAnalysisManagerProxy<ModuleAnalysisManager, Function>; |
26 | |
27 | template <> |
28 | bool FunctionAnalysisManagerModuleProxy::Result::invalidate( |
29 | Module &M, const PreservedAnalyses &PA, |
30 | ModuleAnalysisManager::Invalidator &Inv) { |
31 | // If literally everything is preserved, we're done. |
32 | if (PA.areAllPreserved()) |
33 | return false; // This is still a valid proxy. |
34 | |
35 | // If this proxy isn't marked as preserved, then even if the result remains |
36 | // valid, the key itself may no longer be valid, so we clear everything. |
37 | // |
38 | // Note that in order to preserve this proxy, a module pass must ensure that |
39 | // the FAM has been completely updated to handle the deletion of functions. |
40 | // Specifically, any FAM-cached results for those functions need to have been |
41 | // forcibly cleared. When preserved, this proxy will only invalidate results |
42 | // cached on functions *still in the module* at the end of the module pass. |
43 | auto PAC = PA.getChecker<FunctionAnalysisManagerModuleProxy>(); |
44 | if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Module>>()) { |
45 | InnerAM->clear(); |
46 | return true; |
47 | } |
48 | |
49 | // Directly check if the relevant set is preserved. |
50 | bool AreFunctionAnalysesPreserved = |
51 | PA.allAnalysesInSetPreserved<AllAnalysesOn<Function>>(); |
52 | |
53 | // Now walk all the functions to see if any inner analysis invalidation is |
54 | // necessary. |
55 | for (Function &F : M) { |
56 | std::optional<PreservedAnalyses> FunctionPA; |
57 | |
58 | // Check to see whether the preserved set needs to be pruned based on |
59 | // module-level analysis invalidation that triggers deferred invalidation |
60 | // registered with the outer analysis manager proxy for this function. |
61 | if (auto *OuterProxy = |
62 | InnerAM->getCachedResult<ModuleAnalysisManagerFunctionProxy>(IR&: F)) |
63 | for (const auto &OuterInvalidationPair : |
64 | OuterProxy->getOuterInvalidations()) { |
65 | AnalysisKey *OuterAnalysisID = OuterInvalidationPair.first; |
66 | const auto &InnerAnalysisIDs = OuterInvalidationPair.second; |
67 | if (Inv.invalidate(ID: OuterAnalysisID, IR&: M, PA)) { |
68 | if (!FunctionPA) |
69 | FunctionPA = PA; |
70 | for (AnalysisKey *InnerAnalysisID : InnerAnalysisIDs) |
71 | FunctionPA->abandon(ID: InnerAnalysisID); |
72 | } |
73 | } |
74 | |
75 | // Check if we needed a custom PA set, and if so we'll need to run the |
76 | // inner invalidation. |
77 | if (FunctionPA) { |
78 | InnerAM->invalidate(IR&: F, PA: *FunctionPA); |
79 | continue; |
80 | } |
81 | |
82 | // Otherwise we only need to do invalidation if the original PA set didn't |
83 | // preserve all function analyses. |
84 | if (!AreFunctionAnalysesPreserved) |
85 | InnerAM->invalidate(IR&: F, PA); |
86 | } |
87 | |
88 | // Return false to indicate that this result is still a valid proxy. |
89 | return false; |
90 | } |
91 | } // namespace llvm |
92 | |
93 | void ModuleToFunctionPassAdaptor::printPipeline( |
94 | raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) { |
95 | OS << "function" ; |
96 | if (EagerlyInvalidate) |
97 | OS << "<eager-inv>" ; |
98 | OS << '('; |
99 | Pass->printPipeline(OS, MapClassName2PassName); |
100 | OS << ')'; |
101 | } |
102 | |
103 | PreservedAnalyses ModuleToFunctionPassAdaptor::run(Module &M, |
104 | ModuleAnalysisManager &AM) { |
105 | FunctionAnalysisManager &FAM = |
106 | AM.getResult<FunctionAnalysisManagerModuleProxy>(IR&: M).getManager(); |
107 | |
108 | // Request PassInstrumentation from analysis manager, will use it to run |
109 | // instrumenting callbacks for the passes later. |
110 | PassInstrumentation PI = AM.getResult<PassInstrumentationAnalysis>(IR&: M); |
111 | |
112 | PreservedAnalyses PA = PreservedAnalyses::all(); |
113 | for (Function &F : M) { |
114 | if (F.isDeclaration()) |
115 | continue; |
116 | |
117 | // Check the PassInstrumentation's BeforePass callbacks before running the |
118 | // pass, skip its execution completely if asked to (callback returns |
119 | // false). |
120 | if (!PI.runBeforePass<Function>(Pass: *Pass, IR: F)) |
121 | continue; |
122 | |
123 | PreservedAnalyses PassPA = Pass->run(IR&: F, AM&: FAM); |
124 | |
125 | // We know that the function pass couldn't have invalidated any other |
126 | // function's analyses (that's the contract of a function pass), so |
127 | // directly handle the function analysis manager's invalidation here. |
128 | FAM.invalidate(IR&: F, PA: EagerlyInvalidate ? PreservedAnalyses::none() : PassPA); |
129 | |
130 | PI.runAfterPass(Pass: *Pass, IR: F, PA: PassPA); |
131 | |
132 | // Then intersect the preserved set so that invalidation of module |
133 | // analyses will eventually occur when the module pass completes. |
134 | PA.intersect(Arg: std::move(PassPA)); |
135 | } |
136 | |
137 | // The FunctionAnalysisManagerModuleProxy is preserved because (we assume) |
138 | // the function passes we ran didn't add or remove any functions. |
139 | // |
140 | // We also preserve all analyses on Functions, because we did all the |
141 | // invalidation we needed to do above. |
142 | PA.preserveSet<AllAnalysesOn<Function>>(); |
143 | PA.preserve<FunctionAnalysisManagerModuleProxy>(); |
144 | return PA; |
145 | } |
146 | |
147 | AnalysisSetKey CFGAnalyses::SetKey; |
148 | |
149 | AnalysisSetKey PreservedAnalyses::AllAnalysesKey; |
150 | |