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