llvm.org GIT mirror llvm / 601226c
[NewPM] fixing asserts on deleted loop in -print-after-all IR-printing AfterPass instrumentation might be called on a loop that has just been invalidated. We should skip printing it to avoid spurious asserts. Reviewed By: chandlerc, philip.pfaffe Differential Revision: https://reviews.llvm.org/D54740 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@348887 91177308-0d34-0410-b5e6-96231b3b80d8 Fedor Sergeev 1 year, 11 months ago
11 changed file(s) with 233 addition(s) and 17 deletion(s). Raw diff Collapse all Expand all
440440
441441 PreservedAnalyses PassPA = Pass.run(*C, CGAM, CG, UR);
442442
443 PI.runAfterPass(Pass, *C);
443 if (UR.InvalidatedSCCs.count(C))
444 PI.runAfterPassInvalidated(Pass);
445 else
446 PI.runAfterPass(Pass, *C);
444447
445448 // Update the SCC and RefSCC if necessary.
446449 C = UR.UpdatedC ? UR.UpdatedC : C;
761764
762765 PreservedAnalyses PassPA = Pass.run(*C, AM, CG, UR);
763766
764 PI.runAfterPass(Pass, *C);
767 if (UR.InvalidatedSCCs.count(C))
768 PI.runAfterPassInvalidated(Pass);
769 else
770 PI.runAfterPass(Pass, *C);
765771
766772 // If the SCC structure has changed, bail immediately and let the outer
767773 // CGSCC layer handle any iteration to reflect the refined structure.
6767 /// PassInstrumentation to pass control to the registered callbacks.
6868 class PassInstrumentationCallbacks {
6969 public:
70 // Before/After callbacks accept IRUnits, so they need to take them
71 // as pointers, wrapped with llvm::Any
70 // Before/After callbacks accept IRUnits whenever appropriate, so they need
71 // to take them as constant pointers, wrapped with llvm::Any.
72 // For the case when IRUnit has been invalidated there is a different
73 // callback to use - AfterPassInvalidated.
74 // TODO: currently AfterPassInvalidated does not accept IRUnit, since passing
75 // already invalidated IRUnit is unsafe. There are ways to handle invalidated IRUnits
76 // in a safe way, and we might pursue that as soon as there is a useful instrumentation
77 // that needs it.
7278 using BeforePassFunc = bool(StringRef, Any);
7379 using AfterPassFunc = void(StringRef, Any);
80 using AfterPassInvalidatedFunc = void(StringRef);
7481 using BeforeAnalysisFunc = void(StringRef, Any);
7582 using AfterAnalysisFunc = void(StringRef, Any);
7683
9097 }
9198
9299 template
100 void registerAfterPassInvalidatedCallback(CallableT C) {
101 AfterPassInvalidatedCallbacks.emplace_back(std::move(C));
102 }
103
104 template
93105 void registerBeforeAnalysisCallback(CallableT C) {
94106 BeforeAnalysisCallbacks.emplace_back(std::move(C));
95107 }
104116
105117 SmallVector, 4> BeforePassCallbacks;
106118 SmallVector, 4> AfterPassCallbacks;
119 SmallVector, 4>
120 AfterPassInvalidatedCallbacks;
107121 SmallVector, 4>
108122 BeforeAnalysisCallbacks;
109123 SmallVector, 4>
138152 }
139153
140154 /// AfterPass instrumentation point - takes \p Pass instance that has
141 /// just been executed and constant reference to IR it operates on.
155 /// just been executed and constant reference to \p IR it operates on.
156 /// \p IR is guaranteed to be valid at this point.
142157 template
143158 void runAfterPass(const PassT &Pass, const IRUnitT &IR) const {
144159 if (Callbacks)
145160 for (auto &C : Callbacks->AfterPassCallbacks)
146161 C(Pass.name(), llvm::Any(&IR));
162 }
163
164 /// AfterPassInvalidated instrumentation point - takes \p Pass instance
165 /// that has just been executed. For use when IR has been invalidated
166 /// by \p Pass execution.
167 template
168 void runAfterPassInvalidated(const PassT &Pass) const {
169 if (Callbacks)
170 for (auto &C : Callbacks->AfterPassInvalidatedCallbacks)
171 C(Pass.name());
147172 }
148173
149174 /// BeforeAnalysis instrumentation point - takes \p Analysis instance
9898 void stopTimer(StringRef PassID);
9999
100100 // Implementation of pass instrumentation callbacks.
101 bool runBeforePass(StringRef PassID, Any IR);
102 void runAfterPass(StringRef PassID, Any IR);
101 bool runBeforePass(StringRef PassID);
102 void runAfterPass(StringRef PassID);
103103 };
104104
105105 } // namespace llvm
351351 continue;
352352 PreservedAnalyses PassPA = Pass.run(*L, LAM, LAR, Updater);
353353
354 PI.runAfterPass(Pass, *L);
354 // Do not pass deleted Loop into the instrumentation.
355 if (Updater.skipCurrentLoop())
356 PI.runAfterPassInvalidated(Pass);
357 else
358 PI.runAfterPass(Pass, *L);
355359
356360 // FIXME: We should verify the set of analyses relevant to Loop passes
357361 // are preserved.
7878
7979 PreservedAnalyses PassPA = Pass->run(*C, AM, G, UR);
8080
81 PI.runAfterPass(*Pass, *C);
81 if (UR.InvalidatedSCCs.count(C))
82 PI.runAfterPassInvalidated(*Pass);
83 else
84 PI.runAfterPass(*Pass, *C);
8285
8386 // Update the SCC if necessary.
8487 C = UR.UpdatedC ? UR.UpdatedC : C;
225225 Prefix.endswith("AnalysisManagerProxy");
226226 }
227227
228 bool TimePassesHandler::runBeforePass(StringRef PassID, Any IR) {
228 bool TimePassesHandler::runBeforePass(StringRef PassID) {
229229 if (matchPassManager(PassID))
230230 return true;
231231
238238 return true;
239239 }
240240
241 void TimePassesHandler::runAfterPass(StringRef PassID, Any IR) {
241 void TimePassesHandler::runAfterPass(StringRef PassID) {
242242 if (matchPassManager(PassID))
243243 return;
244244
253253 return;
254254
255255 PIC.registerBeforePassCallback(
256 [this](StringRef P, Any IR) { return this->runBeforePass(P, IR); });
256 [this](StringRef P, Any) { return this->runBeforePass(P); });
257257 PIC.registerAfterPassCallback(
258 [this](StringRef P, Any IR) { this->runAfterPass(P, IR); });
258 [this](StringRef P, Any) { this->runAfterPass(P); });
259 PIC.registerAfterPassInvalidatedCallback(
260 [this](StringRef P) { this->runAfterPass(P); });
259261 PIC.registerBeforeAnalysisCallback(
260 [this](StringRef P, Any IR) { this->runBeforePass(P, IR); });
262 [this](StringRef P, Any) { this->runBeforePass(P); });
261263 PIC.registerAfterAnalysisCallback(
262 [this](StringRef P, Any IR) { this->runAfterPass(P, IR); });
264 [this](StringRef P, Any) { this->runAfterPass(P); });
263265 }
264266
265267 } // namespace llvm
5252 Extra = formatv(" (function: {0})\n", F->getName());
5353 } else if (any_isa(IR)) {
5454 const LazyCallGraph::SCC *C = any_cast(IR);
55 assert(C);
5655 if (!llvm::forcePrintModuleIR()) {
5756 Extra = formatv(" (scc: {0})\n", C->getName());
5857 bool BannerPrinted = false;
4343
4444 PreservedAnalyses PassPA = Pass->run(L, AM, AR, U);
4545
46 PI.runAfterPass(*Pass, L);
46 // do not pass deleted Loop into the instrumentation
47 if (U.skipCurrentLoop())
48 PI.runAfterPassInvalidated(*Pass);
49 else
50 PI.runAfterPass(*Pass, L);
4751
4852 // If the loop was deleted, abort the run and return to the outer walk.
4953 if (U.skipCurrentLoop()) {
0 ; Make sure that Loop which was invalidated by loop-deletion
1 ; does not lead to problems for -print-after-all and is just skipped.
2 ;
3 ; RUN: opt < %s -disable-output \
4 ; RUN: -passes=loop-instsimplify -print-after-all 2>&1 | FileCheck %s -check-prefix=SIMPLIFY
5 ; RUN: opt < %s -disable-output \
6 ; RUN: -passes=loop-deletion,loop-instsimplify -print-after-all 2>&1 | FileCheck %s -check-prefix=DELETED
7 ;
8 ; SIMPLIFY: IR Dump {{.*}} LoopInstSimplifyPass
9 ; DELETED-NOT: IR Dump {{.*}}LoopInstSimplifyPass
10 ; DELETED-NOT: IR Dump {{.*}}LoopDeletionPass
11
12 define void @deleteme() {
13 entry:
14 br label %loop
15 loop:
16 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
17 %iv.next = add i32 %iv, 1
18 %check = icmp ult i32 %iv.next, 3
19 br i1 %check, label %loop, label %exit
20 exit:
21 ret void
22 }
23
0 ; RUN: opt < %s 2>&1 -disable-output \
1 ; RUN: -passes=inline -print-before-all -print-after-all | FileCheck %s -check-prefix=INL
2 ; RUN: opt < %s 2>&1 -disable-output \
3 ; RUN: -passes=inline -print-before-all -print-after-all -print-module-scope | FileCheck %s -check-prefix=INL-MOD
4
5 ; INL: IR Dump Before {{InlinerPass .*scc: .tester, foo}}
6 ; INL-NOT: IR Dump After {{InlinerPass}}
7 ; INL: IR Dump Before {{InlinerPass .*scc: .tester}}
8 ; INL: IR Dump After {{InlinerPass .*scc: .tester}}
9
10 ; INL-MOD: IR Dump Before {{InlinerPass .*scc: .tester, foo}}
11 ; INL-MOD-NOT: IR Dump After {{InlinerPass}}
12 ; INL-MOD: IR Dump Before {{InlinerPass .*scc: .tester}}
13 ; INL-MOD: IR Dump After {{InlinerPass .*scc: .tester}}
14
15
16 define void @tester() noinline {
17 call void @foo()
18 ret void
19 }
20
21 define internal void @foo() alwaysinline {
22 call void @tester()
23 ret void
24 }
166166 MOCK_METHOD4(run,
167167 PreservedAnalyses(Loop &, LoopAnalysisManager &,
168168 LoopStandardAnalysisResults &, LPMUpdater &));
169 static void invalidateLoop(Loop &L, LoopAnalysisManager &,
170 LoopStandardAnalysisResults &,
171 LPMUpdater &Updater) {
172 Updater.markLoopAsDeleted(L, L.getName());
173 }
169174 MockPassHandle() { setDefaults(); }
170175 };
171176
185190 MOCK_METHOD4(run,
186191 PreservedAnalyses(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
187192 LazyCallGraph &G, CGSCCUpdateResult &UR));
193
194 static void invalidateSCC(LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
195 LazyCallGraph &, CGSCCUpdateResult &UR) {
196 UR.InvalidatedSCCs.insert(&C);
197 }
188198
189199 MockPassHandle() { setDefaults(); }
190200 };
309319 }
310320 MOCK_METHOD2(runBeforePass, bool(StringRef PassID, llvm::Any));
311321 MOCK_METHOD2(runAfterPass, void(StringRef PassID, llvm::Any));
322 MOCK_METHOD1(runAfterPassInvalidated, void(StringRef PassID));
312323 MOCK_METHOD2(runBeforeAnalysis, void(StringRef PassID, llvm::Any));
313324 MOCK_METHOD2(runAfterAnalysis, void(StringRef PassID, llvm::Any));
314325
318329 });
319330 Callbacks.registerAfterPassCallback(
320331 [this](StringRef P, llvm::Any IR) { this->runAfterPass(P, IR); });
332 Callbacks.registerAfterPassInvalidatedCallback(
333 [this](StringRef P) { this->runAfterPassInvalidated(P); });
321334 Callbacks.registerBeforeAnalysisCallback([this](StringRef P, llvm::Any IR) {
322335 return this->runBeforeAnalysis(P, IR);
323336 });
570583 runAfterPass(HasNameRegex("MockPassHandle"), HasName("foo")))
571584 .InSequence(PISequence);
572585
586 // Our mock pass does not invalidate IR.
587 EXPECT_CALL(CallbacksHandle,
588 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
589 .Times(0);
590
573591 StringRef PipelineText = "test-transform";
574592 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
575593 << "Pipeline was: " << PipelineText;
593611 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
594612 // as well.
595613 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
614 .Times(0);
615 EXPECT_CALL(CallbacksHandle,
616 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
596617 .Times(0);
597618 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
598619 .Times(0);
649670 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop")))
650671 .InSequence(PISequence);
651672
673 // Our mock pass does not invalidate IR.
674 EXPECT_CALL(CallbacksHandle,
675 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
676 .Times(0);
677
678 StringRef PipelineText = "test-transform";
679 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
680 << "Pipeline was: " << PipelineText;
681 PM.run(*M, AM);
682 }
683
684 TEST_F(LoopCallbacksTest, InstrumentedInvalidatingPasses) {
685 CallbacksHandle.registerPassInstrumentation();
686 // Non-mock instrumentation not specifically mentioned below can be ignored.
687 CallbacksHandle.ignoreNonMockPassInstrumentation("");
688 CallbacksHandle.ignoreNonMockPassInstrumentation("foo");
689 CallbacksHandle.ignoreNonMockPassInstrumentation("loop");
690
691 EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _));
692 EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _))
693 .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(Invoke(PassHandle.invalidateLoop)),
694 WithArgs<0, 1, 2>(Invoke(getAnalysisResult))));
695
696 // PassInstrumentation calls should happen in-sequence, in the same order
697 // as passes/analyses are scheduled.
698 ::testing::Sequence PISequence;
699 EXPECT_CALL(CallbacksHandle,
700 runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop")))
701 .InSequence(PISequence);
702 EXPECT_CALL(
703 CallbacksHandle,
704 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
705 .InSequence(PISequence);
706 EXPECT_CALL(
707 CallbacksHandle,
708 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop")))
709 .InSequence(PISequence);
710 EXPECT_CALL(CallbacksHandle,
711 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
712 .InSequence(PISequence);
713 EXPECT_CALL(CallbacksHandle,
714 runAfterPassInvalidated(HasNameRegex("^PassManager")))
715 .InSequence(PISequence);
716
717 // Our mock pass invalidates IR, thus normal runAfterPass is never called.
718 EXPECT_CALL(CallbacksHandle,
719 runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop")))
720 .Times(0);
721
652722 StringRef PipelineText = "test-transform";
653723 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
654724 << "Pipeline was: " << PipelineText;
675745 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
676746 .Times(0);
677747 EXPECT_CALL(CallbacksHandle,
748 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
749 .Times(0);
750 EXPECT_CALL(CallbacksHandle,
678751 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))
679752 .Times(0);
680753 EXPECT_CALL(CallbacksHandle,
726799 runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
727800 .InSequence(PISequence);
728801
802 // Our mock pass does not invalidate IR.
803 EXPECT_CALL(CallbacksHandle,
804 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
805 .Times(0);
806
807 StringRef PipelineText = "test-transform";
808 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
809 << "Pipeline was: " << PipelineText;
810 PM.run(*M, AM);
811 }
812
813 TEST_F(CGSCCCallbacksTest, InstrumentedInvalidatingPasses) {
814 CallbacksHandle.registerPassInstrumentation();
815 // Non-mock instrumentation not specifically mentioned below can be ignored.
816 CallbacksHandle.ignoreNonMockPassInstrumentation("");
817 CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)");
818
819 EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _));
820 EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _))
821 .WillOnce(DoAll(WithArgs<0, 1, 2, 3>(Invoke(PassHandle.invalidateSCC)),
822 WithArgs<0, 1, 2>(Invoke(getAnalysisResult))));
823
824 // PassInstrumentation calls should happen in-sequence, in the same order
825 // as passes/analyses are scheduled.
826 ::testing::Sequence PISequence;
827 EXPECT_CALL(CallbacksHandle,
828 runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
829 .InSequence(PISequence);
830 EXPECT_CALL(
831 CallbacksHandle,
832 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
833 .InSequence(PISequence);
834 EXPECT_CALL(
835 CallbacksHandle,
836 runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)")))
837 .InSequence(PISequence);
838 EXPECT_CALL(CallbacksHandle,
839 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
840 .InSequence(PISequence);
841 EXPECT_CALL(CallbacksHandle,
842 runAfterPassInvalidated(HasNameRegex("^PassManager")))
843 .InSequence(PISequence);
844
845 // Our mock pass does invalidate IR, thus normal runAfterPass is never called.
846 EXPECT_CALL(CallbacksHandle,
847 runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)")))
848 .Times(0);
849
729850 StringRef PipelineText = "test-transform";
730851 ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded())
731852 << "Pipeline was: " << PipelineText;
750871 // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis
751872 // as well.
752873 EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _))
874 .Times(0);
875 EXPECT_CALL(CallbacksHandle,
876 runAfterPassInvalidated(HasNameRegex("MockPassHandle")))
753877 .Times(0);
754878 EXPECT_CALL(CallbacksHandle,
755879 runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _))