• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_CGSCC_PASS_MANAGER_H
22 #define LLVM_ANALYSIS_CGSCC_PASS_MANAGER_H
23 
24 #include "llvm/IR/PassManager.h"
25 #include "llvm/Analysis/LazyCallGraph.h"
26 
27 namespace llvm {
28 
29 class CGSCCAnalysisManager;
30 
31 class CGSCCPassManager {
32 public:
33   // We have to explicitly define all the special member functions because MSVC
34   // refuses to generate them.
CGSCCPassManager()35   CGSCCPassManager() {}
CGSCCPassManager(CGSCCPassManager && Arg)36   CGSCCPassManager(CGSCCPassManager &&Arg) : Passes(std::move(Arg.Passes)) {}
37   CGSCCPassManager &operator=(CGSCCPassManager &&RHS) {
38     Passes = std::move(RHS.Passes);
39     return *this;
40   }
41 
42   /// \brief Run all of the CGSCC passes in this pass manager over a SCC.
43   PreservedAnalyses run(LazyCallGraph::SCC *C,
44                         CGSCCAnalysisManager *AM = nullptr);
45 
addPass(CGSCCPassT Pass)46   template <typename CGSCCPassT> void addPass(CGSCCPassT Pass) {
47     Passes.emplace_back(new CGSCCPassModel<CGSCCPassT>(std::move(Pass)));
48   }
49 
name()50   static StringRef name() { return "CGSCCPassManager"; }
51 
52 private:
53   // Pull in the concept type and model template specialized for SCCs.
54   typedef detail::PassConcept<LazyCallGraph::SCC *, CGSCCAnalysisManager>
55   CGSCCPassConcept;
56   template <typename PassT>
57   struct CGSCCPassModel
58       : detail::PassModel<LazyCallGraph::SCC *, CGSCCAnalysisManager, PassT> {
CGSCCPassModelCGSCCPassModel59     CGSCCPassModel(PassT Pass)
60         : detail::PassModel<LazyCallGraph::SCC *, CGSCCAnalysisManager, PassT>(
61               std::move(Pass)) {}
62   };
63 
64   CGSCCPassManager(const CGSCCPassManager &) LLVM_DELETED_FUNCTION;
65   CGSCCPassManager &operator=(const CGSCCPassManager &) LLVM_DELETED_FUNCTION;
66 
67   std::vector<std::unique_ptr<CGSCCPassConcept>> Passes;
68 };
69 
70 /// \brief A function analysis manager to coordinate and cache analyses run over
71 /// a module.
72 class CGSCCAnalysisManager : public detail::AnalysisManagerBase<
73                                  CGSCCAnalysisManager, LazyCallGraph::SCC *> {
74   friend class detail::AnalysisManagerBase<CGSCCAnalysisManager,
75                                            LazyCallGraph::SCC *>;
76   typedef detail::AnalysisManagerBase<CGSCCAnalysisManager,
77                                       LazyCallGraph::SCC *> BaseT;
78   typedef BaseT::ResultConceptT ResultConceptT;
79   typedef BaseT::PassConceptT PassConceptT;
80 
81 public:
82   // Most public APIs are inherited from the CRTP base class.
83 
84   // We have to explicitly define all the special member functions because MSVC
85   // refuses to generate them.
CGSCCAnalysisManager()86   CGSCCAnalysisManager() {}
CGSCCAnalysisManager(CGSCCAnalysisManager && Arg)87   CGSCCAnalysisManager(CGSCCAnalysisManager &&Arg)
88       : BaseT(std::move(static_cast<BaseT &>(Arg))),
89         CGSCCAnalysisResults(std::move(Arg.CGSCCAnalysisResults)) {}
90   CGSCCAnalysisManager &operator=(CGSCCAnalysisManager &&RHS) {
91     BaseT::operator=(std::move(static_cast<BaseT &>(RHS)));
92     CGSCCAnalysisResults = std::move(RHS.CGSCCAnalysisResults);
93     return *this;
94   }
95 
96   /// \brief Returns true if the analysis manager has an empty results cache.
97   bool empty() const;
98 
99   /// \brief Clear the function analysis result cache.
100   ///
101   /// This routine allows cleaning up when the set of functions itself has
102   /// potentially changed, and thus we can't even look up a a result and
103   /// invalidate it directly. Notably, this does *not* call invalidate
104   /// functions as there is nothing to be done for them.
105   void clear();
106 
107 private:
108   CGSCCAnalysisManager(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION;
109   CGSCCAnalysisManager &
110   operator=(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION;
111 
112   /// \brief Get a function pass result, running the pass if necessary.
113   ResultConceptT &getResultImpl(void *PassID, LazyCallGraph::SCC *C);
114 
115   /// \brief Get a cached function pass result or return null.
116   ResultConceptT *getCachedResultImpl(void *PassID,
117                                       LazyCallGraph::SCC *C) const;
118 
119   /// \brief Invalidate a function pass result.
120   void invalidateImpl(void *PassID, LazyCallGraph::SCC *C);
121 
122   /// \brief Invalidate the results for a function..
123   void invalidateImpl(LazyCallGraph::SCC *C, const PreservedAnalyses &PA);
124 
125   /// \brief List of function analysis pass IDs and associated concept pointers.
126   ///
127   /// Requires iterators to be valid across appending new entries and arbitrary
128   /// erases. Provides both the pass ID and concept pointer such that it is
129   /// half of a bijection and provides storage for the actual result concept.
130   typedef std::list<
131       std::pair<void *, std::unique_ptr<detail::AnalysisResultConcept<
132                             LazyCallGraph::SCC *>>>> CGSCCAnalysisResultListT;
133 
134   /// \brief Map type from function pointer to our custom list type.
135   typedef DenseMap<LazyCallGraph::SCC *, CGSCCAnalysisResultListT>
136   CGSCCAnalysisResultListMapT;
137 
138   /// \brief Map from function to a list of function analysis results.
139   ///
140   /// Provides linear time removal of all analysis results for a function and
141   /// the ultimate storage for a particular cached analysis result.
142   CGSCCAnalysisResultListMapT CGSCCAnalysisResultLists;
143 
144   /// \brief Map type from a pair of analysis ID and function pointer to an
145   /// iterator into a particular result list.
146   typedef DenseMap<std::pair<void *, LazyCallGraph::SCC *>,
147                    CGSCCAnalysisResultListT::iterator> CGSCCAnalysisResultMapT;
148 
149   /// \brief Map from an analysis ID and function to a particular cached
150   /// analysis result.
151   CGSCCAnalysisResultMapT CGSCCAnalysisResults;
152 };
153 
154 /// \brief A module analysis which acts as a proxy for a CGSCC analysis
155 /// manager.
156 ///
157 /// This primarily proxies invalidation information from the module analysis
158 /// manager and module pass manager to a CGSCC analysis manager. You should
159 /// never use a CGSCC analysis manager from within (transitively) a module
160 /// pass manager unless your parent module pass has received a proxy result
161 /// object for it.
162 class CGSCCAnalysisManagerModuleProxy {
163 public:
164   class Result {
165   public:
Result(CGSCCAnalysisManager & CGAM)166     explicit Result(CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {}
167     // We have to explicitly define all the special member functions because
168     // MSVC refuses to generate them.
Result(const Result & Arg)169     Result(const Result &Arg) : CGAM(Arg.CGAM) {}
Result(Result && Arg)170     Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {}
171     Result &operator=(Result RHS) {
172       std::swap(CGAM, RHS.CGAM);
173       return *this;
174     }
175     ~Result();
176 
177     /// \brief Accessor for the \c CGSCCAnalysisManager.
getManager()178     CGSCCAnalysisManager &getManager() { return *CGAM; }
179 
180     /// \brief Handler for invalidation of the module.
181     ///
182     /// If this analysis itself is preserved, then we assume that the call
183     /// graph of the module hasn't changed and thus we don't need to invalidate
184     /// *all* cached data associated with a \c SCC* in the \c
185     /// CGSCCAnalysisManager.
186     ///
187     /// Regardless of whether this analysis is marked as preserved, all of the
188     /// analyses in the \c CGSCCAnalysisManager are potentially invalidated
189     /// based on the set of preserved analyses.
190     bool invalidate(Module *M, const PreservedAnalyses &PA);
191 
192   private:
193     CGSCCAnalysisManager *CGAM;
194   };
195 
ID()196   static void *ID() { return (void *)&PassID; }
197 
CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManager & CGAM)198   explicit CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManager &CGAM)
199       : CGAM(&CGAM) {}
200   // We have to explicitly define all the special member functions because MSVC
201   // refuses to generate them.
CGSCCAnalysisManagerModuleProxy(const CGSCCAnalysisManagerModuleProxy & Arg)202   CGSCCAnalysisManagerModuleProxy(
203       const CGSCCAnalysisManagerModuleProxy &Arg)
204       : CGAM(Arg.CGAM) {}
CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManagerModuleProxy && Arg)205   CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManagerModuleProxy &&Arg)
206       : CGAM(std::move(Arg.CGAM)) {}
207   CGSCCAnalysisManagerModuleProxy &
208   operator=(CGSCCAnalysisManagerModuleProxy RHS) {
209     std::swap(CGAM, RHS.CGAM);
210     return *this;
211   }
212 
213   /// \brief Run the analysis pass and create our proxy result object.
214   ///
215   /// This doesn't do any interesting work, it is primarily used to insert our
216   /// proxy result object into the module analysis cache so that we can proxy
217   /// invalidation to the CGSCC analysis manager.
218   ///
219   /// In debug builds, it will also assert that the analysis manager is empty
220   /// as no queries should arrive at the CGSCC analysis manager prior to
221   /// this analysis being requested.
222   Result run(Module *M);
223 
224 private:
225   static char PassID;
226 
227   CGSCCAnalysisManager *CGAM;
228 };
229 
230 /// \brief A CGSCC analysis which acts as a proxy for a module analysis
231 /// manager.
232 ///
233 /// This primarily provides an accessor to a parent module analysis manager to
234 /// CGSCC passes. Only the const interface of the module analysis manager is
235 /// provided to indicate that once inside of a CGSCC analysis pass you
236 /// cannot request a module analysis to actually run. Instead, the user must
237 /// rely on the \c getCachedResult API.
238 ///
239 /// This proxy *doesn't* manage the invalidation in any way. That is handled by
240 /// the recursive return path of each layer of the pass manager and the
241 /// returned PreservedAnalysis set.
242 class ModuleAnalysisManagerCGSCCProxy {
243 public:
244   /// \brief Result proxy object for \c ModuleAnalysisManagerCGSCCProxy.
245   class Result {
246   public:
Result(const ModuleAnalysisManager & MAM)247     explicit Result(const ModuleAnalysisManager &MAM) : MAM(&MAM) {}
248     // We have to explicitly define all the special member functions because
249     // MSVC refuses to generate them.
Result(const Result & Arg)250     Result(const Result &Arg) : MAM(Arg.MAM) {}
Result(Result && Arg)251     Result(Result &&Arg) : MAM(std::move(Arg.MAM)) {}
252     Result &operator=(Result RHS) {
253       std::swap(MAM, RHS.MAM);
254       return *this;
255     }
256 
getManager()257     const ModuleAnalysisManager &getManager() const { return *MAM; }
258 
259     /// \brief Handle invalidation by ignoring it, this pass is immutable.
invalidate(LazyCallGraph::SCC *)260     bool invalidate(LazyCallGraph::SCC *) { return false; }
261 
262   private:
263     const ModuleAnalysisManager *MAM;
264   };
265 
ID()266   static void *ID() { return (void *)&PassID; }
267 
ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManager & MAM)268   ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManager &MAM)
269       : MAM(&MAM) {}
270   // We have to explicitly define all the special member functions because MSVC
271   // refuses to generate them.
ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManagerCGSCCProxy & Arg)272   ModuleAnalysisManagerCGSCCProxy(
273       const ModuleAnalysisManagerCGSCCProxy &Arg)
274       : MAM(Arg.MAM) {}
ModuleAnalysisManagerCGSCCProxy(ModuleAnalysisManagerCGSCCProxy && Arg)275   ModuleAnalysisManagerCGSCCProxy(ModuleAnalysisManagerCGSCCProxy &&Arg)
276       : MAM(std::move(Arg.MAM)) {}
277   ModuleAnalysisManagerCGSCCProxy &
278   operator=(ModuleAnalysisManagerCGSCCProxy RHS) {
279     std::swap(MAM, RHS.MAM);
280     return *this;
281   }
282 
283   /// \brief Run the analysis pass and create our proxy result object.
284   /// Nothing to see here, it just forwards the \c MAM reference into the
285   /// result.
run(LazyCallGraph::SCC *)286   Result run(LazyCallGraph::SCC *) { return Result(*MAM); }
287 
288 private:
289   static char PassID;
290 
291   const ModuleAnalysisManager *MAM;
292 };
293 
294 /// \brief The core module pass which does a post-order walk of the SCCs and
295 /// runs a CGSCC pass over each one.
296 ///
297 /// Designed to allow composition of a CGSCCPass(Manager) and
298 /// a ModulePassManager. Note that this pass must be run with a module analysis
299 /// manager as it uses the LazyCallGraph analysis. It will also run the
300 /// \c CGSCCAnalysisManagerModuleProxy analysis prior to running the CGSCC
301 /// pass over the module to enable a \c FunctionAnalysisManager to be used
302 /// within this run safely.
303 template <typename CGSCCPassT> class ModuleToPostOrderCGSCCPassAdaptor {
304 public:
ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass)305   explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass)
306       : Pass(std::move(Pass)) {}
307   // We have to explicitly define all the special member functions because MSVC
308   // refuses to generate them.
ModuleToPostOrderCGSCCPassAdaptor(const ModuleToPostOrderCGSCCPassAdaptor & Arg)309   ModuleToPostOrderCGSCCPassAdaptor(
310       const ModuleToPostOrderCGSCCPassAdaptor &Arg)
311       : Pass(Arg.Pass) {}
ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor && Arg)312   ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor &&Arg)
313       : Pass(std::move(Arg.Pass)) {}
swap(ModuleToPostOrderCGSCCPassAdaptor & LHS,ModuleToPostOrderCGSCCPassAdaptor & RHS)314   friend void swap(ModuleToPostOrderCGSCCPassAdaptor &LHS,
315                    ModuleToPostOrderCGSCCPassAdaptor &RHS) {
316     using std::swap;
317     swap(LHS.Pass, RHS.Pass);
318   }
319   ModuleToPostOrderCGSCCPassAdaptor &
320   operator=(ModuleToPostOrderCGSCCPassAdaptor RHS) {
321     swap(*this, RHS);
322     return *this;
323   }
324 
325   /// \brief Runs the CGSCC pass across every SCC in the module.
run(Module * M,ModuleAnalysisManager * AM)326   PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) {
327     assert(AM && "We need analyses to compute the call graph!");
328 
329     // Setup the CGSCC analysis manager from its proxy.
330     CGSCCAnalysisManager &CGAM =
331         AM->getResult<CGSCCAnalysisManagerModuleProxy>(M).getManager();
332 
333     // Get the call graph for this module.
334     LazyCallGraph &CG = AM->getResult<LazyCallGraphAnalysis>(M);
335 
336     PreservedAnalyses PA = PreservedAnalyses::all();
337     for (LazyCallGraph::SCC &C : CG.postorder_sccs()) {
338       PreservedAnalyses PassPA = Pass.run(&C, &CGAM);
339 
340       // We know that the CGSCC pass couldn't have invalidated any other
341       // SCC's analyses (that's the contract of a CGSCC pass), so
342       // directly handle the CGSCC analysis manager's invalidation here.
343       // FIXME: This isn't quite correct. We need to handle the case where the
344       // pass updated the CG, particularly some child of the current SCC, and
345       // invalidate its analyses.
346       CGAM.invalidate(&C, PassPA);
347 
348       // Then intersect the preserved set so that invalidation of module
349       // analyses will eventually occur when the module pass completes.
350       PA.intersect(std::move(PassPA));
351     }
352 
353     // By definition we preserve the proxy. This precludes *any* invalidation
354     // of CGSCC analyses by the proxy, but that's OK because we've taken
355     // care to invalidate analyses in the CGSCC analysis manager
356     // incrementally above.
357     PA.preserve<CGSCCAnalysisManagerModuleProxy>();
358     return PA;
359   }
360 
name()361   static StringRef name() { return "ModuleToPostOrderCGSCCPassAdaptor"; }
362 
363 private:
364   CGSCCPassT Pass;
365 };
366 
367 /// \brief A function to deduce a function pass type and wrap it in the
368 /// templated adaptor.
369 template <typename CGSCCPassT>
370 ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>
createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass)371 createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) {
372   return std::move(
373       ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass)));
374 }
375 
376 /// \brief A CGSCC analysis which acts as a proxy for a function analysis
377 /// manager.
378 ///
379 /// This primarily proxies invalidation information from the CGSCC analysis
380 /// manager and CGSCC pass manager to a function analysis manager. You should
381 /// never use a function analysis manager from within (transitively) a CGSCC
382 /// pass manager unless your parent CGSCC pass has received a proxy result
383 /// object for it.
384 class FunctionAnalysisManagerCGSCCProxy {
385 public:
386   class Result {
387   public:
Result(FunctionAnalysisManager & FAM)388     explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
389     // We have to explicitly define all the special member functions because
390     // MSVC refuses to generate them.
Result(const Result & Arg)391     Result(const Result &Arg) : FAM(Arg.FAM) {}
Result(Result && Arg)392     Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {}
393     Result &operator=(Result RHS) {
394       std::swap(FAM, RHS.FAM);
395       return *this;
396     }
397     ~Result();
398 
399     /// \brief Accessor for the \c FunctionAnalysisManager.
getManager()400     FunctionAnalysisManager &getManager() { return *FAM; }
401 
402     /// \brief Handler for invalidation of the SCC.
403     ///
404     /// If this analysis itself is preserved, then we assume that the set of \c
405     /// Function objects in the \c SCC hasn't changed and thus we don't need
406     /// to invalidate *all* cached data associated with a \c Function* in the \c
407     /// FunctionAnalysisManager.
408     ///
409     /// Regardless of whether this analysis is marked as preserved, all of the
410     /// analyses in the \c FunctionAnalysisManager are potentially invalidated
411     /// based on the set of preserved analyses.
412     bool invalidate(LazyCallGraph::SCC *C, const PreservedAnalyses &PA);
413 
414   private:
415     FunctionAnalysisManager *FAM;
416   };
417 
ID()418   static void *ID() { return (void *)&PassID; }
419 
FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManager & FAM)420   explicit FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManager &FAM)
421       : FAM(&FAM) {}
422   // We have to explicitly define all the special member functions because MSVC
423   // refuses to generate them.
FunctionAnalysisManagerCGSCCProxy(const FunctionAnalysisManagerCGSCCProxy & Arg)424   FunctionAnalysisManagerCGSCCProxy(
425       const FunctionAnalysisManagerCGSCCProxy &Arg)
426       : FAM(Arg.FAM) {}
FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManagerCGSCCProxy && Arg)427   FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManagerCGSCCProxy &&Arg)
428       : FAM(std::move(Arg.FAM)) {}
429   FunctionAnalysisManagerCGSCCProxy &
430   operator=(FunctionAnalysisManagerCGSCCProxy RHS) {
431     std::swap(FAM, RHS.FAM);
432     return *this;
433   }
434 
435   /// \brief Run the analysis pass and create our proxy result object.
436   ///
437   /// This doesn't do any interesting work, it is primarily used to insert our
438   /// proxy result object into the module analysis cache so that we can proxy
439   /// invalidation to the function analysis manager.
440   ///
441   /// In debug builds, it will also assert that the analysis manager is empty
442   /// as no queries should arrive at the function analysis manager prior to
443   /// this analysis being requested.
444   Result run(LazyCallGraph::SCC *C);
445 
446 private:
447   static char PassID;
448 
449   FunctionAnalysisManager *FAM;
450 };
451 
452 /// \brief A function analysis which acts as a proxy for a CGSCC analysis
453 /// manager.
454 ///
455 /// This primarily provides an accessor to a parent CGSCC analysis manager to
456 /// function passes. Only the const interface of the CGSCC analysis manager is
457 /// provided to indicate that once inside of a function analysis pass you
458 /// cannot request a CGSCC analysis to actually run. Instead, the user must
459 /// rely on the \c getCachedResult API.
460 ///
461 /// This proxy *doesn't* manage the invalidation in any way. That is handled by
462 /// the recursive return path of each layer of the pass manager and the
463 /// returned PreservedAnalysis set.
464 class CGSCCAnalysisManagerFunctionProxy {
465 public:
466   /// \brief Result proxy object for \c ModuleAnalysisManagerFunctionProxy.
467   class Result {
468   public:
Result(const CGSCCAnalysisManager & CGAM)469     explicit Result(const CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {}
470     // We have to explicitly define all the special member functions because
471     // MSVC refuses to generate them.
Result(const Result & Arg)472     Result(const Result &Arg) : CGAM(Arg.CGAM) {}
Result(Result && Arg)473     Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {}
474     Result &operator=(Result RHS) {
475       std::swap(CGAM, RHS.CGAM);
476       return *this;
477     }
478 
getManager()479     const CGSCCAnalysisManager &getManager() const { return *CGAM; }
480 
481     /// \brief Handle invalidation by ignoring it, this pass is immutable.
invalidate(Function *)482     bool invalidate(Function *) { return false; }
483 
484   private:
485     const CGSCCAnalysisManager *CGAM;
486   };
487 
ID()488   static void *ID() { return (void *)&PassID; }
489 
CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManager & CGAM)490   CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManager &CGAM)
491       : CGAM(&CGAM) {}
492   // We have to explicitly define all the special member functions because MSVC
493   // refuses to generate them.
CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManagerFunctionProxy & Arg)494   CGSCCAnalysisManagerFunctionProxy(
495       const CGSCCAnalysisManagerFunctionProxy &Arg)
496       : CGAM(Arg.CGAM) {}
CGSCCAnalysisManagerFunctionProxy(CGSCCAnalysisManagerFunctionProxy && Arg)497   CGSCCAnalysisManagerFunctionProxy(CGSCCAnalysisManagerFunctionProxy &&Arg)
498       : CGAM(std::move(Arg.CGAM)) {}
499   CGSCCAnalysisManagerFunctionProxy &
500   operator=(CGSCCAnalysisManagerFunctionProxy RHS) {
501     std::swap(CGAM, RHS.CGAM);
502     return *this;
503   }
504 
505   /// \brief Run the analysis pass and create our proxy result object.
506   /// Nothing to see here, it just forwards the \c CGAM reference into the
507   /// result.
run(Function *)508   Result run(Function *) { return Result(*CGAM); }
509 
510 private:
511   static char PassID;
512 
513   const CGSCCAnalysisManager *CGAM;
514 };
515 
516 /// \brief Adaptor that maps from a SCC to its functions.
517 ///
518 /// Designed to allow composition of a FunctionPass(Manager) and
519 /// a CGSCCPassManager. Note that if this pass is constructed with a pointer
520 /// to a \c CGSCCAnalysisManager it will run the
521 /// \c FunctionAnalysisManagerCGSCCProxy analysis prior to running the function
522 /// pass over the SCC to enable a \c FunctionAnalysisManager to be used
523 /// within this run safely.
524 template <typename FunctionPassT> class CGSCCToFunctionPassAdaptor {
525 public:
CGSCCToFunctionPassAdaptor(FunctionPassT Pass)526   explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass)
527       : Pass(std::move(Pass)) {}
528   // We have to explicitly define all the special member functions because MSVC
529   // refuses to generate them.
CGSCCToFunctionPassAdaptor(const CGSCCToFunctionPassAdaptor & Arg)530   CGSCCToFunctionPassAdaptor(const CGSCCToFunctionPassAdaptor &Arg)
531       : Pass(Arg.Pass) {}
CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor && Arg)532   CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg)
533       : Pass(std::move(Arg.Pass)) {}
swap(CGSCCToFunctionPassAdaptor & LHS,CGSCCToFunctionPassAdaptor & RHS)534   friend void swap(CGSCCToFunctionPassAdaptor &LHS, CGSCCToFunctionPassAdaptor &RHS) {
535     using std::swap;
536     swap(LHS.Pass, RHS.Pass);
537   }
538   CGSCCToFunctionPassAdaptor &operator=(CGSCCToFunctionPassAdaptor RHS) {
539     swap(*this, RHS);
540     return *this;
541   }
542 
543   /// \brief Runs the function pass across every function in the module.
run(LazyCallGraph::SCC * C,CGSCCAnalysisManager * AM)544   PreservedAnalyses run(LazyCallGraph::SCC *C, CGSCCAnalysisManager *AM) {
545     FunctionAnalysisManager *FAM = nullptr;
546     if (AM)
547       // Setup the function analysis manager from its proxy.
548       FAM = &AM->getResult<FunctionAnalysisManagerCGSCCProxy>(C).getManager();
549 
550     PreservedAnalyses PA = PreservedAnalyses::all();
551     for (LazyCallGraph::Node *N : *C) {
552       PreservedAnalyses PassPA = Pass.run(&N->getFunction(), FAM);
553 
554       // We know that the function pass couldn't have invalidated any other
555       // function's analyses (that's the contract of a function pass), so
556       // directly handle the function analysis manager's invalidation here.
557       if (FAM)
558         FAM->invalidate(&N->getFunction(), PassPA);
559 
560       // Then intersect the preserved set so that invalidation of module
561       // analyses will eventually occur when the module pass completes.
562       PA.intersect(std::move(PassPA));
563     }
564 
565     // By definition we preserve the proxy. This precludes *any* invalidation
566     // of function analyses by the proxy, but that's OK because we've taken
567     // care to invalidate analyses in the function analysis manager
568     // incrementally above.
569     // FIXME: We need to update the call graph here to account for any deleted
570     // edges!
571     PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
572     return PA;
573   }
574 
name()575   static StringRef name() { return "CGSCCToFunctionPassAdaptor"; }
576 
577 private:
578   FunctionPassT Pass;
579 };
580 
581 /// \brief A function to deduce a function pass type and wrap it in the
582 /// templated adaptor.
583 template <typename FunctionPassT>
584 CGSCCToFunctionPassAdaptor<FunctionPassT>
createCGSCCToFunctionPassAdaptor(FunctionPassT Pass)585 createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) {
586   return std::move(CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass)));
587 }
588 
589 }
590 
591 #endif
592