llvm.org GIT mirror llvm / 1cb1b30
[NewPM] Fix a nasty bug with analysis invalidation in the new PM. The issue here is that we actually allow CGSCC passes to mutate IR (and therefore invalidate analyses) outside of the current SCC. At a minimum, we need to support mutating parent and ancestor SCCs to support the ArgumentPromotion pass which rewrites all calls to a function. However, the analysis invalidation infrastructure is heavily based around not needing to invalidate the same IR-unit at multiple levels. With Loop passes for example, they don't invalidate other Loops. So we need to customize how we handle CGSCC invalidation. Doing this without gratuitously re-running analyses is even harder. I've avoided most of these by using an out-of-band preserved set to accumulate the cross-SCC invalidation, but it still isn't perfect in the case of re-visiting the same SCC repeatedly *but* it coming off the worklist. Unclear how important this use case really is, but I wanted to call it out. Another wrinkle is that in order for this to successfully propagate to function analyses, we have to make sure we have a proxy from the SCC to the Function level. That requires pre-creating the necessary proxy. The motivating test case now works cleanly and is added for ArgumentPromotion. Thanks for the review from Philip and Wei! Differential Revision: https://reviews.llvm.org/D59869 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@357137 91177308-0d34-0410-b5e6-96231b3b80d8 Chandler Carruth 4 months ago
8 changed file(s) with 300 addition(s) and 186 deletion(s). Raw diff Collapse all Expand all
290290 /// post-order walk.
291291 LazyCallGraph::SCC *UpdatedC;
292292
293 /// Preserved analyses across SCCs.
294 ///
295 /// We specifically want to allow CGSCC passes to mutate ancestor IR
296 /// (changing both the CG structure and the function IR itself). However,
297 /// this means we need to take special care to correctly mark what analyses
298 /// are preserved *across* SCCs. We have to track this out-of-band here
299 /// because within the main `PassManeger` infrastructure we need to mark
300 /// everything within an SCC as preserved in order to avoid repeatedly
301 /// invalidating the same analyses as we unnest pass managers and adaptors.
302 /// So we track the cross-SCC version of the preserved analyses here from any
303 /// code that does direct invalidation of SCC analyses, and then use it
304 /// whenever we move forward in the post-order walk of SCCs before running
305 /// passes over the new SCC.
306 PreservedAnalyses CrossSCCPA;
307
293308 /// A hacky area where the inliner can retain history about inlining
294309 /// decisions that mutated the call graph's SCC structure in order to avoid
295310 /// infinite inlining. See the comments in the inliner's CG update logic.
337352 }
338353
339354 /// Runs the CGSCC pass across every SCC in the module.
340 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) {
341 // Setup the CGSCC analysis manager from its proxy.
342 CGSCCAnalysisManager &CGAM =
343 AM.getResult(M).getManager();
344
345 // Get the call graph for this module.
346 LazyCallGraph &CG = AM.getResult(M);
347
348 // We keep worklists to allow us to push more work onto the pass manager as
349 // the passes are run.
350 SmallPriorityWorklist RCWorklist;
351 SmallPriorityWorklist CWorklist;
352
353 // Keep sets for invalidated SCCs and RefSCCs that should be skipped when
354 // iterating off the worklists.
355 SmallPtrSet InvalidRefSCCSet;
356 SmallPtrSet InvalidSCCSet;
357
358 SmallDenseSet, 4>
359 InlinedInternalEdges;
360
361 CGSCCUpdateResult UR = {RCWorklist, CWorklist, InvalidRefSCCSet,
362 InvalidSCCSet, nullptr, nullptr,
363 InlinedInternalEdges};
364
365 // Request PassInstrumentation from analysis manager, will use it to run
366 // instrumenting callbacks for the passes later.
367 PassInstrumentation PI = AM.getResult(M);
368
369 PreservedAnalyses PA = PreservedAnalyses::all();
370 CG.buildRefSCCs();
371 for (auto RCI = CG.postorder_ref_scc_begin(),
372 RCE = CG.postorder_ref_scc_end();
373 RCI != RCE;) {
374 assert(RCWorklist.empty() &&
375 "Should always start with an empty RefSCC worklist");
376 // The postorder_ref_sccs range we are walking is lazily constructed, so
377 // we only push the first one onto the worklist. The worklist allows us
378 // to capture *new* RefSCCs created during transformations.
379 //
380 // We really want to form RefSCCs lazily because that makes them cheaper
381 // to update as the program is simplified and allows us to have greater
382 // cache locality as forming a RefSCC touches all the parts of all the
383 // functions within that RefSCC.
384 //
385 // We also eagerly increment the iterator to the next position because
386 // the CGSCC passes below may delete the current RefSCC.
387 RCWorklist.insert(&*RCI++);
388
389 do {
390 LazyCallGraph::RefSCC *RC = RCWorklist.pop_back_val();
391 if (InvalidRefSCCSet.count(RC)) {
392 LLVM_DEBUG(dbgs() << "Skipping an invalid RefSCC...\n");
393 continue;
394 }
395
396 assert(CWorklist.empty() &&
397 "Should always start with an empty SCC worklist");
398
399 LLVM_DEBUG(dbgs() << "Running an SCC pass across the RefSCC: " << *RC
400 << "\n");
401
402 // Push the initial SCCs in reverse post-order as we'll pop off the
403 // back and so see this in post-order.
404 for (LazyCallGraph::SCC &C : llvm::reverse(*RC))
405 CWorklist.insert(&C);
406
407 do {
408 LazyCallGraph::SCC *C = CWorklist.pop_back_val();
409 // Due to call graph mutations, we may have invalid SCCs or SCCs from
410 // other RefSCCs in the worklist. The invalid ones are dead and the
411 // other RefSCCs should be queued above, so we just need to skip both
412 // scenarios here.
413 if (InvalidSCCSet.count(C)) {
414 LLVM_DEBUG(dbgs() << "Skipping an invalid SCC...\n");
415 continue;
416 }
417 if (&C->getOuterRefSCC() != RC) {
418 LLVM_DEBUG(dbgs()
419 << "Skipping an SCC that is now part of some other "
420 "RefSCC...\n");
421 continue;
422 }
423
424 do {
425 // Check that we didn't miss any update scenario.
426 assert(!InvalidSCCSet.count(C) && "Processing an invalid SCC!");
427 assert(C->begin() != C->end() && "Cannot have an empty SCC!");
428 assert(&C->getOuterRefSCC() == RC &&
429 "Processing an SCC in a different RefSCC!");
430
431 UR.UpdatedRC = nullptr;
432 UR.UpdatedC = nullptr;
433
434 // Check the PassInstrumentation's BeforePass callbacks before
435 // running the pass, skip its execution completely if asked to
436 // (callback returns false).
437 if (!PI.runBeforePass(Pass, *C))
438 continue;
439
440 PreservedAnalyses PassPA = Pass.run(*C, CGAM, CG, UR);
441
442 if (UR.InvalidatedSCCs.count(C))
443 PI.runAfterPassInvalidated(Pass);
444 else
445 PI.runAfterPass(Pass, *C);
446
447 // Update the SCC and RefSCC if necessary.
448 C = UR.UpdatedC ? UR.UpdatedC : C;
449 RC = UR.UpdatedRC ? UR.UpdatedRC : RC;
450
451 // If the CGSCC pass wasn't able to provide a valid updated SCC,
452 // the current SCC may simply need to be skipped if invalid.
453 if (UR.InvalidatedSCCs.count(C)) {
454 LLVM_DEBUG(dbgs()
455 << "Skipping invalidated root or island SCC!\n");
456 break;
457 }
458 // Check that we didn't miss any update scenario.
459 assert(C->begin() != C->end() && "Cannot have an empty SCC!");
460
461 // We handle invalidating the CGSCC analysis manager's information
462 // for the (potentially updated) SCC here. Note that any other SCCs
463 // whose structure has changed should have been invalidated by
464 // whatever was updating the call graph. This SCC gets invalidated
465 // late as it contains the nodes that were actively being
466 // processed.
467 CGAM.invalidate(*C, PassPA);
468
469 // Then intersect the preserved set so that invalidation of module
470 // analyses will eventually occur when the module pass completes.
471 PA.intersect(std::move(PassPA));
472
473 // The pass may have restructured the call graph and refined the
474 // current SCC and/or RefSCC. We need to update our current SCC and
475 // RefSCC pointers to follow these. Also, when the current SCC is
476 // refined, re-run the SCC pass over the newly refined SCC in order
477 // to observe the most precise SCC model available. This inherently
478 // cannot cycle excessively as it only happens when we split SCCs
479 // apart, at most converging on a DAG of single nodes.
480 // FIXME: If we ever start having RefSCC passes, we'll want to
481 // iterate there too.
482 if (UR.UpdatedC)
483 LLVM_DEBUG(dbgs()
484 << "Re-running SCC passes after a refinement of the "
485 "current SCC: "
486 << *UR.UpdatedC << "\n");
487
488 // Note that both `C` and `RC` may at this point refer to deleted,
489 // invalid SCC and RefSCCs respectively. But we will short circuit
490 // the processing when we check them in the loop above.
491 } while (UR.UpdatedC);
492 } while (!CWorklist.empty());
493
494 // We only need to keep internal inlined edge information within
495 // a RefSCC, clear it to save on space and let the next time we visit
496 // any of these functions have a fresh start.
497 InlinedInternalEdges.clear();
498 } while (!RCWorklist.empty());
499 }
500
501 // By definition we preserve the call garph, all SCC analyses, and the
502 // analysis proxies by handling them above and in any nested pass managers.
503 PA.preserveSet>();
504 PA.preserve();
505 PA.preserve();
506 PA.preserve();
507 return PA;
508 }
355 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
509356
510357 private:
511358 CGSCCPassT Pass;
871718 return DevirtSCCRepeatedPass(std::move(Pass), MaxIterations);
872719 }
873720
721 // Out-of-line implementation details for templates below this point.
722
723 template
724 PreservedAnalyses
725 ModuleToPostOrderCGSCCPassAdaptor::run(Module &M,
726 ModuleAnalysisManager &AM) {
727 // Setup the CGSCC analysis manager from its proxy.
728 CGSCCAnalysisManager &CGAM =
729 AM.getResult(M).getManager();
730
731 // Get the call graph for this module.
732 LazyCallGraph &CG = AM.getResult(M);
733
734 // We keep worklists to allow us to push more work onto the pass manager as
735 // the passes are run.
736 SmallPriorityWorklist RCWorklist;
737 SmallPriorityWorklist CWorklist;
738
739 // Keep sets for invalidated SCCs and RefSCCs that should be skipped when
740 // iterating off the worklists.
741 SmallPtrSet InvalidRefSCCSet;
742 SmallPtrSet InvalidSCCSet;
743
744 SmallDenseSet, 4>
745 InlinedInternalEdges;
746
747 CGSCCUpdateResult UR = {
748 RCWorklist, CWorklist, InvalidRefSCCSet, InvalidSCCSet,
749 nullptr, nullptr, PreservedAnalyses::all(), InlinedInternalEdges};
750
751 // Request PassInstrumentation from analysis manager, will use it to run
752 // instrumenting callbacks for the passes later.
753 PassInstrumentation PI = AM.getResult(M);
754
755 PreservedAnalyses PA = PreservedAnalyses::all();
756 CG.buildRefSCCs();
757 for (auto RCI = CG.postorder_ref_scc_begin(),
758 RCE = CG.postorder_ref_scc_end();
759 RCI != RCE;) {
760 assert(RCWorklist.empty() &&
761 "Should always start with an empty RefSCC worklist");
762 // The postorder_ref_sccs range we are walking is lazily constructed, so
763 // we only push the first one onto the worklist. The worklist allows us
764 // to capture *new* RefSCCs created during transformations.
765 //
766 // We really want to form RefSCCs lazily because that makes them cheaper
767 // to update as the program is simplified and allows us to have greater
768 // cache locality as forming a RefSCC touches all the parts of all the
769 // functions within that RefSCC.
770 //
771 // We also eagerly increment the iterator to the next position because
772 // the CGSCC passes below may delete the current RefSCC.
773 RCWorklist.insert(&*RCI++);
774
775 do {
776 LazyCallGraph::RefSCC *RC = RCWorklist.pop_back_val();
777 if (InvalidRefSCCSet.count(RC)) {
778 LLVM_DEBUG(dbgs() << "Skipping an invalid RefSCC...\n");
779 continue;
780 }
781
782 assert(CWorklist.empty() &&
783 "Should always start with an empty SCC worklist");
784
785 LLVM_DEBUG(dbgs() << "Running an SCC pass across the RefSCC: " << *RC
786 << "\n");
787
788 // Push the initial SCCs in reverse post-order as we'll pop off the
789 // back and so see this in post-order.
790 for (LazyCallGraph::SCC &C : llvm::reverse(*RC))
791 CWorklist.insert(&C);
792
793 do {
794 LazyCallGraph::SCC *C = CWorklist.pop_back_val();
795 // Due to call graph mutations, we may have invalid SCCs or SCCs from
796 // other RefSCCs in the worklist. The invalid ones are dead and the
797 // other RefSCCs should be queued above, so we just need to skip both
798 // scenarios here.
799 if (InvalidSCCSet.count(C)) {
800 LLVM_DEBUG(dbgs() << "Skipping an invalid SCC...\n");
801 continue;
802 }
803 if (&C->getOuterRefSCC() != RC) {
804 LLVM_DEBUG(dbgs() << "Skipping an SCC that is now part of some other "
805 "RefSCC...\n");
806 continue;
807 }
808
809 // Ensure we can proxy analysis updates from from the CGSCC analysis
810 // manager into the Function analysis manager by getting a proxy here.
811 // FIXME: This seems like a bit of a hack. We should find a cleaner
812 // or more costructive way to ensure this happens.
813 (void)CGAM.getResult(*C, CG);
814
815 // Each time we visit a new SCC pulled off the worklist,
816 // a transformation of a child SCC may have also modified this parent
817 // and invalidated analyses. So we invalidate using the update record's
818 // cross-SCC preserved set. This preserved set is intersected by any
819 // CGSCC pass that handles invalidation (primarily pass managers) prior
820 // to marking its SCC as preserved. That lets us track everything that
821 // might need invalidation across SCCs without excessive invalidations
822 // on a single SCC.
823 //
824 // This essentially allows SCC passes to freely invalidate analyses
825 // of any ancestor SCC. If this becomes detrimental to successfully
826 // caching analyses, we could force each SCC pass to manually
827 // invalidate the analyses for any SCCs other than themselves which
828 // are mutated. However, that seems to lose the robustness of the
829 // pass-manager driven invalidation scheme.
830 //
831 // FIXME: This is redundant in one case -- the top of the worklist may
832 // *also* be the same SCC we just ran over (and invalidated for). In
833 // that case, we'll end up doing a redundant invalidation here as
834 // a consequence.
835 CGAM.invalidate(*C, UR.CrossSCCPA);
836
837 do {
838 // Check that we didn't miss any update scenario.
839 assert(!InvalidSCCSet.count(C) && "Processing an invalid SCC!");
840 assert(C->begin() != C->end() && "Cannot have an empty SCC!");
841 assert(&C->getOuterRefSCC() == RC &&
842 "Processing an SCC in a different RefSCC!");
843
844 UR.UpdatedRC = nullptr;
845 UR.UpdatedC = nullptr;
846
847 // Check the PassInstrumentation's BeforePass callbacks before
848 // running the pass, skip its execution completely if asked to
849 // (callback returns false).
850 if (!PI.runBeforePass(Pass, *C))
851 continue;
852
853 PreservedAnalyses PassPA = Pass.run(*C, CGAM, CG, UR);
854
855 if (UR.InvalidatedSCCs.count(C))
856 PI.runAfterPassInvalidated(Pass);
857 else
858 PI.runAfterPass(Pass, *C);
859
860 // Update the SCC and RefSCC if necessary.
861 C = UR.UpdatedC ? UR.UpdatedC : C;
862 RC = UR.UpdatedRC ? UR.UpdatedRC : RC;
863
864 // If the CGSCC pass wasn't able to provide a valid updated SCC,
865 // the current SCC may simply need to be skipped if invalid.
866 if (UR.InvalidatedSCCs.count(C)) {
867 LLVM_DEBUG(dbgs() << "Skipping invalidated root or island SCC!\n");
868 break;
869 }
870 // Check that we didn't miss any update scenario.
871 assert(C->begin() != C->end() && "Cannot have an empty SCC!");
872
873 // We handle invalidating the CGSCC analysis manager's information
874 // for the (potentially updated) SCC here. Note that any other SCCs
875 // whose structure has changed should have been invalidated by
876 // whatever was updating the call graph. This SCC gets invalidated
877 // late as it contains the nodes that were actively being
878 // processed.
879 CGAM.invalidate(*C, PassPA);
880
881 // Then intersect the preserved set so that invalidation of module
882 // analyses will eventually occur when the module pass completes.
883 // Also intersect with the cross-SCC preserved set to capture any
884 // cross-SCC invalidation.
885 UR.CrossSCCPA.intersect(PassPA);
886 PA.intersect(std::move(PassPA));
887
888 // The pass may have restructured the call graph and refined the
889 // current SCC and/or RefSCC. We need to update our current SCC and
890 // RefSCC pointers to follow these. Also, when the current SCC is
891 // refined, re-run the SCC pass over the newly refined SCC in order
892 // to observe the most precise SCC model available. This inherently
893 // cannot cycle excessively as it only happens when we split SCCs
894 // apart, at most converging on a DAG of single nodes.
895 // FIXME: If we ever start having RefSCC passes, we'll want to
896 // iterate there too.
897 if (UR.UpdatedC)
898 LLVM_DEBUG(dbgs()
899 << "Re-running SCC passes after a refinement of the "
900 "current SCC: "
901 << *UR.UpdatedC << "\n");
902
903 // Note that both `C` and `RC` may at this point refer to deleted,
904 // invalid SCC and RefSCCs respectively. But we will short circuit
905 // the processing when we check them in the loop above.
906 } while (UR.UpdatedC);
907 } while (!CWorklist.empty());
908
909 // We only need to keep internal inlined edge information within
910 // a RefSCC, clear it to save on space and let the next time we visit
911 // any of these functions have a fresh start.
912 InlinedInternalEdges.clear();
913 } while (!RCWorklist.empty());
914 }
915
916 // By definition we preserve the call garph, all SCC analyses, and the
917 // analysis proxies by handling them above and in any nested pass managers.
918 PA.preserveSet>();
919 PA.preserve();
920 PA.preserve();
921 PA.preserve();
922 return PA;
923 }
924
874925 // Clear out the debug logging macro.
875926 #undef DEBUG_TYPE
876927
108108 // in the new pass manager so it is currently omitted.
109109 // ...getContext().yield();
110110 }
111
112 // Before we mark all of *this* SCC's analyses as preserved below, intersect
113 // this with the cross-SCC preserved analysis set. This is used to allow
114 // CGSCC passes to mutate ancestor SCCs and still trigger proper invalidation
115 // for them.
116 UR.CrossSCCPA.intersect(PA);
111117
112118 // Invalidation was handled after each pass in the above loop for the current
113119 // SCC. Therefore, the remaining analysis results in the AnalysisManager are
2323 ; CHECK-CGSCC-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*(FunctionAnalysisManager|AnalysisManager<.*Function.*>).*}},{{.*}}Module>
2424 ; CHECK-CGSCC-PASS-NEXT: Running analysis: LazyCallGraphAnalysis
2525 ; CHECK-CGSCC-PASS-NEXT: Running analysis: TargetLibraryAnalysis
26 ; CHECK-CGSCC-PASS-NEXT: Running analysis: FunctionAnalysisManagerCGSCCProxy
2627 ; CHECK-CGSCC-PASS-NEXT: Running analysis: PassInstrumentationAnalysis
28 ; CHECK-CGSCC-PASS-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph::SCC{{.*}}>
2729 ; CHECK-CGSCC-PASS-NEXT: Starting CGSCC pass manager run
2830 ; CHECK-CGSCC-PASS-NEXT: Running pass: NoOpCGSCCPass
2931 ; CHECK-CGSCC-PASS-NEXT: Finished CGSCC pass manager run
409411 ; CHECK-REPEAT-CGSCC-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*(FunctionAnalysisManager|AnalysisManager<.*Function.*>).*}},{{.*}}Module>
410412 ; CHECK-REPEAT-CGSCC-PASS-NEXT: Running analysis: LazyCallGraphAnalysis
411413 ; CHECK-REPEAT-CGSCC-PASS-NEXT: Running analysis: TargetLibraryAnalysis
414 ; CHECK-REPEAT-CGSCC-PASS-NEXT: Running analysis: FunctionAnalysisManagerCGSCCProxy
412415 ; CHECK-REPEAT-CGSCC-PASS-NEXT: Running analysis: PassInstrumentationAnalysis
416 ; CHECK-REPEAT-CGSCC-PASS-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph::SCC{{.*}}>
413417 ; CHECK-REPEAT-CGSCC-PASS-NEXT: Starting CGSCC pass manager run
414418 ; CHECK-REPEAT-CGSCC-PASS-NEXT: Running pass: RepeatedPass
415419 ; CHECK-REPEAT-CGSCC-PASS-NEXT: Starting CGSCC pass manager run
116116 ; CHECK-O-NEXT: Running pass: ModuleToPostOrderCGSCCPassAdaptor<{{.*}}LazyCallGraph{{.*}}>
117117 ; CHECK-O-NEXT: Running analysis: InnerAnalysisManagerProxy
118118 ; CHECK-O-NEXT: Running analysis: LazyCallGraphAnalysis
119 ; CHECK-O-NEXT: Running analysis: FunctionAnalysisManagerCGSCCProxy
119120 ; CHECK-O-NEXT: Running analysis: PassInstrumentationAnalysis
121 ; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph::SCC{{.*}}>
120122 ; CHECK-O-NEXT: Starting CGSCC pass manager run.
121123 ; CHECK-O-NEXT: Running pass: InlinerPass
122 ; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph{{.*}}>
123 ; CHECK-O-NEXT: Running analysis: FunctionAnalysisManagerCGSCCProxy
124124 ; CHECK-O-NEXT: Running pass: PostOrderFunctionAttrsPass
125125 ; CHECK-O3-NEXT: Running pass: ArgumentPromotionPass
126126 ; CHECK-O-NEXT: Running pass: CGSCCToFunctionPassAdaptor<{{.*}}PassManager{{.*}}>
9797 ; CHECK-O-NEXT: Running pass: ModuleToPostOrderCGSCCPassAdaptor<{{.*}}LazyCallGraph{{.*}}>
9898 ; CHECK-O-NEXT: Running analysis: InnerAnalysisManagerProxy
9999 ; CHECK-O-NEXT: Running analysis: LazyCallGraphAnalysis
100 ; CHECK-O-NEXT: Running analysis: FunctionAnalysisManagerCGSCCProxy
100101 ; CHECK-O-NEXT: Running analysis: PassInstrumentationAnalysis
102 ; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph::SCC{{.*}}>
101103 ; CHECK-O-NEXT: Starting CGSCC pass manager run.
102104 ; CHECK-O-NEXT: Running pass: InlinerPass
103 ; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph{{.*}}>
104 ; CHECK-O-NEXT: Running analysis: FunctionAnalysisManagerCGSCCProxy
105105 ; CHECK-O-NEXT: Running pass: PostOrderFunctionAttrsPass
106106 ; CHECK-O3-NEXT: Running pass: ArgumentPromotionPass
107107 ; CHECK-O-NEXT: Running pass: CGSCCToFunctionPassAdaptor<{{.*}}PassManager{{.*}}>
0 ; Check that when argument promotion changes a function in some parent node of
1 ; the call graph, any analyses that happened to be cached for that function are
2 ; actually invalidated. We are using `demanded-bits` here because when printed
3 ; it will end up caching a value for every instruction, making it easy to
4 ; detect the instruction-level changes that will fail here. With improper
5 ; invalidation this will crash in the second printer as it tries to reuse
6 ; now-invalid demanded bits.
7 ;
8 ; RUN: opt < %s -passes='function(print),cgscc(argpromotion,function(print))' -S | FileCheck %s
9
10 @G = constant i32 0
11
12 define internal i32 @a(i32* %x) {
13 ; CHECK-LABEL: define internal i32 @a(
14 ; CHECK-SAME: i32 %[[V:.*]]) {
15 ; CHECK-NEXT: entry:
16 ; CHECK-NEXT: ret i32 %[[V]]
17 ; CHECK-NEXT: }
18 entry:
19 %v = load i32, i32* %x
20 ret i32 %v
21 }
22
23 define i32 @b() {
24 ; CHECK-LABEL: define i32 @b()
25 ; CHECK-NEXT: entry:
26 ; CHECK-NEXT: %[[L:.*]] = load i32, i32* @G
27 ; CHECK-NEXT: %[[V:.*]] = call i32 @a(i32 %[[L]])
28 ; CHECK-NEXT: ret i32 %[[V]]
29 ; CHECK-NEXT: }
30 entry:
31 %v = call i32 @a(i32* @G)
32 ret i32 %v
33 }
34
35 define i32 @c() {
36 ; CHECK-LABEL: define i32 @c()
37 ; CHECK-NEXT: entry:
38 ; CHECK-NEXT: %[[L:.*]] = load i32, i32* @G
39 ; CHECK-NEXT: %[[V1:.*]] = call i32 @a(i32 %[[L]])
40 ; CHECK-NEXT: %[[V2:.*]] = call i32 @b()
41 ; CHECK-NEXT: %[[RESULT:.*]] = add i32 %[[V1]], %[[V2]]
42 ; CHECK-NEXT: ret i32 %[[RESULT]]
43 ; CHECK-NEXT: }
44 entry:
45 %v1 = call i32 @a(i32* @G)
46 %v2 = call i32 @b()
47 %result = add i32 %v1, %v2
48 ret i32 %result
49 }
77 ;
88 ; CHECK-LABEL: Starting llvm::Module pass manager run.
99 ; CHECK: Running pass: InlinerPass on (test1_f, test1_g, test1_h)
10 ; CHECK: Running analysis: FunctionAnalysisManagerCGSCCProxy on (test1_f, test1_g, test1_h)
1110 ; CHECK: Running analysis: DominatorTreeAnalysis on test1_f
1211 ; CHECK: Running analysis: DominatorTreeAnalysis on test1_g
1312 ; CHECK: Invalidating all non-preserved analyses for: (test1_f)
12541254 MPM.run(*M, MAM);
12551255
12561256 // We run over four SCCs the first time. But then we split an SCC into three.
1257 // And then we merge those three back into one.
1258 EXPECT_EQ(4 + 3 + 1, SCCAnalysisRuns);
1257 // And then we merge those three back into one. However, this also
1258 // invalidates all three SCCs further down in the PO walk.
1259 EXPECT_EQ(4 + 3 + 1 + 3, SCCAnalysisRuns);
12591260 // The module analysis pass should be run three times.
12601261 EXPECT_EQ(3, ModuleAnalysisRuns);
12611262 // We run over four SCCs the first time. Then over the two new ones. Then the
12621263 // entire module is invalidated causing a full run over all seven. Then we
1263 // fold three SCCs back to one, and then run over the whole module again.
1264 EXPECT_EQ(4 + 2 + 7 + 1 + 4, IndirectSCCAnalysisRuns);
1265 EXPECT_EQ(4 + 2 + 7 + 1 + 4, DoublyIndirectSCCAnalysisRuns);
1264 // fold three SCCs back to one, re-compute for it and the two SCCs above it
1265 // in the graph, and then run over the whole module again.
1266 EXPECT_EQ(4 + 2 + 7 + 1 + 3 + 4, IndirectSCCAnalysisRuns);
1267 EXPECT_EQ(4 + 2 + 7 + 1 + 3 + 4, DoublyIndirectSCCAnalysisRuns);
12661268
12671269 // First we run over all six functions. Then we re-run it over three when we
12681270 // split their SCCs. Then we re-run over the whole module. Then we re-run
1269 // over three functions merged back into a single SCC, and then over the
1270 // whole module again.
1271 EXPECT_EQ(6 + 3 + 6 + 3 + 6, FunctionAnalysisRuns);
1271 // over three functions merged back into a single SCC, then those three
1272 // functions again, the two functions in SCCs above it in the graph, and then
1273 // over the whole module again.
1274 EXPECT_EQ(6 + 3 + 6 + 3 + 3 + 2 + 6, FunctionAnalysisRuns);
12721275
12731276 // Re run the function analysis over the entire module, and then re-run it
12741277 // over the `(h3, h1, h2)` SCC due to invalidation. Then we re-run it over
12751278 // the entire module, then the three functions merged back into a single SCC,
1276 // and then over the whole module.
1277 EXPECT_EQ(6 + 3 + 6 + 3 + 6, IndirectFunctionAnalysisRuns);
1278 }
1279 }
1279 // those three functions again, then the two functions in SCCs above it in
1280 // the graph, and then over the whole module.
1281 EXPECT_EQ(6 + 3 + 6 + 3 + 3 + 2 + 6, IndirectFunctionAnalysisRuns);
1282 }
1283 }