CGSCCPassManager.h revision dce4a407a24b04eebc6a376f8e62b41aaa7b071f
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
27namespace llvm {
28
29class CGSCCAnalysisManager;
30
31class CGSCCPassManager {
32public:
33  // We have to explicitly define all the special member functions because MSVC
34  // refuses to generate them.
35  CGSCCPassManager() {}
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
46  template <typename CGSCCPassT> void addPass(CGSCCPassT Pass) {
47    Passes.emplace_back(new CGSCCPassModel<CGSCCPassT>(std::move(Pass)));
48  }
49
50  static StringRef name() { return "CGSCCPassManager"; }
51
52private:
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> {
59    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.
72class 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
81public:
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.
86  CGSCCAnalysisManager() {}
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
107private:
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.
162class CGSCCAnalysisManagerModuleProxy {
163public:
164  class Result {
165  public:
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.
169    Result(const Result &Arg) : CGAM(Arg.CGAM) {}
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.
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
196  static void *ID() { return (void *)&PassID; }
197
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.
202  CGSCCAnalysisManagerModuleProxy(
203      const CGSCCAnalysisManagerModuleProxy &Arg)
204      : CGAM(Arg.CGAM) {}
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
224private:
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.
242class ModuleAnalysisManagerCGSCCProxy {
243public:
244  /// \brief Result proxy object for \c ModuleAnalysisManagerCGSCCProxy.
245  class Result {
246  public:
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.
250    Result(const Result &Arg) : MAM(Arg.MAM) {}
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
257    const ModuleAnalysisManager &getManager() const { return *MAM; }
258
259    /// \brief Handle invalidation by ignoring it, this pass is immutable.
260    bool invalidate(LazyCallGraph::SCC *) { return false; }
261
262  private:
263    const ModuleAnalysisManager *MAM;
264  };
265
266  static void *ID() { return (void *)&PassID; }
267
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.
272  ModuleAnalysisManagerCGSCCProxy(
273      const ModuleAnalysisManagerCGSCCProxy &Arg)
274      : MAM(Arg.MAM) {}
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.
286  Result run(LazyCallGraph::SCC *) { return Result(*MAM); }
287
288private:
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.
303template <typename CGSCCPassT> class ModuleToPostOrderCGSCCPassAdaptor {
304public:
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.
309  ModuleToPostOrderCGSCCPassAdaptor(
310      const ModuleToPostOrderCGSCCPassAdaptor &Arg)
311      : Pass(Arg.Pass) {}
312  ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor &&Arg)
313      : Pass(std::move(Arg.Pass)) {}
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.
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
361  static StringRef name() { return "ModuleToPostOrderCGSCCPassAdaptor"; }
362
363private:
364  CGSCCPassT Pass;
365};
366
367/// \brief A function to deduce a function pass type and wrap it in the
368/// templated adaptor.
369template <typename CGSCCPassT>
370ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>
371createModuleToPostOrderCGSCCPassAdaptor(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.
384class FunctionAnalysisManagerCGSCCProxy {
385public:
386  class Result {
387  public:
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.
391    Result(const Result &Arg) : FAM(Arg.FAM) {}
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.
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
418  static void *ID() { return (void *)&PassID; }
419
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.
424  FunctionAnalysisManagerCGSCCProxy(
425      const FunctionAnalysisManagerCGSCCProxy &Arg)
426      : FAM(Arg.FAM) {}
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
446private:
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.
464class CGSCCAnalysisManagerFunctionProxy {
465public:
466  /// \brief Result proxy object for \c ModuleAnalysisManagerFunctionProxy.
467  class Result {
468  public:
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.
472    Result(const Result &Arg) : CGAM(Arg.CGAM) {}
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
479    const CGSCCAnalysisManager &getManager() const { return *CGAM; }
480
481    /// \brief Handle invalidation by ignoring it, this pass is immutable.
482    bool invalidate(Function *) { return false; }
483
484  private:
485    const CGSCCAnalysisManager *CGAM;
486  };
487
488  static void *ID() { return (void *)&PassID; }
489
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.
494  CGSCCAnalysisManagerFunctionProxy(
495      const CGSCCAnalysisManagerFunctionProxy &Arg)
496      : CGAM(Arg.CGAM) {}
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.
508  Result run(Function *) { return Result(*CGAM); }
509
510private:
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.
524template <typename FunctionPassT> class CGSCCToFunctionPassAdaptor {
525public:
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.
530  CGSCCToFunctionPassAdaptor(const CGSCCToFunctionPassAdaptor &Arg)
531      : Pass(Arg.Pass) {}
532  CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg)
533      : Pass(std::move(Arg.Pass)) {}
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.
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
575  static StringRef name() { return "CGSCCToFunctionPassAdaptor"; }
576
577private:
578  FunctionPassT Pass;
579};
580
581/// \brief A function to deduce a function pass type and wrap it in the
582/// templated adaptor.
583template <typename FunctionPassT>
584CGSCCToFunctionPassAdaptor<FunctionPassT>
585createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) {
586  return std::move(CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass)));
587}
588
589}
590
591#endif
592