llvm.org GIT mirror llvm / 57418d8
[PM] Add a new-PM-style CGSCC pass manager using the newly added LazyCallGraph analysis framework. Wire it up all the way through the opt driver and add some very basic testing that we can build pass pipelines including these components. Still a lot more to do in terms of testing that all of this works, but the basic pieces are here. There is a *lot* of boiler plate here. It's something I'm going to actively look at reducing, but I don't have any immediate ideas that don't end up making the code terribly complex in order to fold away the boilerplate. Until I figure out something to minimize the boilerplate, almost all of this is based on the code for the existing pass managers, copied and heavily adjusted to suit the needs of the CGSCC pass management layer. The actual CG management still has a bunch of FIXMEs in it. Notably, we don't do *any* updating of the CG as it is potentially invalidated. I wanted to get this in place to motivate the new analysis, and add update APIs to the analysis and the pass management layers in concert to make sure that the *right* APIs are present. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206745 91177308-0d34-0410-b5e6-96231b3b80d8 Chandler Carruth 5 years ago
7 changed file(s) with 929 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 //===- CGSCCPassManager.h - Call graph pass management ----------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 ///
10 /// This header provides classes for managing passes over SCCs of the call
11 /// graph. These passes form an important component of LLVM's interprocedural
12 /// optimizations. Because they operate on the SCCs of the call graph, and they
13 /// wtraverse the graph in post order, they can effectively do pair-wise
14 /// interprocedural optimizations for all call edges in the program. At each
15 /// call site edge, the callee has already been optimized as much as is
16 /// possible. This in turn allows very accurate analysis of it for IPO.
17 ///
18 //===----------------------------------------------------------------------===//
19
20 #ifndef LLVM_ANALYSIS_CGSCC_PASS_MANAGER_H
21 #define LLVM_ANALYSIS_CGSCC_PASS_MANAGER_H
22
23 #include "llvm/IR/PassManager.h"
24 #include "llvm/Analysis/LazyCallGraph.h"
25
26 namespace llvm {
27
28 class CGSCCAnalysisManager;
29
30 class CGSCCPassManager {
31 public:
32 // We have to explicitly define all the special member functions because MSVC
33 // refuses to generate them.
34 CGSCCPassManager() {}
35 CGSCCPassManager(CGSCCPassManager &&Arg) : Passes(std::move(Arg.Passes)) {}
36 CGSCCPassManager &operator=(CGSCCPassManager &&RHS) {
37 Passes = std::move(RHS.Passes);
38 return *this;
39 }
40
41 /// \brief Run all of the CGSCC passes in this pass manager over a SCC.
42 PreservedAnalyses run(LazyCallGraph::SCC *C,
43 CGSCCAnalysisManager *AM = nullptr);
44
45 template void addPass(CGSCCPassT Pass) {
46 Passes.emplace_back(new CGSCCPassModel(std::move(Pass)));
47 }
48
49 static StringRef name() { return "CGSCCPassManager"; }
50
51 private:
52 // Pull in the concept type and model template specialized for SCCs.
53 typedef detail::PassConcept
54 CGSCCPassConcept;
55 template
56 struct CGSCCPassModel
57 : detail::PassModel {
58 CGSCCPassModel(PassT Pass)
59 : detail::PassModel(
60 std::move(Pass)) {}
61 };
62
63 CGSCCPassManager(const CGSCCPassManager &) LLVM_DELETED_FUNCTION;
64 CGSCCPassManager &operator=(const CGSCCPassManager &) LLVM_DELETED_FUNCTION;
65
66 std::vector> Passes;
67 };
68
69 /// \brief A function analysis manager to coordinate and cache analyses run over
70 /// a module.
71 class CGSCCAnalysisManager : public detail::AnalysisManagerBase<
72 CGSCCAnalysisManager, LazyCallGraph::SCC *> {
73 friend class detail::AnalysisManagerBase
74 LazyCallGraph::SCC *>;
75 typedef detail::AnalysisManagerBase
76 LazyCallGraph::SCC *> BaseT;
77 typedef BaseT::ResultConceptT ResultConceptT;
78 typedef BaseT::PassConceptT PassConceptT;
79
80 public:
81 // Most public APIs are inherited from the CRTP base class.
82
83 // We have to explicitly define all the special member functions because MSVC
84 // refuses to generate them.
85 CGSCCAnalysisManager() {}
86 CGSCCAnalysisManager(CGSCCAnalysisManager &&Arg)
87 : BaseT(std::move(static_cast(Arg))),
88 CGSCCAnalysisResults(std::move(Arg.CGSCCAnalysisResults)) {}
89 CGSCCAnalysisManager &operator=(CGSCCAnalysisManager &&RHS) {
90 BaseT::operator=(std::move(static_cast(RHS)));
91 CGSCCAnalysisResults = std::move(RHS.CGSCCAnalysisResults);
92 return *this;
93 }
94
95 /// \brief Returns true if the analysis manager has an empty results cache.
96 bool empty() const;
97
98 /// \brief Clear the function analysis result cache.
99 ///
100 /// This routine allows cleaning up when the set of functions itself has
101 /// potentially changed, and thus we can't even look up a a result and
102 /// invalidate it directly. Notably, this does *not* call invalidate
103 /// functions as there is nothing to be done for them.
104 void clear();
105
106 private:
107 CGSCCAnalysisManager(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION;
108 CGSCCAnalysisManager &
109 operator=(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION;
110
111 /// \brief Get a function pass result, running the pass if necessary.
112 ResultConceptT &getResultImpl(void *PassID, LazyCallGraph::SCC *C);
113
114 /// \brief Get a cached function pass result or return null.
115 ResultConceptT *getCachedResultImpl(void *PassID,
116 LazyCallGraph::SCC *C) const;
117
118 /// \brief Invalidate a function pass result.
119 void invalidateImpl(void *PassID, LazyCallGraph::SCC *C);
120
121 /// \brief Invalidate the results for a function..
122 void invalidateImpl(LazyCallGraph::SCC *C, const PreservedAnalyses &PA);
123
124 /// \brief List of function analysis pass IDs and associated concept pointers.
125 ///
126 /// Requires iterators to be valid across appending new entries and arbitrary
127 /// erases. Provides both the pass ID and concept pointer such that it is
128 /// half of a bijection and provides storage for the actual result concept.
129 typedef std::list<
130 std::pair
131 LazyCallGraph::SCC *>>>> CGSCCAnalysisResultListT;
132
133 /// \brief Map type from function pointer to our custom list type.
134 typedef DenseMap
135 CGSCCAnalysisResultListMapT;
136
137 /// \brief Map from function to a list of function analysis results.
138 ///
139 /// Provides linear time removal of all analysis results for a function and
140 /// the ultimate storage for a particular cached analysis result.
141 CGSCCAnalysisResultListMapT CGSCCAnalysisResultLists;
142
143 /// \brief Map type from a pair of analysis ID and function pointer to an
144 /// iterator into a particular result list.
145 typedef DenseMap,
146 CGSCCAnalysisResultListT::iterator> CGSCCAnalysisResultMapT;
147
148 /// \brief Map from an analysis ID and function to a particular cached
149 /// analysis result.
150 CGSCCAnalysisResultMapT CGSCCAnalysisResults;
151 };
152
153 /// \brief A module analysis which acts as a proxy for a CGSCC analysis
154 /// manager.
155 ///
156 /// This primarily proxies invalidation information from the module analysis
157 /// manager and module pass manager to a CGSCC analysis manager. You should
158 /// never use a CGSCC analysis manager from within (transitively) a module
159 /// pass manager unless your parent module pass has received a proxy result
160 /// object for it.
161 class CGSCCAnalysisManagerModuleProxy {
162 public:
163 class Result {
164 public:
165 explicit Result(CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {}
166 // We have to explicitly define all the special member functions because
167 // MSVC refuses to generate them.
168 Result(const Result &Arg) : CGAM(Arg.CGAM) {}
169 Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {}
170 Result &operator=(Result RHS) {
171 std::swap(CGAM, RHS.CGAM);
172 return *this;
173 }
174 ~Result();
175
176 /// \brief Accessor for the \c CGSCCAnalysisManager.
177 CGSCCAnalysisManager &getManager() { return *CGAM; }
178
179 /// \brief Handler for invalidation of the module.
180 ///
181 /// If this analysis itself is preserved, then we assume that the call
182 /// graph of the module hasn't changed and thus we don't need to invalidate
183 /// *all* cached data associated with a \c SCC* in the \c
184 /// CGSCCAnalysisManager.
185 ///
186 /// Regardless of whether this analysis is marked as preserved, all of the
187 /// analyses in the \c CGSCCAnalysisManager are potentially invalidated
188 /// based on the set of preserved analyses.
189 bool invalidate(Module *M, const PreservedAnalyses &PA);
190
191 private:
192 CGSCCAnalysisManager *CGAM;
193 };
194
195 static void *ID() { return (void *)&PassID; }
196
197 explicit CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManager &CGAM)
198 : CGAM(&CGAM) {}
199 // We have to explicitly define all the special member functions because MSVC
200 // refuses to generate them.
201 CGSCCAnalysisManagerModuleProxy(
202 const CGSCCAnalysisManagerModuleProxy &Arg)
203 : CGAM(Arg.CGAM) {}
204 CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManagerModuleProxy &&Arg)
205 : CGAM(std::move(Arg.CGAM)) {}
206 CGSCCAnalysisManagerModuleProxy &
207 operator=(CGSCCAnalysisManagerModuleProxy RHS) {
208 std::swap(CGAM, RHS.CGAM);
209 return *this;
210 }
211
212 /// \brief Run the analysis pass and create our proxy result object.
213 ///
214 /// This doesn't do any interesting work, it is primarily used to insert our
215 /// proxy result object into the module analysis cache so that we can proxy
216 /// invalidation to the CGSCC analysis manager.
217 ///
218 /// In debug builds, it will also assert that the analysis manager is empty
219 /// as no queries should arrive at the CGSCC analysis manager prior to
220 /// this analysis being requested.
221 Result run(Module *M);
222
223 private:
224 static char PassID;
225
226 CGSCCAnalysisManager *CGAM;
227 };
228
229 /// \brief A CGSCC analysis which acts as a proxy for a module analysis
230 /// manager.
231 ///
232 /// This primarily provides an accessor to a parent module analysis manager to
233 /// CGSCC passes. Only the const interface of the module analysis manager is
234 /// provided to indicate that once inside of a CGSCC analysis pass you
235 /// cannot request a module analysis to actually run. Instead, the user must
236 /// rely on the \c getCachedResult API.
237 ///
238 /// This proxy *doesn't* manage the invalidation in any way. That is handled by
239 /// the recursive return path of each layer of the pass manager and the
240 /// returned PreservedAnalysis set.
241 class ModuleAnalysisManagerCGSCCProxy {
242 public:
243 /// \brief Result proxy object for \c ModuleAnalysisManagerCGSCCProxy.
244 class Result {
245 public:
246 explicit Result(const ModuleAnalysisManager &MAM) : MAM(&MAM) {}
247 // We have to explicitly define all the special member functions because
248 // MSVC refuses to generate them.
249 Result(const Result &Arg) : MAM(Arg.MAM) {}
250 Result(Result &&Arg) : MAM(std::move(Arg.MAM)) {}
251 Result &operator=(Result RHS) {
252 std::swap(MAM, RHS.MAM);
253 return *this;
254 }
255
256 const ModuleAnalysisManager &getManager() const { return *MAM; }
257
258 /// \brief Handle invalidation by ignoring it, this pass is immutable.
259 bool invalidate(LazyCallGraph::SCC *) { return false; }
260
261 private:
262 const ModuleAnalysisManager *MAM;
263 };
264
265 static void *ID() { return (void *)&PassID; }
266
267 ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManager &MAM)
268 : MAM(&MAM) {}
269 // We have to explicitly define all the special member functions because MSVC
270 // refuses to generate them.
271 ModuleAnalysisManagerCGSCCProxy(
272 const ModuleAnalysisManagerCGSCCProxy &Arg)
273 : MAM(Arg.MAM) {}
274 ModuleAnalysisManagerCGSCCProxy(ModuleAnalysisManagerCGSCCProxy &&Arg)
275 : MAM(std::move(Arg.MAM)) {}
276 ModuleAnalysisManagerCGSCCProxy &
277 operator=(ModuleAnalysisManagerCGSCCProxy RHS) {
278 std::swap(MAM, RHS.MAM);
279 return *this;
280 }
281
282 /// \brief Run the analysis pass and create our proxy result object.
283 /// Nothing to see here, it just forwards the \c MAM reference into the
284 /// result.
285 Result run(LazyCallGraph::SCC *) { return Result(*MAM); }
286
287 private:
288 static char PassID;
289
290 const ModuleAnalysisManager *MAM;
291 };
292
293 /// \brief The core module pass which does a post-order walk of the SCCs and
294 /// runs a CGSCC pass over each one.
295 ///
296 /// Designed to allow composition of a CGSCCPass(Manager) and
297 /// a ModulePassManager. Note that this pass must be run with a module analysis
298 /// manager as it uses the LazyCallGraph analysis. It will also run the
299 /// \c CGSCCAnalysisManagerModuleProxy analysis prior to running the CGSCC
300 /// pass over the module to enable a \c FunctionAnalysisManager to be used
301 /// within this run safely.
302 template class ModuleToPostOrderCGSCCPassAdaptor {
303 public:
304 explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass)
305 : Pass(std::move(Pass)) {}
306 // We have to explicitly define all the special member functions because MSVC
307 // refuses to generate them.
308 ModuleToPostOrderCGSCCPassAdaptor(
309 const ModuleToPostOrderCGSCCPassAdaptor &Arg)
310 : Pass(Arg.Pass) {}
311 ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor &&Arg)
312 : Pass(std::move(Arg.Pass)) {}
313 friend void swap(ModuleToPostOrderCGSCCPassAdaptor &LHS,
314 ModuleToPostOrderCGSCCPassAdaptor &RHS) {
315 using std::swap;
316 swap(LHS.Pass, RHS.Pass);
317 }
318 ModuleToPostOrderCGSCCPassAdaptor &
319 operator=(ModuleToPostOrderCGSCCPassAdaptor RHS) {
320 swap(*this, RHS);
321 return *this;
322 }
323
324 /// \brief Runs the CGSCC pass across every SCC in the module.
325 PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) {
326 assert(AM && "We need analyses to compute the call graph!");
327
328 // Setup the CGSCC analysis manager from its proxy.
329 CGSCCAnalysisManager &CGAM =
330 AM->getResult(M).getManager();
331
332 // Get the call graph for this module.
333 LazyCallGraph &CG = AM->getResult(M);
334
335 PreservedAnalyses PA = PreservedAnalyses::all();
336 for (LazyCallGraph::SCC *C : CG.postorder_sccs()) {
337 PreservedAnalyses PassPA = Pass.run(C, &CGAM);
338
339 // We know that the CGSCC pass couldn't have invalidated any other
340 // SCC's analyses (that's the contract of a CGSCC pass), so
341 // directly handle the CGSCC analysis manager's invalidation here.
342 // FIXME: This isn't quite correct. We need to handle the case where the
343 // pass updated the CG, particularly some child of the current SCC, and
344 // invalidate its analyses.
345 CGAM.invalidate(C, PassPA);
346
347 // Then intersect the preserved set so that invalidation of module
348 // analyses will eventually occur when the module pass completes.
349 PA.intersect(std::move(PassPA));
350 }
351
352 // By definition we preserve the proxy. This precludes *any* invalidation
353 // of CGSCC analyses by the proxy, but that's OK because we've taken
354 // care to invalidate analyses in the CGSCC analysis manager
355 // incrementally above.
356 PA.preserve();
357 return PA;
358 }
359
360 static StringRef name() { return "ModuleToPostOrderCGSCCPassAdaptor"; }
361
362 private:
363 CGSCCPassT Pass;
364 };
365
366 /// \brief A function to deduce a function pass type and wrap it in the
367 /// templated adaptor.
368 template
369 ModuleToPostOrderCGSCCPassAdaptor
370 createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) {
371 return std::move(
372 ModuleToPostOrderCGSCCPassAdaptor(std::move(Pass)));
373 }
374
375 /// \brief A CGSCC analysis which acts as a proxy for a function analysis
376 /// manager.
377 ///
378 /// This primarily proxies invalidation information from the CGSCC analysis
379 /// manager and CGSCC pass manager to a function analysis manager. You should
380 /// never use a function analysis manager from within (transitively) a CGSCC
381 /// pass manager unless your parent CGSCC pass has received a proxy result
382 /// object for it.
383 class FunctionAnalysisManagerCGSCCProxy {
384 public:
385 class Result {
386 public:
387 explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
388 // We have to explicitly define all the special member functions because
389 // MSVC refuses to generate them.
390 Result(const Result &Arg) : FAM(Arg.FAM) {}
391 Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {}
392 Result &operator=(Result RHS) {
393 std::swap(FAM, RHS.FAM);
394 return *this;
395 }
396 ~Result();
397
398 /// \brief Accessor for the \c FunctionAnalysisManager.
399 FunctionAnalysisManager &getManager() { return *FAM; }
400
401 /// \brief Handler for invalidation of the SCC.
402 ///
403 /// If this analysis itself is preserved, then we assume that the set of \c
404 /// Function objects in the \c SCC hasn't changed and thus we don't need
405 /// to invalidate *all* cached data associated with a \c Function* in the \c
406 /// FunctionAnalysisManager.
407 ///
408 /// Regardless of whether this analysis is marked as preserved, all of the
409 /// analyses in the \c FunctionAnalysisManager are potentially invalidated
410 /// based on the set of preserved analyses.
411 bool invalidate(LazyCallGraph::SCC *C, const PreservedAnalyses &PA);
412
413 private:
414 FunctionAnalysisManager *FAM;
415 };
416
417 static void *ID() { return (void *)&PassID; }
418
419 explicit FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManager &FAM)
420 : FAM(&FAM) {}
421 // We have to explicitly define all the special member functions because MSVC
422 // refuses to generate them.
423 FunctionAnalysisManagerCGSCCProxy(
424 const FunctionAnalysisManagerCGSCCProxy &Arg)
425 : FAM(Arg.FAM) {}
426 FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManagerCGSCCProxy &&Arg)
427 : FAM(std::move(Arg.FAM)) {}
428 FunctionAnalysisManagerCGSCCProxy &
429 operator=(FunctionAnalysisManagerCGSCCProxy RHS) {
430 std::swap(FAM, RHS.FAM);
431 return *this;
432 }
433
434 /// \brief Run the analysis pass and create our proxy result object.
435 ///
436 /// This doesn't do any interesting work, it is primarily used to insert our
437 /// proxy result object into the module analysis cache so that we can proxy
438 /// invalidation to the function analysis manager.
439 ///
440 /// In debug builds, it will also assert that the analysis manager is empty
441 /// as no queries should arrive at the function analysis manager prior to
442 /// this analysis being requested.
443 Result run(LazyCallGraph::SCC *C);
444
445 private:
446 static char PassID;
447
448 FunctionAnalysisManager *FAM;
449 };
450
451 /// \brief A function analysis which acts as a proxy for a CGSCC analysis
452 /// manager.
453 ///
454 /// This primarily provides an accessor to a parent CGSCC analysis manager to
455 /// function passes. Only the const interface of the CGSCC analysis manager is
456 /// provided to indicate that once inside of a function analysis pass you
457 /// cannot request a CGSCC analysis to actually run. Instead, the user must
458 /// rely on the \c getCachedResult API.
459 ///
460 /// This proxy *doesn't* manage the invalidation in any way. That is handled by
461 /// the recursive return path of each layer of the pass manager and the
462 /// returned PreservedAnalysis set.
463 class CGSCCAnalysisManagerFunctionProxy {
464 public:
465 /// \brief Result proxy object for \c ModuleAnalysisManagerFunctionProxy.
466 class Result {
467 public:
468 explicit Result(const CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {}
469 // We have to explicitly define all the special member functions because
470 // MSVC refuses to generate them.
471 Result(const Result &Arg) : CGAM(Arg.CGAM) {}
472 Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {}
473 Result &operator=(Result RHS) {
474 std::swap(CGAM, RHS.CGAM);
475 return *this;
476 }
477
478 const CGSCCAnalysisManager &getManager() const { return *CGAM; }
479
480 /// \brief Handle invalidation by ignoring it, this pass is immutable.
481 bool invalidate(Function *) { return false; }
482
483 private:
484 const CGSCCAnalysisManager *CGAM;
485 };
486
487 static void *ID() { return (void *)&PassID; }
488
489 CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManager &CGAM)
490 : CGAM(&CGAM) {}
491 // We have to explicitly define all the special member functions because MSVC
492 // refuses to generate them.
493 CGSCCAnalysisManagerFunctionProxy(
494 const CGSCCAnalysisManagerFunctionProxy &Arg)
495 : CGAM(Arg.CGAM) {}
496 CGSCCAnalysisManagerFunctionProxy(CGSCCAnalysisManagerFunctionProxy &&Arg)
497 : CGAM(std::move(Arg.CGAM)) {}
498 CGSCCAnalysisManagerFunctionProxy &
499 operator=(CGSCCAnalysisManagerFunctionProxy RHS) {
500 std::swap(CGAM, RHS.CGAM);
501 return *this;
502 }
503
504 /// \brief Run the analysis pass and create our proxy result object.
505 /// Nothing to see here, it just forwards the \c CGAM reference into the
506 /// result.
507 Result run(Function *) { return Result(*CGAM); }
508
509 private:
510 static char PassID;
511
512 const CGSCCAnalysisManager *CGAM;
513 };
514
515 /// \brief Adaptor that maps from a SCC to its functions.
516 ///
517 /// Designed to allow composition of a FunctionPass(Manager) and
518 /// a CGSCCPassManager. Note that if this pass is constructed with a pointer
519 /// to a \c CGSCCAnalysisManager it will run the
520 /// \c FunctionAnalysisManagerCGSCCProxy analysis prior to running the function
521 /// pass over the SCC to enable a \c FunctionAnalysisManager to be used
522 /// within this run safely.
523 template class CGSCCToFunctionPassAdaptor {
524 public:
525 explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass)
526 : Pass(std::move(Pass)) {}
527 // We have to explicitly define all the special member functions because MSVC
528 // refuses to generate them.
529 CGSCCToFunctionPassAdaptor(const CGSCCToFunctionPassAdaptor &Arg)
530 : Pass(Arg.Pass) {}
531 CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg)
532 : Pass(std::move(Arg.Pass)) {}
533 friend void swap(CGSCCToFunctionPassAdaptor &LHS, CGSCCToFunctionPassAdaptor &RHS) {
534 using std::swap;
535 swap(LHS.Pass, RHS.Pass);
536 }
537 CGSCCToFunctionPassAdaptor &operator=(CGSCCToFunctionPassAdaptor RHS) {
538 swap(*this, RHS);
539 return *this;
540 }
541
542 /// \brief Runs the function pass across every function in the module.
543 PreservedAnalyses run(LazyCallGraph::SCC *C, CGSCCAnalysisManager *AM) {
544 FunctionAnalysisManager *FAM = nullptr;
545 if (AM)
546 // Setup the function analysis manager from its proxy.
547 FAM = &AM->getResult(C).getManager();
548
549 PreservedAnalyses PA = PreservedAnalyses::all();
550 for (LazyCallGraph::Node *N : *C) {
551 PreservedAnalyses PassPA = Pass.run(&N->getFunction(), FAM);
552
553 // We know that the function pass couldn't have invalidated any other
554 // function's analyses (that's the contract of a function pass), so
555 // directly handle the function analysis manager's invalidation here.
556 if (FAM)
557 FAM->invalidate(&N->getFunction(), PassPA);
558
559 // Then intersect the preserved set so that invalidation of module
560 // analyses will eventually occur when the module pass completes.
561 PA.intersect(std::move(PassPA));
562 }
563
564 // By definition we preserve the proxy. This precludes *any* invalidation
565 // of function analyses by the proxy, but that's OK because we've taken
566 // care to invalidate analyses in the function analysis manager
567 // incrementally above.
568 // FIXME: We need to update the call graph here to account for any deleted
569 // edges!
570 PA.preserve();
571 return PA;
572 }
573
574 static StringRef name() { return "CGSCCToFunctionPassAdaptor"; }
575
576 private:
577 FunctionPassT Pass;
578 };
579
580 /// \brief A function to deduce a function pass type and wrap it in the
581 /// templated adaptor.
582 template
583 CGSCCToFunctionPassAdaptor
584 createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) {
585 return std::move(CGSCCToFunctionPassAdaptor(std::move(Pass)));
586 }
587
588 }
589
590 #endif
0 //===- CGSCCPassManager.cpp - Managing & running CGSCC passes -------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/Analysis/CGSCCPassManager.h"
10 #include "llvm/Support/CommandLine.h"
11 #include "llvm/Support/Debug.h"
12
13 using namespace llvm;
14
15 static cl::opt
16 DebugPM("debug-cgscc-pass-manager", cl::Hidden,
17 cl::desc("Print CGSCC pass management debugging information"));
18
19 PreservedAnalyses CGSCCPassManager::run(LazyCallGraph::SCC *C,
20 CGSCCAnalysisManager *AM) {
21 PreservedAnalyses PA = PreservedAnalyses::all();
22
23 if (DebugPM)
24 dbgs() << "Starting CGSCC pass manager run.\n";
25
26 for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) {
27 if (DebugPM)
28 dbgs() << "Running CGSCC pass: " << Passes[Idx]->name() << "\n";
29
30 PreservedAnalyses PassPA = Passes[Idx]->run(C, AM);
31 if (AM)
32 AM->invalidate(C, PassPA);
33 PA.intersect(std::move(PassPA));
34 }
35
36 if (DebugPM)
37 dbgs() << "Finished CGSCC pass manager run.\n";
38
39 return PA;
40 }
41
42 bool CGSCCAnalysisManager::empty() const {
43 assert(CGSCCAnalysisResults.empty() == CGSCCAnalysisResultLists.empty() &&
44 "The storage and index of analysis results disagree on how many there "
45 "are!");
46 return CGSCCAnalysisResults.empty();
47 }
48
49 void CGSCCAnalysisManager::clear() {
50 CGSCCAnalysisResults.clear();
51 CGSCCAnalysisResultLists.clear();
52 }
53
54 CGSCCAnalysisManager::ResultConceptT &
55 CGSCCAnalysisManager::getResultImpl(void *PassID, LazyCallGraph::SCC *C) {
56 CGSCCAnalysisResultMapT::iterator RI;
57 bool Inserted;
58 std::tie(RI, Inserted) = CGSCCAnalysisResults.insert(std::make_pair(
59 std::make_pair(PassID, C), CGSCCAnalysisResultListT::iterator()));
60
61 // If we don't have a cached result for this function, look up the pass and
62 // run it to produce a result, which we then add to the cache.
63 if (Inserted) {
64 CGSCCAnalysisResultListT &ResultList = CGSCCAnalysisResultLists[C];
65 ResultList.emplace_back(PassID, lookupPass(PassID).run(C, this));
66 RI->second = std::prev(ResultList.end());
67 }
68
69 return *RI->second->second;
70 }
71
72 CGSCCAnalysisManager::ResultConceptT *
73 CGSCCAnalysisManager::getCachedResultImpl(void *PassID,
74 LazyCallGraph::SCC *C) const {
75 CGSCCAnalysisResultMapT::const_iterator RI =
76 CGSCCAnalysisResults.find(std::make_pair(PassID, C));
77 return RI == CGSCCAnalysisResults.end() ? nullptr : &*RI->second->second;
78 }
79
80 void CGSCCAnalysisManager::invalidateImpl(void *PassID, LazyCallGraph::SCC *C) {
81 CGSCCAnalysisResultMapT::iterator RI =
82 CGSCCAnalysisResults.find(std::make_pair(PassID, C));
83 if (RI == CGSCCAnalysisResults.end())
84 return;
85
86 CGSCCAnalysisResultLists[C].erase(RI->second);
87 }
88
89 void CGSCCAnalysisManager::invalidateImpl(LazyCallGraph::SCC *C,
90 const PreservedAnalyses &PA) {
91 // Clear all the invalidated results associated specifically with this
92 // function.
93 SmallVector InvalidatedPassIDs;
94 CGSCCAnalysisResultListT &ResultsList = CGSCCAnalysisResultLists[C];
95 for (CGSCCAnalysisResultListT::iterator I = ResultsList.begin(),
96 E = ResultsList.end();
97 I != E;)
98 if (I->second->invalidate(C, PA)) {
99 InvalidatedPassIDs.push_back(I->first);
100 I = ResultsList.erase(I);
101 } else {
102 ++I;
103 }
104 while (!InvalidatedPassIDs.empty())
105 CGSCCAnalysisResults.erase(
106 std::make_pair(InvalidatedPassIDs.pop_back_val(), C));
107 CGSCCAnalysisResultLists.erase(C);
108 }
109
110 char CGSCCAnalysisManagerModuleProxy::PassID;
111
112 CGSCCAnalysisManagerModuleProxy::Result
113 CGSCCAnalysisManagerModuleProxy::run(Module *M) {
114 assert(CGAM->empty() && "CGSCC analyses ran prior to the module proxy!");
115 return Result(*CGAM);
116 }
117
118 CGSCCAnalysisManagerModuleProxy::Result::~Result() {
119 // Clear out the analysis manager if we're being destroyed -- it means we
120 // didn't even see an invalidate call when we got invalidated.
121 CGAM->clear();
122 }
123
124 bool CGSCCAnalysisManagerModuleProxy::Result::invalidate(
125 Module *M, const PreservedAnalyses &PA) {
126 // If this proxy isn't marked as preserved, then we can't even invalidate
127 // individual CGSCC analyses, there may be an invalid set of SCC objects in
128 // the cache making it impossible to incrementally preserve them.
129 // Just clear the entire manager.
130 if (!PA.preserved(ID()))
131 CGAM->clear();
132
133 // Return false to indicate that this result is still a valid proxy.
134 return false;
135 }
136
137 char ModuleAnalysisManagerCGSCCProxy::PassID;
138
139 char FunctionAnalysisManagerCGSCCProxy::PassID;
140
141 FunctionAnalysisManagerCGSCCProxy::Result
142 FunctionAnalysisManagerCGSCCProxy::run(LazyCallGraph::SCC *C) {
143 assert(FAM->empty() && "Function analyses ran prior to the CGSCC proxy!");
144 return Result(*FAM);
145 }
146
147 FunctionAnalysisManagerCGSCCProxy::Result::~Result() {
148 // Clear out the analysis manager if we're being destroyed -- it means we
149 // didn't even see an invalidate call when we got invalidated.
150 FAM->clear();
151 }
152
153 bool FunctionAnalysisManagerCGSCCProxy::Result::invalidate(
154 LazyCallGraph::SCC *C, const PreservedAnalyses &PA) {
155 // If this proxy isn't marked as preserved, then we can't even invalidate
156 // individual function analyses, there may be an invalid set of Function
157 // objects in the cache making it impossible to incrementally preserve them.
158 // Just clear the entire manager.
159 if (!PA.preserved(ID()))
160 FAM->clear();
161
162 // Return false to indicate that this result is still a valid proxy.
163 return false;
164 }
165
166 char CGSCCAnalysisManagerFunctionProxy::PassID;
99 BranchProbabilityInfo.cpp
1010 CFG.cpp
1111 CFGPrinter.cpp
12 CGSCCPassManager.cpp
1213 CaptureTracking.cpp
1314 CostModel.cpp
1415 CodeMetrics.cpp
104104 ; RUN: | FileCheck %s --check-prefix=CHECK-UNBALANCED10
105105 ; CHECK-UNBALANCED10: unable to parse pass pipeline description
106106
107 ; RUN: opt -disable-output -debug-pass-manager -debug-cgscc-pass-manager \
108 ; RUN: -passes=no-op-cgscc,no-op-cgscc %s 2>&1 \
109 ; RUN: | FileCheck %s --check-prefix=CHECK-TWO-NOOP-CG
110 ; CHECK-TWO-NOOP-CG: Starting module pass manager
111 ; CHECK-TWO-NOOP-CG: Running module pass: ModuleToPostOrderCGSCCPassAdaptor
112 ; CHECK-TWO-NOOP-CG: Starting CGSCC pass manager
113 ; CHECK-TWO-NOOP-CG: Running CGSCC pass: NoOpCGSCCPass
114 ; CHECK-TWO-NOOP-CG: Running CGSCC pass: NoOpCGSCCPass
115 ; CHECK-TWO-NOOP-CG: Finished CGSCC pass manager
116 ; CHECK-TWO-NOOP-CG: Finished module pass manager
117
118 ; RUN: opt -disable-output -debug-pass-manager -debug-cgscc-pass-manager \
119 ; RUN: -passes='module(function(no-op-function),cgscc(no-op-cgscc,function(no-op-function),no-op-cgscc),function(no-op-function))' %s 2>&1 \
120 ; RUN: | FileCheck %s --check-prefix=CHECK-NESTED-MP-CG-FP
121 ; CHECK-NESTED-MP-CG-FP: Starting module pass manager
122 ; CHECK-NESTED-MP-CG-FP: Starting module pass manager
123 ; CHECK-NESTED-MP-CG-FP: Running module pass: ModuleToFunctionPassAdaptor
124 ; CHECK-NESTED-MP-CG-FP: Starting function pass manager
125 ; CHECK-NESTED-MP-CG-FP: Running function pass: NoOpFunctionPass
126 ; CHECK-NESTED-MP-CG-FP: Finished function pass manager
127 ; CHECK-NESTED-MP-CG-FP: Running module pass: ModuleToPostOrderCGSCCPassAdaptor
128 ; CHECK-NESTED-MP-CG-FP: Starting CGSCC pass manager
129 ; CHECK-NESTED-MP-CG-FP: Running CGSCC pass: NoOpCGSCCPass
130 ; CHECK-NESTED-MP-CG-FP: Running CGSCC pass: CGSCCToFunctionPassAdaptor
131 ; CHECK-NESTED-MP-CG-FP: Starting function pass manager
132 ; CHECK-NESTED-MP-CG-FP: Running function pass: NoOpFunctionPass
133 ; CHECK-NESTED-MP-CG-FP: Finished function pass manager
134 ; CHECK-NESTED-MP-CG-FP: Running CGSCC pass: NoOpCGSCCPass
135 ; CHECK-NESTED-MP-CG-FP: Finished CGSCC pass manager
136 ; CHECK-NESTED-MP-CG-FP: Running module pass: ModuleToFunctionPassAdaptor
137 ; CHECK-NESTED-MP-CG-FP: Starting function pass manager
138 ; CHECK-NESTED-MP-CG-FP: Running function pass: NoOpFunctionPass
139 ; CHECK-NESTED-MP-CG-FP: Finished function pass manager
140 ; CHECK-NESTED-MP-CG-FP: Finished module pass manager
141 ; CHECK-NESTED-MP-CG-FP: Finished module pass manager
142
107143 define void @f() {
108144 ret void
109145 }
1515 #include "NewPMDriver.h"
1616 #include "Passes.h"
1717 #include "llvm/ADT/StringRef.h"
18 #include "llvm/Analysis/CGSCCPassManager.h"
1819 #include "llvm/Analysis/LazyCallGraph.h"
1920 #include "llvm/Bitcode/BitcodeWriterPass.h"
2021 #include "llvm/IR/IRPrintingPasses.h"
3334 tool_output_file *Out, StringRef PassPipeline,
3435 OutputKind OK, VerifierKind VK) {
3536 FunctionAnalysisManager FAM;
37 CGSCCAnalysisManager CGAM;
3638 ModuleAnalysisManager MAM;
3739
3840 #define MODULE_ANALYSIS(NAME, CREATE_PASS) \
3941 MAM.registerPass(CREATE_PASS);
42 #include "PassRegistry.def"
43
44 #define CGSCC_ANALYSIS(NAME, CREATE_PASS) \
45 CGAM.registerPass(CREATE_PASS);
4046 #include "PassRegistry.def"
4147
4248 #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
4551
4652 // Cross register the analysis managers through their proxies.
4753 MAM.registerPass(FunctionAnalysisManagerModuleProxy(FAM));
54 MAM.registerPass(CGSCCAnalysisManagerModuleProxy(CGAM));
55 CGAM.registerPass(FunctionAnalysisManagerCGSCCProxy(FAM));
56 CGAM.registerPass(ModuleAnalysisManagerCGSCCProxy(MAM));
57 FAM.registerPass(CGSCCAnalysisManagerFunctionProxy(CGAM));
4858 FAM.registerPass(ModuleAnalysisManagerFunctionProxy(MAM));
4959
5060 ModulePassManager MPM;
2828 MODULE_PASS("print-cg", LazyCallGraphPrinterPass(dbgs()))
2929 #undef MODULE_PASS
3030
31 #ifndef CGSCC_ANALYSIS
32 #define CGSCC_ANALYSIS(NAME, CREATE_PASS)
33 #endif
34 #undef CGSCC_ANALYSIS
35
36 #ifndef CGSCC_PASS
37 #define CGSCC_PASS(NAME, CREATE_PASS)
38 #endif
39 #undef CGSCC_PASS
40
3141 #ifndef FUNCTION_ANALYSIS
3242 #define FUNCTION_ANALYSIS(NAME, CREATE_PASS)
3343 #endif
1414 //===----------------------------------------------------------------------===//
1515
1616 #include "Passes.h"
17 #include "llvm/Analysis/CGSCCPassManager.h"
1718 #include "llvm/Analysis/LazyCallGraph.h"
1819 #include "llvm/IR/IRPrintingPasses.h"
1920 #include "llvm/IR/PassManager.h"
3031 static StringRef name() { return "NoOpModulePass"; }
3132 };
3233
34 /// \brief No-op CGSCC pass which does nothing.
35 struct NoOpCGSCCPass {
36 PreservedAnalyses run(LazyCallGraph::SCC *C) {
37 return PreservedAnalyses::all();
38 }
39 static StringRef name() { return "NoOpCGSCCPass"; }
40 };
41
3342 /// \brief No-op function pass which does nothing.
3443 struct NoOpFunctionPass {
3544 PreservedAnalyses run(Function *F) { return PreservedAnalyses::all(); }
4756 return false;
4857 }
4958
59 static bool isCGSCCPassName(StringRef Name) {
60 if (Name == "no-op-cgscc") return true;
61
62 #define CGSCC_PASS(NAME, CREATE_PASS) if (Name == NAME) return true;
63 #include "PassRegistry.def"
64
65 return false;
66 }
67
5068 static bool isFunctionPassName(StringRef Name) {
5169 if (Name == "no-op-function") return true;
5270
6583 #define MODULE_PASS(NAME, CREATE_PASS) \
6684 if (Name == NAME) { \
6785 MPM.addPass(CREATE_PASS); \
86 return true; \
87 }
88 #include "PassRegistry.def"
89
90 return false;
91 }
92
93 static bool parseCGSCCPassName(CGSCCPassManager &CGPM, StringRef Name) {
94 if (Name == "no-op-cgscc") {
95 CGPM.addPass(NoOpCGSCCPass());
96 return true;
97 }
98
99 #define CGSCC_PASS(NAME, CREATE_PASS) \
100 if (Name == NAME) { \
101 CGPM.addPass(CREATE_PASS); \
68102 return true; \
69103 }
70104 #include "PassRegistry.def"
125159 }
126160 }
127161
162 static bool parseCGSCCPassPipeline(CGSCCPassManager &CGPM,
163 StringRef &PipelineText,
164 bool VerifyEachPass) {
165 for (;;) {
166 // Parse nested pass managers by recursing.
167 if (PipelineText.startswith("cgscc(")) {
168 CGSCCPassManager NestedCGPM;
169
170 // Parse the inner pipeline into the nested manager.
171 PipelineText = PipelineText.substr(strlen("cgscc("));
172 if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass) ||
173 PipelineText.empty())
174 return false;
175 assert(PipelineText[0] == ')');
176 PipelineText = PipelineText.substr(1);
177
178 // Add the nested pass manager with the appropriate adaptor.
179 CGPM.addPass(std::move(NestedCGPM));
180 } else if (PipelineText.startswith("function(")) {
181 FunctionPassManager NestedFPM;
182
183 // Parse the inner pipeline inte the nested manager.
184 PipelineText = PipelineText.substr(strlen("function("));
185 if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass) ||
186 PipelineText.empty())
187 return false;
188 assert(PipelineText[0] == ')');
189 PipelineText = PipelineText.substr(1);
190
191 // Add the nested pass manager with the appropriate adaptor.
192 CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(NestedFPM)));
193 } else {
194 // Otherwise try to parse a pass name.
195 size_t End = PipelineText.find_first_of(",)");
196 if (!parseCGSCCPassName(CGPM, PipelineText.substr(0, End)))
197 return false;
198 // FIXME: No verifier support for CGSCC passes!
199
200 PipelineText = PipelineText.substr(End);
201 }
202
203 if (PipelineText.empty() || PipelineText[0] == ')')
204 return true;
205
206 assert(PipelineText[0] == ',');
207 PipelineText = PipelineText.substr(1);
208 }
209 }
210
128211 static bool parseModulePassPipeline(ModulePassManager &MPM,
129212 StringRef &PipelineText,
130213 bool VerifyEachPass) {
143226
144227 // Now add the nested manager as a module pass.
145228 MPM.addPass(std::move(NestedMPM));
229 } else if (PipelineText.startswith("cgscc(")) {
230 CGSCCPassManager NestedCGPM;
231
232 // Parse the inner pipeline inte the nested manager.
233 PipelineText = PipelineText.substr(strlen("cgscc("));
234 if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass) ||
235 PipelineText.empty())
236 return false;
237 assert(PipelineText[0] == ')');
238 PipelineText = PipelineText.substr(1);
239
240 // Add the nested pass manager with the appropriate adaptor.
241 MPM.addPass(
242 createModuleToPostOrderCGSCCPassAdaptor(std::move(NestedCGPM)));
146243 } else if (PipelineText.startswith("function(")) {
147244 FunctionPassManager NestedFPM;
148245
184281 if (PipelineText.startswith("module("))
185282 return parseModulePassPipeline(MPM, PipelineText, VerifyEachPass) &&
186283 PipelineText.empty();
284 if (PipelineText.startswith("cgscc(")) {
285 CGSCCPassManager CGPM;
286 if (!parseCGSCCPassPipeline(CGPM, PipelineText, VerifyEachPass) ||
287 !PipelineText.empty())
288 return false;
289 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
290 return true;
291 }
187292 if (PipelineText.startswith("function(")) {
188293 FunctionPassManager FPM;
189294 if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) ||
200305 return parseModulePassPipeline(MPM, PipelineText, VerifyEachPass) &&
201306 PipelineText.empty();
202307
308 if (isCGSCCPassName(FirstName)) {
309 CGSCCPassManager CGPM;
310 if (!parseCGSCCPassPipeline(CGPM, PipelineText, VerifyEachPass) ||
311 !PipelineText.empty())
312 return false;
313 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
314 return true;
315 }
316
203317 if (isFunctionPassName(FirstName)) {
204318 FunctionPassManager FPM;
205319 if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) ||