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 @@ -107,13 +107,21 @@ BeforeNonSkippedPassCallbacks.emplace_back(std::move(C)); } - template void registerAfterPassCallback(CallableT C) { - AfterPassCallbacks.emplace_back(std::move(C)); + template + void registerAfterPassCallback(CallableT C, bool ToFront = false) { + if (ToFront) + AfterPassCallbacks.insert(AfterPassCallbacks.begin(), std::move(C)); + else + AfterPassCallbacks.emplace_back(std::move(C)); } template - void registerAfterPassInvalidatedCallback(CallableT C) { - AfterPassInvalidatedCallbacks.emplace_back(std::move(C)); + void registerAfterPassInvalidatedCallback(CallableT C, bool ToFront = false) { + if (ToFront) + AfterPassInvalidatedCallbacks.insert( + AfterPassInvalidatedCallbacks.begin(), std::move(C)); + else + AfterPassInvalidatedCallbacks.emplace_back(std::move(C)); } template @@ -122,8 +130,12 @@ } template - void registerAfterAnalysisCallback(CallableT C) { - AfterAnalysisCallbacks.emplace_back(std::move(C)); + void registerAfterAnalysisCallback(CallableT C, bool ToFront = false) { + if (ToFront) + AfterAnalysisCallbacks.insert(AfterAnalysisCallbacks.begin(), + std::move(C)); + else + AfterAnalysisCallbacks.emplace_back(std::move(C)); } template 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 @@ -514,11 +514,7 @@ if (!PI.runBeforePass(*Pass, IR)) continue; - PreservedAnalyses PassPA; - { - TimeTraceScope TimeScope(Pass->name(), IR.getName()); - PassPA = Pass->run(IR, AM, ExtraArgs...); - } + PreservedAnalyses PassPA = Pass->run(IR, AM, ExtraArgs...); // Call onto PassInstrumentation's AfterPass callbacks immediately after // running the pass. diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h b/llvm/include/llvm/Passes/StandardInstrumentations.h --- a/llvm/include/llvm/Passes/StandardInstrumentations.h +++ b/llvm/include/llvm/Passes/StandardInstrumentations.h @@ -23,6 +23,7 @@ #include "llvm/IR/PassTimingInfo.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/TimeProfiler.h" #include "llvm/Transforms/IPO/SampleProfileProbe.h" #include @@ -405,6 +406,24 @@ void registerCallbacks(PassInstrumentationCallbacks &PIC); }; +/// This class implements --time-trace functionality for new pass manager. +/// It provides the pass-instrumentation callbacks that measure the pass +/// execution time. They collect time tracing info by TimeProfiler. +class TimeProfilingPassesHandler { +public: + TimeProfilingPassesHandler(); + // We intend this to be unique per-compilation, thus no copies. + TimeProfilingPassesHandler(const TimeProfilingPassesHandler &) = delete; + void operator=(const TimeProfilingPassesHandler &) = delete; + + void registerCallbacks(PassInstrumentationCallbacks &PIC); + +private: + // Implementation of pass instrumentation callbacks. + void runBeforePass(StringRef PassID, Any IR); + void runAfterPass(); +}; + // Class that holds transitions between basic blocks. The transitions // are contained in a map of values to names of basic blocks. class DCData { @@ -505,6 +524,7 @@ PrintIRInstrumentation PrintIR; PrintPassInstrumentation PrintPass; TimePassesHandler TimePasses; + TimeProfilingPassesHandler TimeProfilingPasses; OptNoneInstrumentation OptNone; OptBisectInstrumentation OptBisect; PreservedCFGCheckerInstrumentation PreservedCFGChecker; 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 @@ -392,11 +392,7 @@ if (!PI.runBeforePass(*Pass, L)) return None; - PreservedAnalyses PA; - { - TimeTraceScope TimeScope(Pass->name(), IR.getName()); - PA = Pass->run(IR, AM, AR, U); - } + PreservedAnalyses PA = Pass->run(IR, AM, AR, U); // do not pass deleted Loop into the instrumentation if (U.skipCurrentLoop()) 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 @@ -84,11 +84,7 @@ if (!PI.runBeforePass(*Pass, *C)) continue; - PreservedAnalyses PassPA; - { - TimeTraceScope TimeScope(Pass->name()); - PassPA = Pass->run(*C, AM, G, UR); - } + PreservedAnalyses PassPA = Pass->run(*C, AM, G, UR); if (UR.InvalidatedSCCs.count(C)) PI.runAfterPassInvalidated(*Pass, PassPA); @@ -277,11 +273,7 @@ if (!PI.runBeforePass(*Pass, *C)) continue; - PreservedAnalyses PassPA; - { - TimeTraceScope TimeScope(Pass->name()); - PassPA = Pass->run(*C, CGAM, CG, UR); - } + PreservedAnalyses PassPA = Pass->run(*C, CGAM, CG, UR); if (UR.InvalidatedSCCs.count(C)) PI.runAfterPassInvalidated(*Pass, PassPA); @@ -548,12 +540,7 @@ if (!PI.runBeforePass(*Pass, F)) continue; - PreservedAnalyses PassPA; - { - TimeTraceScope TimeScope(Pass->name()); - PassPA = Pass->run(F, FAM); - } - + PreservedAnalyses PassPA = Pass->run(F, FAM); PI.runAfterPass(*Pass, F, PassPA); // We know that the function pass couldn't have invalidated any other diff --git a/llvm/lib/IR/PassManager.cpp b/llvm/lib/IR/PassManager.cpp --- a/llvm/lib/IR/PassManager.cpp +++ b/llvm/lib/IR/PassManager.cpp @@ -121,12 +121,7 @@ if (!PI.runBeforePass(*Pass, F)) continue; - PreservedAnalyses PassPA; - { - TimeTraceScope TimeScope(Pass->name(), F.getName()); - PassPA = Pass->run(F, FAM); - } - + PreservedAnalyses PassPA = Pass->run(F, FAM); PI.runAfterPass(*Pass, F, PassPA); // We know that the function pass couldn't have invalidated any other 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 @@ -1161,6 +1161,34 @@ TextChangeReporter>::registerRequiredCallbacks(PIC); } +TimeProfilingPassesHandler::TimeProfilingPassesHandler() {} + +void TimeProfilingPassesHandler::registerCallbacks( + PassInstrumentationCallbacks &PIC) { + if (!getTimeTraceProfilerInstance()) + return; + PIC.registerBeforeNonSkippedPassCallback( + [this](StringRef P, Any IR) { this->runBeforePass(P, IR); }); + PIC.registerAfterPassCallback( + [this](StringRef P, Any IR, const PreservedAnalyses &) { + this->runAfterPass(); + }, + true); + PIC.registerAfterPassInvalidatedCallback( + [this](StringRef P, const PreservedAnalyses &) { this->runAfterPass(); }, + true); + PIC.registerBeforeAnalysisCallback( + [this](StringRef P, Any IR) { this->runBeforePass(P, IR); }); + PIC.registerAfterAnalysisCallback( + [this](StringRef P, Any IR) { this->runAfterPass(); }, true); +} + +void TimeProfilingPassesHandler::runBeforePass(StringRef PassID, Any IR) { + timeTraceProfilerBegin(PassID, getIRName(IR)); +} + +void TimeProfilingPassesHandler::runAfterPass() { timeTraceProfilerEnd(); } + namespace { class DisplayNode; @@ -2077,6 +2105,13 @@ PrintChangedDiff.registerCallbacks(PIC); WebsiteChangeReporter.registerCallbacks(PIC); PrintCrashIR.registerCallbacks(PIC); + // TimeProfiling records the pass running time cost. + // Its 'BeforePassCallback' can be appended at the tail of all the + // BeforeCallbacks by calling `registerCallbacks` in the end. + // Its 'AfterPassCallback' is put at the front of all the + // AfterCallbacks by its `registerCallbacks`. This is necessary + // to ensure that other callbacks are not included in the timings. + TimeProfilingPasses.registerCallbacks(PIC); } template class ChangeReporter; 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 @@ -291,11 +291,7 @@ if (!PI.runBeforePass(*Pass, *L)) continue; - PreservedAnalyses PassPA; - { - TimeTraceScope TimeScope(Pass->name()); - PassPA = Pass->run(*L, LAM, LAR, Updater); - } + PreservedAnalyses PassPA = Pass->run(*L, LAM, LAR, Updater); // Do not pass deleted Loop into the instrumentation. if (Updater.skipCurrentLoop())