1 //===- CGSCCPassManager.h - Call graph pass management ----------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 ///
11 /// This header provides classes for managing passes over SCCs of the call
12 /// graph. These passes form an important component of LLVM's interprocedural
13 /// optimizations. Because they operate on the SCCs of the call graph, and they
14 /// wtraverse the graph in post order, they can effectively do pair-wise
15 /// interprocedural optimizations for all call edges in the program. At each
16 /// call site edge, the callee has already been optimized as much as is
17 /// possible. This in turn allows very accurate analysis of it for IPO.
18 ///
19 //===----------------------------------------------------------------------===//
20
21 #ifndef LLVM_ANALYSIS_CGSCCPASSMANAGER_H
22 #define LLVM_ANALYSIS_CGSCCPASSMANAGER_H
23
24 #include "llvm/Analysis/LazyCallGraph.h"
25 #include "llvm/IR/PassManager.h"
26
27 namespace llvm {
28
29 /// \brief The CGSCC pass manager.
30 ///
31 /// See the documentation for the PassManager template for details. It runs
32 /// a sequency of SCC passes over each SCC that the manager is run over. This
33 /// typedef serves as a convenient way to refer to this construct.
34 typedef PassManager<LazyCallGraph::SCC> CGSCCPassManager;
35
36 /// \brief The CGSCC analysis manager.
37 ///
38 /// See the documentation for the AnalysisManager template for detail
39 /// documentation. This typedef serves as a convenient way to refer to this
40 /// construct in the adaptors and proxies used to integrate this into the larger
41 /// pass manager infrastructure.
42 typedef AnalysisManager<LazyCallGraph::SCC> CGSCCAnalysisManager;
43
44 /// \brief A module analysis which acts as a proxy for a CGSCC analysis
45 /// manager.
46 ///
47 /// This primarily proxies invalidation information from the module analysis
48 /// manager and module pass manager to a CGSCC analysis manager. You should
49 /// never use a CGSCC analysis manager from within (transitively) a module
50 /// pass manager unless your parent module pass has received a proxy result
51 /// object for it.
52 class CGSCCAnalysisManagerModuleProxy {
53 public:
54 class Result {
55 public:
Result(CGSCCAnalysisManager & CGAM)56 explicit Result(CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {}
57 // We have to explicitly define all the special member functions because
58 // MSVC refuses to generate them.
Result(const Result & Arg)59 Result(const Result &Arg) : CGAM(Arg.CGAM) {}
Result(Result && Arg)60 Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {}
61 Result &operator=(Result RHS) {
62 std::swap(CGAM, RHS.CGAM);
63 return *this;
64 }
65 ~Result();
66
67 /// \brief Accessor for the \c CGSCCAnalysisManager.
getManager()68 CGSCCAnalysisManager &getManager() { return *CGAM; }
69
70 /// \brief Handler for invalidation of the module.
71 ///
72 /// If this analysis itself is preserved, then we assume that the call
73 /// graph of the module hasn't changed and thus we don't need to invalidate
74 /// *all* cached data associated with a \c SCC* in the \c
75 /// CGSCCAnalysisManager.
76 ///
77 /// Regardless of whether this analysis is marked as preserved, all of the
78 /// analyses in the \c CGSCCAnalysisManager are potentially invalidated
79 /// based on the set of preserved analyses.
80 bool invalidate(Module &M, const PreservedAnalyses &PA);
81
82 private:
83 CGSCCAnalysisManager *CGAM;
84 };
85
ID()86 static void *ID() { return (void *)&PassID; }
87
name()88 static StringRef name() { return "CGSCCAnalysisManagerModuleProxy"; }
89
CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManager & CGAM)90 explicit CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManager &CGAM)
91 : CGAM(&CGAM) {}
92 // We have to explicitly define all the special member functions because MSVC
93 // refuses to generate them.
CGSCCAnalysisManagerModuleProxy(const CGSCCAnalysisManagerModuleProxy & Arg)94 CGSCCAnalysisManagerModuleProxy(const CGSCCAnalysisManagerModuleProxy &Arg)
95 : CGAM(Arg.CGAM) {}
CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManagerModuleProxy && Arg)96 CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManagerModuleProxy &&Arg)
97 : CGAM(std::move(Arg.CGAM)) {}
98 CGSCCAnalysisManagerModuleProxy &
99 operator=(CGSCCAnalysisManagerModuleProxy RHS) {
100 std::swap(CGAM, RHS.CGAM);
101 return *this;
102 }
103
104 /// \brief Run the analysis pass and create our proxy result object.
105 ///
106 /// This doesn't do any interesting work, it is primarily used to insert our
107 /// proxy result object into the module analysis cache so that we can proxy
108 /// invalidation to the CGSCC analysis manager.
109 ///
110 /// In debug builds, it will also assert that the analysis manager is empty
111 /// as no queries should arrive at the CGSCC analysis manager prior to
112 /// this analysis being requested.
113 Result run(Module &M);
114
115 private:
116 static char PassID;
117
118 CGSCCAnalysisManager *CGAM;
119 };
120
121 /// \brief A CGSCC analysis which acts as a proxy for a module analysis
122 /// manager.
123 ///
124 /// This primarily provides an accessor to a parent module analysis manager to
125 /// CGSCC passes. Only the const interface of the module analysis manager is
126 /// provided to indicate that once inside of a CGSCC analysis pass you
127 /// cannot request a module analysis to actually run. Instead, the user must
128 /// rely on the \c getCachedResult API.
129 ///
130 /// This proxy *doesn't* manage the invalidation in any way. That is handled by
131 /// the recursive return path of each layer of the pass manager and the
132 /// returned PreservedAnalysis set.
133 class ModuleAnalysisManagerCGSCCProxy {
134 public:
135 /// \brief Result proxy object for \c ModuleAnalysisManagerCGSCCProxy.
136 class Result {
137 public:
Result(const ModuleAnalysisManager & MAM)138 explicit Result(const ModuleAnalysisManager &MAM) : MAM(&MAM) {}
139 // We have to explicitly define all the special member functions because
140 // MSVC refuses to generate them.
Result(const Result & Arg)141 Result(const Result &Arg) : MAM(Arg.MAM) {}
Result(Result && Arg)142 Result(Result &&Arg) : MAM(std::move(Arg.MAM)) {}
143 Result &operator=(Result RHS) {
144 std::swap(MAM, RHS.MAM);
145 return *this;
146 }
147
getManager()148 const ModuleAnalysisManager &getManager() const { return *MAM; }
149
150 /// \brief Handle invalidation by ignoring it, this pass is immutable.
invalidate(LazyCallGraph::SCC &)151 bool invalidate(LazyCallGraph::SCC &) { return false; }
152
153 private:
154 const ModuleAnalysisManager *MAM;
155 };
156
ID()157 static void *ID() { return (void *)&PassID; }
158
name()159 static StringRef name() { return "ModuleAnalysisManagerCGSCCProxy"; }
160
ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManager & MAM)161 ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManager &MAM)
162 : MAM(&MAM) {}
163 // We have to explicitly define all the special member functions because MSVC
164 // refuses to generate them.
ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManagerCGSCCProxy & Arg)165 ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManagerCGSCCProxy &Arg)
166 : MAM(Arg.MAM) {}
ModuleAnalysisManagerCGSCCProxy(ModuleAnalysisManagerCGSCCProxy && Arg)167 ModuleAnalysisManagerCGSCCProxy(ModuleAnalysisManagerCGSCCProxy &&Arg)
168 : MAM(std::move(Arg.MAM)) {}
169 ModuleAnalysisManagerCGSCCProxy &
170 operator=(ModuleAnalysisManagerCGSCCProxy RHS) {
171 std::swap(MAM, RHS.MAM);
172 return *this;
173 }
174
175 /// \brief Run the analysis pass and create our proxy result object.
176 /// Nothing to see here, it just forwards the \c MAM reference into the
177 /// result.
run(LazyCallGraph::SCC &)178 Result run(LazyCallGraph::SCC &) { return Result(*MAM); }
179
180 private:
181 static char PassID;
182
183 const ModuleAnalysisManager *MAM;
184 };
185
186 /// \brief The core module pass which does a post-order walk of the SCCs and
187 /// runs a CGSCC pass over each one.
188 ///
189 /// Designed to allow composition of a CGSCCPass(Manager) and
190 /// a ModulePassManager. Note that this pass must be run with a module analysis
191 /// manager as it uses the LazyCallGraph analysis. It will also run the
192 /// \c CGSCCAnalysisManagerModuleProxy analysis prior to running the CGSCC
193 /// pass over the module to enable a \c FunctionAnalysisManager to be used
194 /// within this run safely.
195 template <typename CGSCCPassT> class ModuleToPostOrderCGSCCPassAdaptor {
196 public:
ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass)197 explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass)
198 : Pass(std::move(Pass)) {}
199 // We have to explicitly define all the special member functions because MSVC
200 // refuses to generate them.
ModuleToPostOrderCGSCCPassAdaptor(const ModuleToPostOrderCGSCCPassAdaptor & Arg)201 ModuleToPostOrderCGSCCPassAdaptor(
202 const ModuleToPostOrderCGSCCPassAdaptor &Arg)
203 : Pass(Arg.Pass) {}
ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor && Arg)204 ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor &&Arg)
205 : Pass(std::move(Arg.Pass)) {}
swap(ModuleToPostOrderCGSCCPassAdaptor & LHS,ModuleToPostOrderCGSCCPassAdaptor & RHS)206 friend void swap(ModuleToPostOrderCGSCCPassAdaptor &LHS,
207 ModuleToPostOrderCGSCCPassAdaptor &RHS) {
208 using std::swap;
209 swap(LHS.Pass, RHS.Pass);
210 }
211 ModuleToPostOrderCGSCCPassAdaptor &
212 operator=(ModuleToPostOrderCGSCCPassAdaptor RHS) {
213 swap(*this, RHS);
214 return *this;
215 }
216
217 /// \brief Runs the CGSCC pass across every SCC in the module.
run(Module & M,ModuleAnalysisManager * AM)218 PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) {
219 assert(AM && "We need analyses to compute the call graph!");
220
221 // Setup the CGSCC analysis manager from its proxy.
222 CGSCCAnalysisManager &CGAM =
223 AM->getResult<CGSCCAnalysisManagerModuleProxy>(M).getManager();
224
225 // Get the call graph for this module.
226 LazyCallGraph &CG = AM->getResult<LazyCallGraphAnalysis>(M);
227
228 PreservedAnalyses PA = PreservedAnalyses::all();
229 for (LazyCallGraph::SCC &C : CG.postorder_sccs()) {
230 PreservedAnalyses PassPA = Pass.run(C, &CGAM);
231
232 // We know that the CGSCC pass couldn't have invalidated any other
233 // SCC's analyses (that's the contract of a CGSCC pass), so
234 // directly handle the CGSCC analysis manager's invalidation here. We
235 // also update the preserved set of analyses to reflect that invalidated
236 // analyses are now safe to preserve.
237 // FIXME: This isn't quite correct. We need to handle the case where the
238 // pass updated the CG, particularly some child of the current SCC, and
239 // invalidate its analyses.
240 PassPA = CGAM.invalidate(C, std::move(PassPA));
241
242 // Then intersect the preserved set so that invalidation of module
243 // analyses will eventually occur when the module pass completes.
244 PA.intersect(std::move(PassPA));
245 }
246
247 // By definition we preserve the proxy. This precludes *any* invalidation
248 // of CGSCC analyses by the proxy, but that's OK because we've taken
249 // care to invalidate analyses in the CGSCC analysis manager
250 // incrementally above.
251 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
252 return PA;
253 }
254
name()255 static StringRef name() { return "ModuleToPostOrderCGSCCPassAdaptor"; }
256
257 private:
258 CGSCCPassT Pass;
259 };
260
261 /// \brief A function to deduce a function pass type and wrap it in the
262 /// templated adaptor.
263 template <typename CGSCCPassT>
264 ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>
createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass)265 createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) {
266 return ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass));
267 }
268
269 /// \brief A CGSCC analysis which acts as a proxy for a function analysis
270 /// manager.
271 ///
272 /// This primarily proxies invalidation information from the CGSCC analysis
273 /// manager and CGSCC pass manager to a function analysis manager. You should
274 /// never use a function analysis manager from within (transitively) a CGSCC
275 /// pass manager unless your parent CGSCC pass has received a proxy result
276 /// object for it.
277 class FunctionAnalysisManagerCGSCCProxy {
278 public:
279 class Result {
280 public:
Result(FunctionAnalysisManager & FAM)281 explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
282 // We have to explicitly define all the special member functions because
283 // MSVC refuses to generate them.
Result(const Result & Arg)284 Result(const Result &Arg) : FAM(Arg.FAM) {}
Result(Result && Arg)285 Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {}
286 Result &operator=(Result RHS) {
287 std::swap(FAM, RHS.FAM);
288 return *this;
289 }
290 ~Result();
291
292 /// \brief Accessor for the \c FunctionAnalysisManager.
getManager()293 FunctionAnalysisManager &getManager() { return *FAM; }
294
295 /// \brief Handler for invalidation of the SCC.
296 ///
297 /// If this analysis itself is preserved, then we assume that the set of \c
298 /// Function objects in the \c SCC hasn't changed and thus we don't need
299 /// to invalidate *all* cached data associated with a \c Function* in the \c
300 /// FunctionAnalysisManager.
301 ///
302 /// Regardless of whether this analysis is marked as preserved, all of the
303 /// analyses in the \c FunctionAnalysisManager are potentially invalidated
304 /// based on the set of preserved analyses.
305 bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA);
306
307 private:
308 FunctionAnalysisManager *FAM;
309 };
310
ID()311 static void *ID() { return (void *)&PassID; }
312
name()313 static StringRef name() { return "FunctionAnalysisManagerCGSCCProxy"; }
314
FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManager & FAM)315 explicit FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManager &FAM)
316 : FAM(&FAM) {}
317 // We have to explicitly define all the special member functions because MSVC
318 // refuses to generate them.
FunctionAnalysisManagerCGSCCProxy(const FunctionAnalysisManagerCGSCCProxy & Arg)319 FunctionAnalysisManagerCGSCCProxy(
320 const FunctionAnalysisManagerCGSCCProxy &Arg)
321 : FAM(Arg.FAM) {}
FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManagerCGSCCProxy && Arg)322 FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManagerCGSCCProxy &&Arg)
323 : FAM(std::move(Arg.FAM)) {}
324 FunctionAnalysisManagerCGSCCProxy &
325 operator=(FunctionAnalysisManagerCGSCCProxy RHS) {
326 std::swap(FAM, RHS.FAM);
327 return *this;
328 }
329
330 /// \brief Run the analysis pass and create our proxy result object.
331 ///
332 /// This doesn't do any interesting work, it is primarily used to insert our
333 /// proxy result object into the module analysis cache so that we can proxy
334 /// invalidation to the function analysis manager.
335 ///
336 /// In debug builds, it will also assert that the analysis manager is empty
337 /// as no queries should arrive at the function analysis manager prior to
338 /// this analysis being requested.
339 Result run(LazyCallGraph::SCC &C);
340
341 private:
342 static char PassID;
343
344 FunctionAnalysisManager *FAM;
345 };
346
347 /// \brief A function analysis which acts as a proxy for a CGSCC analysis
348 /// manager.
349 ///
350 /// This primarily provides an accessor to a parent CGSCC analysis manager to
351 /// function passes. Only the const interface of the CGSCC analysis manager is
352 /// provided to indicate that once inside of a function analysis pass you
353 /// cannot request a CGSCC analysis to actually run. Instead, the user must
354 /// rely on the \c getCachedResult API.
355 ///
356 /// This proxy *doesn't* manage the invalidation in any way. That is handled by
357 /// the recursive return path of each layer of the pass manager and the
358 /// returned PreservedAnalysis set.
359 class CGSCCAnalysisManagerFunctionProxy {
360 public:
361 /// \brief Result proxy object for \c CGSCCAnalysisManagerFunctionProxy.
362 class Result {
363 public:
Result(const CGSCCAnalysisManager & CGAM)364 explicit Result(const CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {}
365 // We have to explicitly define all the special member functions because
366 // MSVC refuses to generate them.
Result(const Result & Arg)367 Result(const Result &Arg) : CGAM(Arg.CGAM) {}
Result(Result && Arg)368 Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {}
369 Result &operator=(Result RHS) {
370 std::swap(CGAM, RHS.CGAM);
371 return *this;
372 }
373
getManager()374 const CGSCCAnalysisManager &getManager() const { return *CGAM; }
375
376 /// \brief Handle invalidation by ignoring it, this pass is immutable.
invalidate(Function &)377 bool invalidate(Function &) { return false; }
378
379 private:
380 const CGSCCAnalysisManager *CGAM;
381 };
382
ID()383 static void *ID() { return (void *)&PassID; }
384
name()385 static StringRef name() { return "CGSCCAnalysisManagerFunctionProxy"; }
386
CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManager & CGAM)387 CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManager &CGAM)
388 : CGAM(&CGAM) {}
389 // We have to explicitly define all the special member functions because MSVC
390 // refuses to generate them.
CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManagerFunctionProxy & Arg)391 CGSCCAnalysisManagerFunctionProxy(
392 const CGSCCAnalysisManagerFunctionProxy &Arg)
393 : CGAM(Arg.CGAM) {}
CGSCCAnalysisManagerFunctionProxy(CGSCCAnalysisManagerFunctionProxy && Arg)394 CGSCCAnalysisManagerFunctionProxy(CGSCCAnalysisManagerFunctionProxy &&Arg)
395 : CGAM(std::move(Arg.CGAM)) {}
396 CGSCCAnalysisManagerFunctionProxy &
397 operator=(CGSCCAnalysisManagerFunctionProxy RHS) {
398 std::swap(CGAM, RHS.CGAM);
399 return *this;
400 }
401
402 /// \brief Run the analysis pass and create our proxy result object.
403 /// Nothing to see here, it just forwards the \c CGAM reference into the
404 /// result.
run(Function &)405 Result run(Function &) { return Result(*CGAM); }
406
407 private:
408 static char PassID;
409
410 const CGSCCAnalysisManager *CGAM;
411 };
412
413 /// \brief Adaptor that maps from a SCC to its functions.
414 ///
415 /// Designed to allow composition of a FunctionPass(Manager) and
416 /// a CGSCCPassManager. Note that if this pass is constructed with a pointer
417 /// to a \c CGSCCAnalysisManager it will run the
418 /// \c FunctionAnalysisManagerCGSCCProxy analysis prior to running the function
419 /// pass over the SCC to enable a \c FunctionAnalysisManager to be used
420 /// within this run safely.
421 template <typename FunctionPassT> class CGSCCToFunctionPassAdaptor {
422 public:
CGSCCToFunctionPassAdaptor(FunctionPassT Pass)423 explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass)
424 : Pass(std::move(Pass)) {}
425 // We have to explicitly define all the special member functions because MSVC
426 // refuses to generate them.
CGSCCToFunctionPassAdaptor(const CGSCCToFunctionPassAdaptor & Arg)427 CGSCCToFunctionPassAdaptor(const CGSCCToFunctionPassAdaptor &Arg)
428 : Pass(Arg.Pass) {}
CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor && Arg)429 CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg)
430 : Pass(std::move(Arg.Pass)) {}
swap(CGSCCToFunctionPassAdaptor & LHS,CGSCCToFunctionPassAdaptor & RHS)431 friend void swap(CGSCCToFunctionPassAdaptor &LHS,
432 CGSCCToFunctionPassAdaptor &RHS) {
433 using std::swap;
434 swap(LHS.Pass, RHS.Pass);
435 }
436 CGSCCToFunctionPassAdaptor &operator=(CGSCCToFunctionPassAdaptor RHS) {
437 swap(*this, RHS);
438 return *this;
439 }
440
441 /// \brief Runs the function pass across every function in the module.
run(LazyCallGraph::SCC & C,CGSCCAnalysisManager * AM)442 PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager *AM) {
443 FunctionAnalysisManager *FAM = nullptr;
444 if (AM)
445 // Setup the function analysis manager from its proxy.
446 FAM = &AM->getResult<FunctionAnalysisManagerCGSCCProxy>(C).getManager();
447
448 PreservedAnalyses PA = PreservedAnalyses::all();
449 for (LazyCallGraph::Node *N : C) {
450 PreservedAnalyses PassPA = Pass.run(N->getFunction(), FAM);
451
452 // We know that the function pass couldn't have invalidated any other
453 // function's analyses (that's the contract of a function pass), so
454 // directly handle the function analysis manager's invalidation here.
455 // Also, update the preserved analyses to reflect that once invalidated
456 // these can again be preserved.
457 if (FAM)
458 PassPA = FAM->invalidate(N->getFunction(), std::move(PassPA));
459
460 // Then intersect the preserved set so that invalidation of module
461 // analyses will eventually occur when the module pass completes.
462 PA.intersect(std::move(PassPA));
463 }
464
465 // By definition we preserve the proxy. This precludes *any* invalidation
466 // of function analyses by the proxy, but that's OK because we've taken
467 // care to invalidate analyses in the function analysis manager
468 // incrementally above.
469 // FIXME: We need to update the call graph here to account for any deleted
470 // edges!
471 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
472 return PA;
473 }
474
name()475 static StringRef name() { return "CGSCCToFunctionPassAdaptor"; }
476
477 private:
478 FunctionPassT Pass;
479 };
480
481 /// \brief A function to deduce a function pass type and wrap it in the
482 /// templated adaptor.
483 template <typename FunctionPassT>
484 CGSCCToFunctionPassAdaptor<FunctionPassT>
createCGSCCToFunctionPassAdaptor(FunctionPassT Pass)485 createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) {
486 return CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass));
487 }
488 }
489
490 #endif
491