1 //===- PassManagerImpl.h - Pass management infrastructure -------*- C++ -*-===//
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 /// \file
9 /// Provides implementations for PassManager and AnalysisManager template
10 /// methods. These classes should be explicitly instantiated for any IR unit,
11 /// and files doing the explicit instantiation should include this header.
12 ///
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_IR_PASSMANAGERIMPL_H
16 #define LLVM_IR_PASSMANAGERIMPL_H
17
18 #include "llvm/IR/Function.h"
19 #include "llvm/IR/PassInstrumentation.h"
20 #include "llvm/IR/PassManager.h"
21 #include "llvm/Support/CommandLine.h"
22 #include "llvm/Support/PrettyStackTrace.h"
23
24 extern llvm::cl::opt<bool> UseNewDbgInfoFormat;
25
26 namespace llvm {
27
28 template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
run(IRUnitT & IR,AnalysisManagerT & AM,ExtraArgTs...ExtraArgs)29 PreservedAnalyses PassManager<IRUnitT, AnalysisManagerT, ExtraArgTs...>::run(
30 IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs) {
31 class StackTraceEntry : public PrettyStackTraceEntry {
32 const PassInstrumentation &PI;
33 IRUnitT &IR;
34 PassConceptT *Pass = nullptr;
35
36 public:
37 explicit StackTraceEntry(const PassInstrumentation &PI, IRUnitT &IR)
38 : PI(PI), IR(IR) {}
39
40 void setPass(PassConceptT *P) { Pass = P; }
41
42 void print(raw_ostream &OS) const override {
43 OS << "Running pass \"";
44 if (Pass)
45 Pass->printPipeline(OS, [this](StringRef ClassName) {
46 auto PassName = PI.getPassNameForClassName(ClassName);
47 return PassName.empty() ? ClassName : PassName;
48 });
49 else
50 OS << "unknown";
51 OS << "\" on ";
52 printIRUnitNameForStackTrace(OS, IR);
53 OS << "\n";
54 }
55 };
56
57 PreservedAnalyses PA = PreservedAnalyses::all();
58
59 // Request PassInstrumentation from analysis manager, will use it to run
60 // instrumenting callbacks for the passes later.
61 // Here we use std::tuple wrapper over getResult which helps to extract
62 // AnalysisManager's arguments out of the whole ExtraArgs set.
63 PassInstrumentation PI =
64 detail::getAnalysisResult<PassInstrumentationAnalysis>(
65 AM, IR, std::tuple<ExtraArgTs...>(ExtraArgs...));
66
67 // RemoveDIs: if requested, convert debug-info to DbgRecord representation
68 // for duration of these passes.
69 ScopedDbgInfoFormatSetter FormatSetter(IR, UseNewDbgInfoFormat);
70
71 StackTraceEntry Entry(PI, IR);
72 for (auto &Pass : Passes) {
73 Entry.setPass(&*Pass);
74
75 // Check the PassInstrumentation's BeforePass callbacks before running the
76 // pass, skip its execution completely if asked to (callback returns
77 // false).
78 if (!PI.runBeforePass<IRUnitT>(*Pass, IR))
79 continue;
80
81 PreservedAnalyses PassPA = Pass->run(IR, AM, ExtraArgs...);
82
83 // Update the analysis manager as each pass runs and potentially
84 // invalidates analyses.
85 AM.invalidate(IR, PassPA);
86
87 // Call onto PassInstrumentation's AfterPass callbacks immediately after
88 // running the pass.
89 PI.runAfterPass<IRUnitT>(*Pass, IR, PassPA);
90
91 // Finally, intersect the preserved analyses to compute the aggregate
92 // preserved set for this pass manager.
93 PA.intersect(std::move(PassPA));
94 }
95
96 // Invalidation was handled after each pass in the above loop for the
97 // current unit of IR. Therefore, the remaining analysis results in the
98 // AnalysisManager are preserved. We mark this with a set so that we don't
99 // need to inspect each one individually.
100 PA.preserveSet<AllAnalysesOn<IRUnitT>>();
101
102 return PA;
103 }
104
105 template <typename IRUnitT, typename... ExtraArgTs>
106 inline AnalysisManager<IRUnitT, ExtraArgTs...>::AnalysisManager() = default;
107
108 template <typename IRUnitT, typename... ExtraArgTs>
109 inline AnalysisManager<IRUnitT, ExtraArgTs...>::AnalysisManager(
110 AnalysisManager &&) = default;
111
112 template <typename IRUnitT, typename... ExtraArgTs>
113 inline AnalysisManager<IRUnitT, ExtraArgTs...> &
114 AnalysisManager<IRUnitT, ExtraArgTs...>::operator=(AnalysisManager &&) =
115 default;
116
117 template <typename IRUnitT, typename... ExtraArgTs>
118 inline void
clear(IRUnitT & IR,llvm::StringRef Name)119 AnalysisManager<IRUnitT, ExtraArgTs...>::clear(IRUnitT &IR,
120 llvm::StringRef Name) {
121 if (auto *PI = getCachedResult<PassInstrumentationAnalysis>(IR))
122 PI->runAnalysesCleared(Name);
123
124 auto ResultsListI = AnalysisResultLists.find(&IR);
125 if (ResultsListI == AnalysisResultLists.end())
126 return;
127 // Delete the map entries that point into the results list.
128 for (auto &IDAndResult : ResultsListI->second)
129 AnalysisResults.erase({IDAndResult.first, &IR});
130
131 // And actually destroy and erase the results associated with this IR.
132 AnalysisResultLists.erase(ResultsListI);
133 }
134
135 template <typename IRUnitT, typename... ExtraArgTs>
136 inline typename AnalysisManager<IRUnitT, ExtraArgTs...>::ResultConceptT &
getResultImpl(AnalysisKey * ID,IRUnitT & IR,ExtraArgTs...ExtraArgs)137 AnalysisManager<IRUnitT, ExtraArgTs...>::getResultImpl(
138 AnalysisKey *ID, IRUnitT &IR, ExtraArgTs... ExtraArgs) {
139 typename AnalysisResultMapT::iterator RI;
140 bool Inserted;
141 std::tie(RI, Inserted) = AnalysisResults.insert(std::make_pair(
142 std::make_pair(ID, &IR), typename AnalysisResultListT::iterator()));
143
144 // If we don't have a cached result for this function, look up the pass and
145 // run it to produce a result, which we then add to the cache.
146 if (Inserted) {
147 auto &P = this->lookUpPass(ID);
148
149 PassInstrumentation PI;
150 if (ID != PassInstrumentationAnalysis::ID()) {
151 PI = getResult<PassInstrumentationAnalysis>(IR, ExtraArgs...);
152 PI.runBeforeAnalysis(P, IR);
153 }
154
155 AnalysisResultListT &ResultList = AnalysisResultLists[&IR];
156 ResultList.emplace_back(ID, P.run(IR, *this, ExtraArgs...));
157
158 PI.runAfterAnalysis(P, IR);
159
160 // P.run may have inserted elements into AnalysisResults and invalidated
161 // RI.
162 RI = AnalysisResults.find({ID, &IR});
163 assert(RI != AnalysisResults.end() && "we just inserted it!");
164
165 RI->second = std::prev(ResultList.end());
166 }
167
168 return *RI->second->second;
169 }
170
171 template <typename IRUnitT, typename... ExtraArgTs>
invalidate(IRUnitT & IR,const PreservedAnalyses & PA)172 inline void AnalysisManager<IRUnitT, ExtraArgTs...>::invalidate(
173 IRUnitT &IR, const PreservedAnalyses &PA) {
174 // We're done if all analyses on this IR unit are preserved.
175 if (PA.allAnalysesInSetPreserved<AllAnalysesOn<IRUnitT>>())
176 return;
177
178 // Track whether each analysis's result is invalidated in
179 // IsResultInvalidated.
180 SmallDenseMap<AnalysisKey *, bool, 8> IsResultInvalidated;
181 Invalidator Inv(IsResultInvalidated, AnalysisResults);
182 AnalysisResultListT &ResultsList = AnalysisResultLists[&IR];
183 for (auto &AnalysisResultPair : ResultsList) {
184 // This is basically the same thing as Invalidator::invalidate, but we
185 // can't call it here because we're operating on the type-erased result.
186 // Moreover if we instead called invalidate() directly, it would do an
187 // unnecessary look up in ResultsList.
188 AnalysisKey *ID = AnalysisResultPair.first;
189 auto &Result = *AnalysisResultPair.second;
190
191 auto IMapI = IsResultInvalidated.find(ID);
192 if (IMapI != IsResultInvalidated.end())
193 // This result was already handled via the Invalidator.
194 continue;
195
196 // Try to invalidate the result, giving it the Invalidator so it can
197 // recursively query for any dependencies it has and record the result.
198 // Note that we cannot reuse 'IMapI' here or pre-insert the ID, as
199 // Result.invalidate may insert things into the map, invalidating our
200 // iterator.
201 bool Inserted =
202 IsResultInvalidated.insert({ID, Result.invalidate(IR, PA, Inv)}).second;
203 (void)Inserted;
204 assert(Inserted && "Should never have already inserted this ID, likely "
205 "indicates a cycle!");
206 }
207
208 // Now erase the results that were marked above as invalidated.
209 if (!IsResultInvalidated.empty()) {
210 for (auto I = ResultsList.begin(), E = ResultsList.end(); I != E;) {
211 AnalysisKey *ID = I->first;
212 if (!IsResultInvalidated.lookup(ID)) {
213 ++I;
214 continue;
215 }
216
217 if (auto *PI = getCachedResult<PassInstrumentationAnalysis>(IR))
218 PI->runAnalysisInvalidated(this->lookUpPass(ID), IR);
219
220 I = ResultsList.erase(I);
221 AnalysisResults.erase({ID, &IR});
222 }
223 }
224
225 if (ResultsList.empty())
226 AnalysisResultLists.erase(&IR);
227 }
228 } // end namespace llvm
229
230 #endif // LLVM_IR_PASSMANAGERIMPL_H
231