Index: llvm/include/llvm/Analysis/CGSCCPassManager.h =================================================================== --- llvm/include/llvm/Analysis/CGSCCPassManager.h +++ 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; Index: llvm/include/llvm/IR/PassInstrumentation.h =================================================================== --- llvm/include/llvm/IR/PassInstrumentation.h +++ llvm/include/llvm/IR/PassInstrumentation.h @@ -76,8 +76,8 @@ // in a safe way, and we might pursue that as soon as there is a useful instrumentation // that needs it. using BeforePassFunc = bool(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); @@ -176,20 +176,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 Index: llvm/include/llvm/IR/PassManager.h =================================================================== --- llvm/include/llvm/IR/PassManager.h +++ llvm/include/llvm/IR/PassManager.h @@ -522,7 +522,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. @@ -1249,7 +1249,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 @@ -1373,8 +1373,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; } Index: llvm/include/llvm/Transforms/Scalar/LoopPassManager.h =================================================================== --- llvm/include/llvm/Transforms/Scalar/LoopPassManager.h +++ llvm/include/llvm/Transforms/Scalar/LoopPassManager.h @@ -252,7 +252,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 @@ -326,9 +326,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. Index: llvm/lib/Analysis/CGSCCPassManager.cpp =================================================================== --- llvm/lib/Analysis/CGSCCPassManager.cpp +++ llvm/lib/Analysis/CGSCCPassManager.cpp @@ -88,9 +88,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; Index: llvm/lib/IR/PassTimingInfo.cpp =================================================================== --- llvm/lib/IR/PassTimingInfo.cpp +++ llvm/lib/IR/PassTimingInfo.cpp @@ -270,9 +270,13 @@ PIC.registerBeforePassCallback( [this](StringRef P, Any) { return this->runBeforePass(P); }); PIC.registerAfterPassCallback( - [this](StringRef P, Any) { this->runAfterPass(P); }); + [this](StringRef P, Any, const PreservedAnalyses &PA) { + 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( Index: llvm/lib/Passes/StandardInstrumentations.cpp =================================================================== --- llvm/lib/Passes/StandardInstrumentations.cpp +++ llvm/lib/Passes/StandardInstrumentations.cpp @@ -245,9 +245,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); + }); } } Index: llvm/lib/Transforms/Scalar/LoopPassManager.cpp =================================================================== --- llvm/lib/Transforms/Scalar/LoopPassManager.cpp +++ llvm/lib/Transforms/Scalar/LoopPassManager.cpp @@ -50,9 +50,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()) { Index: llvm/unittests/IR/PassBuilderCallbacksTest.cpp =================================================================== --- llvm/unittests/IR/PassBuilderCallbacksTest.cpp +++ llvm/unittests/IR/PassBuilderCallbacksTest.cpp @@ -320,8 +320,10 @@ ON_CALL(*this, runBeforePass(_, _)).WillByDefault(Return(true)); } MOCK_METHOD2(runBeforePass, bool(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)); @@ -330,9 +332,13 @@ return this->runBeforePass(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); }); @@ -349,7 +355,8 @@ EXPECT_CALL(*this, runBeforePass(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))) @@ -508,8 +515,8 @@ CallbacksHandle, runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), HasName(""))) .InSequence(PISequence); - EXPECT_CALL(CallbacksHandle, - runAfterPass(HasNameRegex("MockPassHandle"), HasName(""))) + EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), + HasName(""), _)) .InSequence(PISequence); StringRef PipelineText = "test-transform"; @@ -534,7 +541,8 @@ // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis // as well. - EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) + EXPECT_CALL(CallbacksHandle, + runAfterPass(HasNameRegex("MockPassHandle"), _, _)) .Times(0); EXPECT_CALL(CallbacksHandle, runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _)) @@ -551,20 +559,20 @@ // Pass managers are not ignored. // 5 = (1) ModulePassManager + (2) FunctionPassMangers + (1) LoopPassManager + // (1) CGSCCPassManager - 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. @@ -639,12 +647,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); StringRef PipelineText = "test-transform"; @@ -669,12 +677,11 @@ // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis // as well. - EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) - .Times(0); EXPECT_CALL(CallbacksHandle, - runAfterPassInvalidated(HasNameRegex("MockPassHandle"))) + runAfterPass(HasNameRegex("MockPassHandle"), _, _)) .Times(0); - EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) + EXPECT_CALL(CallbacksHandle, + runAfterPassInvalidated(HasNameRegex("MockPassHandle"), _)) .Times(0); EXPECT_CALL(CallbacksHandle, runBeforeAnalysis(HasNameRegex("MockAnalysisHandle"), _)) @@ -726,12 +733,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); StringRef PipelineText = "test-transform"; @@ -767,15 +774,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"; @@ -801,10 +808,11 @@ // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis // as well. - 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"), _)) @@ -856,12 +864,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); StringRef PipelineText = "test-transform"; @@ -897,15 +905,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"; @@ -932,10 +940,11 @@ // As the pass is skipped there is no afterPass, beforeAnalysis/afterAnalysis // as well. - 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"), _)) Index: llvm/unittests/IR/TimePassesTest.cpp =================================================================== --- llvm/unittests/IR/TimePassesTest.cpp +++ 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();