1 //===- CGSCCPassManager.h - Call graph pass management ----------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
19 //===----------------------------------------------------------------------===//
21 #ifndef LLVM_ANALYSIS_CGSCCPASSMANAGER_H
22 #define LLVM_ANALYSIS_CGSCCPASSMANAGER_H
24 #include "llvm/IR/PassManager.h"
25 #include "llvm/Analysis/LazyCallGraph.h"
29 /// \brief The CGSCC analysis manager.
31 /// See the documentation for the AnalysisManager template for detail
32 /// documentation. This typedef serves as a convenient way to refer to this
33 /// construct in the adaptors and proxies used to integrate this into the larger
34 /// pass manager infrastructure.
35 typedef AnalysisManager<LazyCallGraph::SCC> CGSCCAnalysisManager;
37 class CGSCCPassManager {
39 // We have to explicitly define all the special member functions because MSVC
40 // refuses to generate them.
42 CGSCCPassManager(CGSCCPassManager &&Arg) : Passes(std::move(Arg.Passes)) {}
43 CGSCCPassManager &operator=(CGSCCPassManager &&RHS) {
44 Passes = std::move(RHS.Passes);
48 /// \brief Run all of the CGSCC passes in this pass manager over a SCC.
49 PreservedAnalyses run(LazyCallGraph::SCC &C,
50 CGSCCAnalysisManager *AM = nullptr);
52 template <typename CGSCCPassT> void addPass(CGSCCPassT Pass) {
53 Passes.emplace_back(new CGSCCPassModel<CGSCCPassT>(std::move(Pass)));
56 static StringRef name() { return "CGSCCPassManager"; }
59 // Pull in the concept type and model template specialized for SCCs.
60 typedef detail::PassConcept<LazyCallGraph::SCC, CGSCCAnalysisManager>
62 template <typename PassT>
64 : detail::PassModel<LazyCallGraph::SCC, CGSCCAnalysisManager, PassT> {
65 CGSCCPassModel(PassT Pass)
66 : detail::PassModel<LazyCallGraph::SCC, CGSCCAnalysisManager, PassT>(
70 CGSCCPassManager(const CGSCCPassManager &) LLVM_DELETED_FUNCTION;
71 CGSCCPassManager &operator=(const CGSCCPassManager &) LLVM_DELETED_FUNCTION;
73 std::vector<std::unique_ptr<CGSCCPassConcept>> Passes;
76 /// \brief A module analysis which acts as a proxy for a CGSCC analysis
79 /// This primarily proxies invalidation information from the module analysis
80 /// manager and module pass manager to a CGSCC analysis manager. You should
81 /// never use a CGSCC analysis manager from within (transitively) a module
82 /// pass manager unless your parent module pass has received a proxy result
84 class CGSCCAnalysisManagerModuleProxy {
88 explicit Result(CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {}
89 // We have to explicitly define all the special member functions because
90 // MSVC refuses to generate them.
91 Result(const Result &Arg) : CGAM(Arg.CGAM) {}
92 Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {}
93 Result &operator=(Result RHS) {
94 std::swap(CGAM, RHS.CGAM);
99 /// \brief Accessor for the \c CGSCCAnalysisManager.
100 CGSCCAnalysisManager &getManager() { return *CGAM; }
102 /// \brief Handler for invalidation of the module.
104 /// If this analysis itself is preserved, then we assume that the call
105 /// graph of the module hasn't changed and thus we don't need to invalidate
106 /// *all* cached data associated with a \c SCC* in the \c
107 /// CGSCCAnalysisManager.
109 /// Regardless of whether this analysis is marked as preserved, all of the
110 /// analyses in the \c CGSCCAnalysisManager are potentially invalidated
111 /// based on the set of preserved analyses.
112 bool invalidate(Module &M, const PreservedAnalyses &PA);
115 CGSCCAnalysisManager *CGAM;
118 static void *ID() { return (void *)&PassID; }
120 static StringRef name() { return "CGSCCAnalysisManagerModuleProxy"; }
122 explicit CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManager &CGAM)
124 // We have to explicitly define all the special member functions because MSVC
125 // refuses to generate them.
126 CGSCCAnalysisManagerModuleProxy(const CGSCCAnalysisManagerModuleProxy &Arg)
128 CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManagerModuleProxy &&Arg)
129 : CGAM(std::move(Arg.CGAM)) {}
130 CGSCCAnalysisManagerModuleProxy &
131 operator=(CGSCCAnalysisManagerModuleProxy RHS) {
132 std::swap(CGAM, RHS.CGAM);
136 /// \brief Run the analysis pass and create our proxy result object.
138 /// This doesn't do any interesting work, it is primarily used to insert our
139 /// proxy result object into the module analysis cache so that we can proxy
140 /// invalidation to the CGSCC analysis manager.
142 /// In debug builds, it will also assert that the analysis manager is empty
143 /// as no queries should arrive at the CGSCC analysis manager prior to
144 /// this analysis being requested.
145 Result run(Module &M);
150 CGSCCAnalysisManager *CGAM;
153 /// \brief A CGSCC analysis which acts as a proxy for a module analysis
156 /// This primarily provides an accessor to a parent module analysis manager to
157 /// CGSCC passes. Only the const interface of the module analysis manager is
158 /// provided to indicate that once inside of a CGSCC analysis pass you
159 /// cannot request a module analysis to actually run. Instead, the user must
160 /// rely on the \c getCachedResult API.
162 /// This proxy *doesn't* manage the invalidation in any way. That is handled by
163 /// the recursive return path of each layer of the pass manager and the
164 /// returned PreservedAnalysis set.
165 class ModuleAnalysisManagerCGSCCProxy {
167 /// \brief Result proxy object for \c ModuleAnalysisManagerCGSCCProxy.
170 explicit Result(const ModuleAnalysisManager &MAM) : MAM(&MAM) {}
171 // We have to explicitly define all the special member functions because
172 // MSVC refuses to generate them.
173 Result(const Result &Arg) : MAM(Arg.MAM) {}
174 Result(Result &&Arg) : MAM(std::move(Arg.MAM)) {}
175 Result &operator=(Result RHS) {
176 std::swap(MAM, RHS.MAM);
180 const ModuleAnalysisManager &getManager() const { return *MAM; }
182 /// \brief Handle invalidation by ignoring it, this pass is immutable.
183 bool invalidate(LazyCallGraph::SCC &) { return false; }
186 const ModuleAnalysisManager *MAM;
189 static void *ID() { return (void *)&PassID; }
191 static StringRef name() { return "ModuleAnalysisManagerCGSCCProxy"; }
193 ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManager &MAM)
195 // We have to explicitly define all the special member functions because MSVC
196 // refuses to generate them.
197 ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManagerCGSCCProxy &Arg)
199 ModuleAnalysisManagerCGSCCProxy(ModuleAnalysisManagerCGSCCProxy &&Arg)
200 : MAM(std::move(Arg.MAM)) {}
201 ModuleAnalysisManagerCGSCCProxy &
202 operator=(ModuleAnalysisManagerCGSCCProxy RHS) {
203 std::swap(MAM, RHS.MAM);
207 /// \brief Run the analysis pass and create our proxy result object.
208 /// Nothing to see here, it just forwards the \c MAM reference into the
210 Result run(LazyCallGraph::SCC &) { return Result(*MAM); }
215 const ModuleAnalysisManager *MAM;
218 /// \brief The core module pass which does a post-order walk of the SCCs and
219 /// runs a CGSCC pass over each one.
221 /// Designed to allow composition of a CGSCCPass(Manager) and
222 /// a ModulePassManager. Note that this pass must be run with a module analysis
223 /// manager as it uses the LazyCallGraph analysis. It will also run the
224 /// \c CGSCCAnalysisManagerModuleProxy analysis prior to running the CGSCC
225 /// pass over the module to enable a \c FunctionAnalysisManager to be used
226 /// within this run safely.
227 template <typename CGSCCPassT> class ModuleToPostOrderCGSCCPassAdaptor {
229 explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass)
230 : Pass(std::move(Pass)) {}
231 // We have to explicitly define all the special member functions because MSVC
232 // refuses to generate them.
233 ModuleToPostOrderCGSCCPassAdaptor(
234 const ModuleToPostOrderCGSCCPassAdaptor &Arg)
236 ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor &&Arg)
237 : Pass(std::move(Arg.Pass)) {}
238 friend void swap(ModuleToPostOrderCGSCCPassAdaptor &LHS,
239 ModuleToPostOrderCGSCCPassAdaptor &RHS) {
241 swap(LHS.Pass, RHS.Pass);
243 ModuleToPostOrderCGSCCPassAdaptor &
244 operator=(ModuleToPostOrderCGSCCPassAdaptor RHS) {
249 /// \brief Runs the CGSCC pass across every SCC in the module.
250 PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) {
251 assert(AM && "We need analyses to compute the call graph!");
253 // Setup the CGSCC analysis manager from its proxy.
254 CGSCCAnalysisManager &CGAM =
255 AM->getResult<CGSCCAnalysisManagerModuleProxy>(M).getManager();
257 // Get the call graph for this module.
258 LazyCallGraph &CG = AM->getResult<LazyCallGraphAnalysis>(M);
260 PreservedAnalyses PA = PreservedAnalyses::all();
261 for (LazyCallGraph::SCC &C : CG.postorder_sccs()) {
262 PreservedAnalyses PassPA = Pass.run(C, &CGAM);
264 // We know that the CGSCC pass couldn't have invalidated any other
265 // SCC's analyses (that's the contract of a CGSCC pass), so
266 // directly handle the CGSCC analysis manager's invalidation here. We
267 // also update the preserved set of analyses to reflect that invalidated
268 // analyses are now safe to preserve.
269 // FIXME: This isn't quite correct. We need to handle the case where the
270 // pass updated the CG, particularly some child of the current SCC, and
271 // invalidate its analyses.
272 PassPA = CGAM.invalidate(C, std::move(PassPA));
274 // Then intersect the preserved set so that invalidation of module
275 // analyses will eventually occur when the module pass completes.
276 PA.intersect(std::move(PassPA));
279 // By definition we preserve the proxy. This precludes *any* invalidation
280 // of CGSCC analyses by the proxy, but that's OK because we've taken
281 // care to invalidate analyses in the CGSCC analysis manager
282 // incrementally above.
283 PA.preserve<CGSCCAnalysisManagerModuleProxy>();
287 static StringRef name() { return "ModuleToPostOrderCGSCCPassAdaptor"; }
293 /// \brief A function to deduce a function pass type and wrap it in the
294 /// templated adaptor.
295 template <typename CGSCCPassT>
296 ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>
297 createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) {
299 ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass)));
302 /// \brief A CGSCC analysis which acts as a proxy for a function analysis
305 /// This primarily proxies invalidation information from the CGSCC analysis
306 /// manager and CGSCC pass manager to a function analysis manager. You should
307 /// never use a function analysis manager from within (transitively) a CGSCC
308 /// pass manager unless your parent CGSCC pass has received a proxy result
310 class FunctionAnalysisManagerCGSCCProxy {
314 explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
315 // We have to explicitly define all the special member functions because
316 // MSVC refuses to generate them.
317 Result(const Result &Arg) : FAM(Arg.FAM) {}
318 Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {}
319 Result &operator=(Result RHS) {
320 std::swap(FAM, RHS.FAM);
325 /// \brief Accessor for the \c FunctionAnalysisManager.
326 FunctionAnalysisManager &getManager() { return *FAM; }
328 /// \brief Handler for invalidation of the SCC.
330 /// If this analysis itself is preserved, then we assume that the set of \c
331 /// Function objects in the \c SCC hasn't changed and thus we don't need
332 /// to invalidate *all* cached data associated with a \c Function* in the \c
333 /// FunctionAnalysisManager.
335 /// Regardless of whether this analysis is marked as preserved, all of the
336 /// analyses in the \c FunctionAnalysisManager are potentially invalidated
337 /// based on the set of preserved analyses.
338 bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA);
341 FunctionAnalysisManager *FAM;
344 static void *ID() { return (void *)&PassID; }
346 static StringRef name() { return "FunctionAnalysisManagerCGSCCProxy"; }
348 explicit FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManager &FAM)
350 // We have to explicitly define all the special member functions because MSVC
351 // refuses to generate them.
352 FunctionAnalysisManagerCGSCCProxy(
353 const FunctionAnalysisManagerCGSCCProxy &Arg)
355 FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManagerCGSCCProxy &&Arg)
356 : FAM(std::move(Arg.FAM)) {}
357 FunctionAnalysisManagerCGSCCProxy &
358 operator=(FunctionAnalysisManagerCGSCCProxy RHS) {
359 std::swap(FAM, RHS.FAM);
363 /// \brief Run the analysis pass and create our proxy result object.
365 /// This doesn't do any interesting work, it is primarily used to insert our
366 /// proxy result object into the module analysis cache so that we can proxy
367 /// invalidation to the function analysis manager.
369 /// In debug builds, it will also assert that the analysis manager is empty
370 /// as no queries should arrive at the function analysis manager prior to
371 /// this analysis being requested.
372 Result run(LazyCallGraph::SCC &C);
377 FunctionAnalysisManager *FAM;
380 /// \brief A function analysis which acts as a proxy for a CGSCC analysis
383 /// This primarily provides an accessor to a parent CGSCC analysis manager to
384 /// function passes. Only the const interface of the CGSCC analysis manager is
385 /// provided to indicate that once inside of a function analysis pass you
386 /// cannot request a CGSCC analysis to actually run. Instead, the user must
387 /// rely on the \c getCachedResult API.
389 /// This proxy *doesn't* manage the invalidation in any way. That is handled by
390 /// the recursive return path of each layer of the pass manager and the
391 /// returned PreservedAnalysis set.
392 class CGSCCAnalysisManagerFunctionProxy {
394 /// \brief Result proxy object for \c ModuleAnalysisManagerFunctionProxy.
397 explicit Result(const CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {}
398 // We have to explicitly define all the special member functions because
399 // MSVC refuses to generate them.
400 Result(const Result &Arg) : CGAM(Arg.CGAM) {}
401 Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {}
402 Result &operator=(Result RHS) {
403 std::swap(CGAM, RHS.CGAM);
407 const CGSCCAnalysisManager &getManager() const { return *CGAM; }
409 /// \brief Handle invalidation by ignoring it, this pass is immutable.
410 bool invalidate(Function &) { return false; }
413 const CGSCCAnalysisManager *CGAM;
416 static void *ID() { return (void *)&PassID; }
418 static StringRef name() { return "CGSCCAnalysisManagerFunctionProxy"; }
420 CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManager &CGAM)
422 // We have to explicitly define all the special member functions because MSVC
423 // refuses to generate them.
424 CGSCCAnalysisManagerFunctionProxy(
425 const CGSCCAnalysisManagerFunctionProxy &Arg)
427 CGSCCAnalysisManagerFunctionProxy(CGSCCAnalysisManagerFunctionProxy &&Arg)
428 : CGAM(std::move(Arg.CGAM)) {}
429 CGSCCAnalysisManagerFunctionProxy &
430 operator=(CGSCCAnalysisManagerFunctionProxy RHS) {
431 std::swap(CGAM, RHS.CGAM);
435 /// \brief Run the analysis pass and create our proxy result object.
436 /// Nothing to see here, it just forwards the \c CGAM reference into the
438 Result run(Function &) { return Result(*CGAM); }
443 const CGSCCAnalysisManager *CGAM;
446 /// \brief Adaptor that maps from a SCC to its functions.
448 /// Designed to allow composition of a FunctionPass(Manager) and
449 /// a CGSCCPassManager. Note that if this pass is constructed with a pointer
450 /// to a \c CGSCCAnalysisManager it will run the
451 /// \c FunctionAnalysisManagerCGSCCProxy analysis prior to running the function
452 /// pass over the SCC to enable a \c FunctionAnalysisManager to be used
453 /// within this run safely.
454 template <typename FunctionPassT> class CGSCCToFunctionPassAdaptor {
456 explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass)
457 : Pass(std::move(Pass)) {}
458 // We have to explicitly define all the special member functions because MSVC
459 // refuses to generate them.
460 CGSCCToFunctionPassAdaptor(const CGSCCToFunctionPassAdaptor &Arg)
462 CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg)
463 : Pass(std::move(Arg.Pass)) {}
464 friend void swap(CGSCCToFunctionPassAdaptor &LHS,
465 CGSCCToFunctionPassAdaptor &RHS) {
467 swap(LHS.Pass, RHS.Pass);
469 CGSCCToFunctionPassAdaptor &operator=(CGSCCToFunctionPassAdaptor RHS) {
474 /// \brief Runs the function pass across every function in the module.
475 PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager *AM) {
476 FunctionAnalysisManager *FAM = nullptr;
478 // Setup the function analysis manager from its proxy.
479 FAM = &AM->getResult<FunctionAnalysisManagerCGSCCProxy>(C).getManager();
481 PreservedAnalyses PA = PreservedAnalyses::all();
482 for (LazyCallGraph::Node *N : C) {
483 PreservedAnalyses PassPA = Pass.run(N->getFunction(), FAM);
485 // We know that the function pass couldn't have invalidated any other
486 // function's analyses (that's the contract of a function pass), so
487 // directly handle the function analysis manager's invalidation here.
488 // Also, update the preserved analyses to reflect that once invalidated
489 // these can again be preserved.
491 PassPA = FAM->invalidate(N->getFunction(), std::move(PassPA));
493 // Then intersect the preserved set so that invalidation of module
494 // analyses will eventually occur when the module pass completes.
495 PA.intersect(std::move(PassPA));
498 // By definition we preserve the proxy. This precludes *any* invalidation
499 // of function analyses by the proxy, but that's OK because we've taken
500 // care to invalidate analyses in the function analysis manager
501 // incrementally above.
502 // FIXME: We need to update the call graph here to account for any deleted
504 PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
508 static StringRef name() { return "CGSCCToFunctionPassAdaptor"; }
514 /// \brief A function to deduce a function pass type and wrap it in the
515 /// templated adaptor.
516 template <typename FunctionPassT>
517 CGSCCToFunctionPassAdaptor<FunctionPassT>
518 createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) {
519 return std::move(CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass)));