diff --git a/llvm/include/llvm/Analysis/CGSCCPassManager.h b/llvm/include/llvm/Analysis/CGSCCPassManager.h --- a/llvm/include/llvm/Analysis/CGSCCPassManager.h +++ b/llvm/include/llvm/Analysis/CGSCCPassManager.h @@ -508,7 +508,7 @@ PassPA = Pass.run(F, FAM); } - PI.runAfterPass(Pass, F); + PI.runAfterPass(Pass, F, PassPA); // We know that the function pass couldn't have invalidated any other // function's analyses (that's the contract of a function pass), so @@ -639,9 +639,9 @@ PreservedAnalyses PassPA = Pass.run(*C, AM, CG, UR); if (UR.InvalidatedSCCs.count(C)) - PI.runAfterPassInvalidated(Pass); + PI.runAfterPassInvalidated(Pass, PassPA); else - PI.runAfterPass(Pass, *C); + PI.runAfterPass(Pass, *C, PassPA); // If the SCC structure has changed, bail immediately and let the outer // CGSCC layer handle any iteration to reflect the refined structure. @@ -903,9 +903,9 @@ } if (UR.InvalidatedSCCs.count(C)) - PI.runAfterPassInvalidated(Pass); + PI.runAfterPassInvalidated(Pass, PassPA); else - PI.runAfterPass(Pass, *C); + PI.runAfterPass(Pass, *C, PassPA); // Update the SCC and RefSCC if necessary. C = UR.UpdatedC ? UR.UpdatedC : C; diff --git a/llvm/include/llvm/IR/PassInstrumentation.h b/llvm/include/llvm/IR/PassInstrumentation.h --- a/llvm/include/llvm/IR/PassInstrumentation.h +++ b/llvm/include/llvm/IR/PassInstrumentation.h @@ -76,8 +76,8 @@ using BeforePassFunc = bool(StringRef, Any); using BeforeSkippedPassFunc = void(StringRef, Any); using BeforeNonSkippedPassFunc = void(StringRef, Any); - using AfterPassFunc = void(StringRef, Any); - using AfterPassInvalidatedFunc = void(StringRef); + using AfterPassFunc = void(StringRef, Any, const PreservedAnalyses &); + using AfterPassInvalidatedFunc = void(StringRef, const PreservedAnalyses &); using BeforeAnalysisFunc = void(StringRef, Any); using AfterAnalysisFunc = void(StringRef, Any); @@ -199,20 +199,22 @@ /// just been executed and constant reference to \p IR it operates on. /// \p IR is guaranteed to be valid at this point. template - void runAfterPass(const PassT &Pass, const IRUnitT &IR) const { + void runAfterPass(const PassT &Pass, const IRUnitT &IR, + const PreservedAnalyses &PA) const { if (Callbacks) for (auto &C : Callbacks->AfterPassCallbacks) - C(Pass.name(), llvm::Any(&IR)); + C(Pass.name(), llvm::Any(&IR), PA); } /// AfterPassInvalidated instrumentation point - takes \p Pass instance /// that has just been executed. For use when IR has been invalidated /// by \p Pass execution. template - void runAfterPassInvalidated(const PassT &Pass) const { + void runAfterPassInvalidated(const PassT &Pass, + const PreservedAnalyses &PA) const { if (Callbacks) for (auto &C : Callbacks->AfterPassInvalidatedCallbacks) - C(Pass.name()); + C(Pass.name(), PA); } /// BeforeAnalysis instrumentation point - takes \p Analysis instance diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h --- a/llvm/include/llvm/IR/PassManager.h +++ b/llvm/include/llvm/IR/PassManager.h @@ -519,7 +519,7 @@ // Call onto PassInstrumentation's AfterPass callbacks immediately after // running the pass. - PI.runAfterPass(*P, IR); + PI.runAfterPass(*P, IR, PassPA); // Update the analysis manager as each pass runs and potentially // invalidates analyses. @@ -1244,7 +1244,7 @@ PassPA = Pass.run(F, FAM); } - PI.runAfterPass(Pass, F); + PI.runAfterPass(Pass, F, PassPA); // We know that the function pass couldn't have invalidated any other // function's analyses (that's the contract of a function pass), so @@ -1369,8 +1369,9 @@ // false). if (!PI.runBeforePass(P, IR)) continue; - PA.intersect(P.run(IR, AM, std::forward(Args)...)); - PI.runAfterPass(P, IR); + PreservedAnalyses IterPA = P.run(IR, AM, std::forward(Args)...); + PA.intersect(IterPA); + PI.runAfterPass(P, IR, IterPA); } return PA; } diff --git a/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h b/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h --- a/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h +++ b/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h @@ -253,7 +253,7 @@ // canonicalization pipeline. if (PI.runBeforePass(LoopCanonicalizationFPM, F)) { PA = LoopCanonicalizationFPM.run(F, AM); - PI.runAfterPass(LoopCanonicalizationFPM, F); + PI.runAfterPass(LoopCanonicalizationFPM, F, PA); } // Get the loop structure for this function @@ -337,9 +337,9 @@ // Do not pass deleted Loop into the instrumentation. if (Updater.skipCurrentLoop()) - PI.runAfterPassInvalidated(Pass); + PI.runAfterPassInvalidated(Pass, PassPA); else - PI.runAfterPass(Pass, *L); + PI.runAfterPass(Pass, *L, PassPA); // FIXME: We should verify the set of analyses relevant to Loop passes // are preserved. diff --git a/llvm/lib/Analysis/CGSCCPassManager.cpp b/llvm/lib/Analysis/CGSCCPassManager.cpp --- a/llvm/lib/Analysis/CGSCCPassManager.cpp +++ b/llvm/lib/Analysis/CGSCCPassManager.cpp @@ -85,9 +85,9 @@ } if (UR.InvalidatedSCCs.count(C)) - PI.runAfterPassInvalidated(*Pass); + PI.runAfterPassInvalidated(*Pass, PassPA); else - PI.runAfterPass(*Pass, *C); + PI.runAfterPass(*Pass, *C, PassPA); // Update the SCC if necessary. C = UR.UpdatedC ? UR.UpdatedC : C; diff --git a/llvm/lib/CodeGen/MachinePassManager.cpp b/llvm/lib/CodeGen/MachinePassManager.cpp --- a/llvm/lib/CodeGen/MachinePassManager.cpp +++ b/llvm/lib/CodeGen/MachinePassManager.cpp @@ -99,7 +99,7 @@ // TODO: EmitSizeRemarks PreservedAnalyses PassPA = P->run(MF, MFAM); - PI.runAfterPass(*P, MF); + PI.runAfterPass(*P, MF, PassPA); MFAM.invalidate(MF, PassPA); } } diff --git a/llvm/lib/IR/PassTimingInfo.cpp b/llvm/lib/IR/PassTimingInfo.cpp --- a/llvm/lib/IR/PassTimingInfo.cpp +++ b/llvm/lib/IR/PassTimingInfo.cpp @@ -260,9 +260,13 @@ PIC.registerBeforeNonSkippedPassCallback( [this](StringRef P, Any) { this->runBeforePass(P); }); PIC.registerAfterPassCallback( - [this](StringRef P, Any) { this->runAfterPass(P); }); + [this](StringRef P, Any, const PreservedAnalyses &) { + this->runAfterPass(P); + }); PIC.registerAfterPassInvalidatedCallback( - [this](StringRef P) { this->runAfterPass(P); }); + [this](StringRef P, const PreservedAnalyses &) { + this->runAfterPass(P); + }); PIC.registerBeforeAnalysisCallback( [this](StringRef P, Any) { this->runBeforePass(P); }); PIC.registerAfterAnalysisCallback( diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp --- a/llvm/lib/Passes/StandardInstrumentations.cpp +++ b/llvm/lib/Passes/StandardInstrumentations.cpp @@ -277,9 +277,13 @@ if (llvm::shouldPrintAfterPass()) { PIC.registerAfterPassCallback( - [this](StringRef P, Any IR) { this->printAfterPass(P, IR); }); + [this](StringRef P, Any IR, const PreservedAnalyses &) { + this->printAfterPass(P, IR); + }); PIC.registerAfterPassInvalidatedCallback( - [this](StringRef P) { this->printAfterPassInvalidated(P); }); + [this](StringRef P, const PreservedAnalyses &) { + this->printAfterPassInvalidated(P); + }); } } diff --git a/llvm/lib/Transforms/Scalar/LoopPassManager.cpp b/llvm/lib/Transforms/Scalar/LoopPassManager.cpp --- a/llvm/lib/Transforms/Scalar/LoopPassManager.cpp +++ b/llvm/lib/Transforms/Scalar/LoopPassManager.cpp @@ -47,9 +47,9 @@ // do not pass deleted Loop into the instrumentation if (U.skipCurrentLoop()) - PI.runAfterPassInvalidated(*Pass); + PI.runAfterPassInvalidated(*Pass, PassPA); else - PI.runAfterPass(*Pass, L); + PI.runAfterPass(*Pass, L, PassPA); // If the loop was deleted, abort the run and return to the outer walk. if (U.skipCurrentLoop()) { diff --git a/llvm/unittests/IR/PassBuilderCallbacksTest.cpp b/llvm/unittests/IR/PassBuilderCallbacksTest.cpp --- a/llvm/unittests/IR/PassBuilderCallbacksTest.cpp +++ b/llvm/unittests/IR/PassBuilderCallbacksTest.cpp @@ -322,8 +322,10 @@ MOCK_METHOD2(runBeforePass, bool(StringRef PassID, llvm::Any)); MOCK_METHOD2(runBeforeSkippedPass, void(StringRef PassID, llvm::Any)); MOCK_METHOD2(runBeforeNonSkippedPass, void(StringRef PassID, llvm::Any)); - MOCK_METHOD2(runAfterPass, void(StringRef PassID, llvm::Any)); - MOCK_METHOD1(runAfterPassInvalidated, void(StringRef PassID)); + MOCK_METHOD3(runAfterPass, + void(StringRef PassID, llvm::Any, const PreservedAnalyses &PA)); + MOCK_METHOD2(runAfterPassInvalidated, + void(StringRef PassID, const PreservedAnalyses &PA)); MOCK_METHOD2(runBeforeAnalysis, void(StringRef PassID, llvm::Any)); MOCK_METHOD2(runAfterAnalysis, void(StringRef PassID, llvm::Any)); @@ -340,9 +342,13 @@ this->runBeforeNonSkippedPass(P, IR); }); Callbacks.registerAfterPassCallback( - [this](StringRef P, llvm::Any IR) { this->runAfterPass(P, IR); }); + [this](StringRef P, llvm::Any IR, const PreservedAnalyses &PA) { + this->runAfterPass(P, IR, PA); + }); Callbacks.registerAfterPassInvalidatedCallback( - [this](StringRef P) { this->runAfterPassInvalidated(P); }); + [this](StringRef P, const PreservedAnalyses &PA) { + this->runAfterPassInvalidated(P, PA); + }); Callbacks.registerBeforeAnalysisCallback([this](StringRef P, llvm::Any IR) { return this->runBeforeAnalysis(P, IR); }); @@ -365,7 +371,8 @@ EXPECT_CALL(*this, runBeforeNonSkippedPass(Not(HasNameRegex("Mock")), HasName(IRName))) .Times(AnyNumber()); - EXPECT_CALL(*this, runAfterPass(Not(HasNameRegex("Mock")), HasName(IRName))) + EXPECT_CALL(*this, + runAfterPass(Not(HasNameRegex("Mock")), HasName(IRName), _)) .Times(AnyNumber()); EXPECT_CALL(*this, runBeforeAnalysis(Not(HasNameRegex("Mock")), HasName(IRName))) @@ -528,8 +535,8 @@ CallbacksHandle, runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName(""))) .InSequence(PISequence); - EXPECT_CALL(CallbacksHandle, - runAfterPass(HasNameRegex("MockPassHandle"), HasName(""))) + EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), + HasName(""), _)) .InSequence(PISequence); // No passes are skipped, so there should be no calls to @@ -569,7 +576,8 @@ EXPECT_CALL(CallbacksHandle, runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _)) .Times(0); - EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) + EXPECT_CALL(CallbacksHandle, + runAfterPass(HasNameRegex("MockPassHandle"), _, _)) .Times(0); EXPECT_CALL(CallbacksHandle, runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _)) @@ -609,20 +617,20 @@ // The `runAfterPass` checks are the same as these of // `runBeforeNonSkippedPass`. - EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("PassManager"), _)) + EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("PassManager"), _, _)) .Times(5); EXPECT_CALL(CallbacksHandle, - runAfterPass(HasNameRegex("ModuleToFunctionPassAdaptor"), _)) + runAfterPass(HasNameRegex("ModuleToFunctionPassAdaptor"), _, _)) .Times(1); EXPECT_CALL( CallbacksHandle, - runAfterPass(HasNameRegex("ModuleToPostOrderCGSCCPassAdaptor"), _)) + runAfterPass(HasNameRegex("ModuleToPostOrderCGSCCPassAdaptor"), _, _)) .Times(1); EXPECT_CALL(CallbacksHandle, - runAfterPass(HasNameRegex("CGSCCToFunctionPassAdaptor"), _)) + runAfterPass(HasNameRegex("CGSCCToFunctionPassAdaptor"), _, _)) .Times(1); EXPECT_CALL(CallbacksHandle, - runAfterPass(HasNameRegex("FunctionToLoopPassAdaptor"), _)) + runAfterPass(HasNameRegex("FunctionToLoopPassAdaptor"), _, _)) .Times(1); // Ignore analyses introduced by adaptor passes. @@ -701,7 +709,7 @@ runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("foo"))) .InSequence(PISequence); EXPECT_CALL(CallbacksHandle, - runAfterPass(HasNameRegex("MockPassHandle"), HasName("foo"))) + runAfterPass(HasNameRegex("MockPassHandle"), HasName("foo"), _)) .InSequence(PISequence); // No passes are skipped, so there should be no calls to @@ -713,7 +721,7 @@ // Our mock pass does not invalidate IR. EXPECT_CALL(CallbacksHandle, - runAfterPassInvalidated(HasNameRegex("MockPassHandle"))) + runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _)) .Times(0); StringRef PipelineText = "test-transform"; @@ -746,12 +754,14 @@ EXPECT_CALL(CallbacksHandle, runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _)) .Times(0); - EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) + EXPECT_CALL(CallbacksHandle, + runAfterPass(HasNameRegex("MockPassHandle"), _, _)) .Times(0); EXPECT_CALL(CallbacksHandle, - runAfterPassInvalidated(HasNameRegex("MockPassHandle"))) + runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _)) .Times(0); - EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) + EXPECT_CALL(CallbacksHandle, + runAfterPass(HasNameRegex("MockPassHandle"), _, _)) .Times(0); EXPECT_CALL(CallbacksHandle, runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _)) @@ -807,12 +817,12 @@ runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop"))) .InSequence(PISequence); EXPECT_CALL(CallbacksHandle, - runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop"))) + runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop"), _)) .InSequence(PISequence); // Our mock pass does not invalidate IR. EXPECT_CALL(CallbacksHandle, - runAfterPassInvalidated(HasNameRegex("MockPassHandle"))) + runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _)) .Times(0); // No passes are skipped, so there should be no calls to @@ -859,15 +869,15 @@ runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("loop"))) .InSequence(PISequence); EXPECT_CALL(CallbacksHandle, - runAfterPassInvalidated(HasNameRegex("MockPassHandle"))) + runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _)) .InSequence(PISequence); EXPECT_CALL(CallbacksHandle, - runAfterPassInvalidated(HasNameRegex("^PassManager"))) + runAfterPassInvalidated(HasNameRegex("^PassManager"), _)) .InSequence(PISequence); // Our mock pass invalidates IR, thus normal runAfterPass is never called. EXPECT_CALL(CallbacksHandle, - runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop"))) + runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop"), _)) .Times(0); StringRef PipelineText = "test-transform"; @@ -901,10 +911,11 @@ EXPECT_CALL(CallbacksHandle, runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _)) .Times(0); - EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) + EXPECT_CALL(CallbacksHandle, + runAfterPass(HasNameRegex("MockPassHandle"), _, _)) .Times(0); EXPECT_CALL(CallbacksHandle, - runAfterPassInvalidated(HasNameRegex("MockPassHandle"))) + runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _)) .Times(0); EXPECT_CALL(CallbacksHandle, runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _)) @@ -960,12 +971,12 @@ runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)"))) .InSequence(PISequence); EXPECT_CALL(CallbacksHandle, - runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)"))) + runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)"), _)) .InSequence(PISequence); // Our mock pass does not invalidate IR. EXPECT_CALL(CallbacksHandle, - runAfterPassInvalidated(HasNameRegex("MockPassHandle"))) + runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _)) .Times(0); // No passes are skipped, so there should be no calls to @@ -1012,15 +1023,15 @@ runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName("(foo)"))) .InSequence(PISequence); EXPECT_CALL(CallbacksHandle, - runAfterPassInvalidated(HasNameRegex("MockPassHandle"))) + runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _)) .InSequence(PISequence); EXPECT_CALL(CallbacksHandle, - runAfterPassInvalidated(HasNameRegex("^PassManager"))) + runAfterPassInvalidated(HasNameRegex("^PassManager"), _)) .InSequence(PISequence); // Our mock pass does invalidate IR, thus normal runAfterPass is never called. EXPECT_CALL(CallbacksHandle, - runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)"))) + runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)"), _)) .Times(0); StringRef PipelineText = "test-transform"; @@ -1055,10 +1066,11 @@ EXPECT_CALL(CallbacksHandle, runBeforeNonSkippedPass(HasNameRegex("MockPassHandle"), _)) .Times(0); - EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) + EXPECT_CALL(CallbacksHandle, + runAfterPass(HasNameRegex("MockPassHandle"), _, _)) .Times(0); EXPECT_CALL(CallbacksHandle, - runAfterPassInvalidated(HasNameRegex("MockPassHandle"))) + runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _)) .Times(0); EXPECT_CALL(CallbacksHandle, runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _)) diff --git a/llvm/unittests/IR/TimePassesTest.cpp b/llvm/unittests/IR/TimePassesTest.cpp --- a/llvm/unittests/IR/TimePassesTest.cpp +++ b/llvm/unittests/IR/TimePassesTest.cpp @@ -134,8 +134,8 @@ // Pretending that passes are running to trigger the timers. PI.runBeforePass(Pass1, M); PI.runBeforePass(Pass2, M); - PI.runAfterPass(Pass2, M); - PI.runAfterPass(Pass1, M); + PI.runAfterPass(Pass2, M, PreservedAnalyses::all()); + PI.runAfterPass(Pass1, M, PreservedAnalyses::all()); // Generating report. TimePasses->print(); @@ -154,7 +154,7 @@ // Now trigger just a single pass to populate timers again. PI.runBeforePass(Pass2, M); - PI.runAfterPass(Pass2, M); + PI.runAfterPass(Pass2, M, PreservedAnalyses::all()); // Generate report by deleting the handler. TimePasses.reset();