Index: include/llvm/IR/PassTimingInfo.h =================================================================== --- include/llvm/IR/PassTimingInfo.h +++ include/llvm/IR/PassTimingInfo.h @@ -19,6 +19,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/IR/PassInstrumentation.h" #include "llvm/Support/Timer.h" #include @@ -31,12 +32,9 @@ /// Legacy pass managers should specialize with \p PassInfo*. /// New pass managers should specialize with \p StringRef. template class PassTimingInfo { -public: - using PassInstanceID = void *; - private: StringMap PassIDCountMap; ///< Map that counts instances of passes - DenseMap TimingData; ///< timers for pass instances + DenseMap TimingData; ///< timers for pass instances TimerGroup TG; public: @@ -57,7 +55,7 @@ void print(); /// Returns the timer for the specified pass if it exists. - Timer *getPassTimer(PassInfoT, PassInstanceID); + Timer *getPassTimer(PassInfoT); static PassTimingInfo *TheTimeInfo; @@ -66,13 +64,23 @@ }; Timer *getPassTimer(Pass *); -Timer *getPassTimer(StringRef); +Timer *getPassTimer(PassInstanceID); /// If the user specifies the -time-passes argument on an LLVM tool command line /// then the value of this boolean will be true, otherwise false. /// This is the storage for the -time-passes option. extern bool TimePassesIsEnabled; +// Implementation of timer callbacks +bool runTimerBeforePass(PassInstanceID PassID, Any IR, + PassExecutionLocation PC); +void stopTimerAfterPass(PassInstanceID PassID, Any IR, + PassExecutionLocation PC); +void startTimerForPassManager(PassInstanceID PassID, Any IR, + PassExecutionLocation); +void stopTimerForPassManager(PassInstanceID PassID, Any IR, + PassExecutionLocation); + } // namespace llvm #endif Index: lib/IR/PassTimingInfo.cpp =================================================================== --- lib/IR/PassTimingInfo.cpp +++ lib/IR/PassTimingInfo.cpp @@ -88,24 +88,22 @@ /// Instances of the same pass type (uniquely identified by \p PassID) are /// numbered by the order of appearance. template <> -Timer *PassTimingInfo::getPassTimer(StringRef PassID, - PassInstanceID Pass) { +Timer *PassTimingInfo::getPassTimer(PassInstanceID PassID) { init(); sys::SmartScopedLock Lock(*TimingInfoMutex); - Timer *&T = TimingData[Pass]; + Timer *&T = TimingData[PassID.getInstance()]; if (!T) - T = newPassTimer(PassID, PassID); + T = newPassTimer(PassID.getName(), PassID.getName()); return T; } -template <> -Timer *PassTimingInfo::getPassTimer(Pass *P, PassInstanceID Pass) { +template <> Timer *PassTimingInfo::getPassTimer(Pass *P) { if (P->getAsPMDataManager()) return nullptr; init(); sys::SmartScopedLock Lock(*TimingInfoMutex); - Timer *&T = TimingData[Pass]; + Timer *&T = TimingData[P]; if (!T) { StringRef PassName = P->getPassName(); @@ -121,30 +119,70 @@ PassTimingInfo *PassTimingInfo::TheTimeInfo; template class PassTimingInfo; -template class PassTimingInfo; +template class PassTimingInfo; Timer *getPassTimer(Pass *P) { PassTimingInfo::init(); if (PassTimingInfo::TheTimeInfo) - return PassTimingInfo::TheTimeInfo->getPassTimer(P, P); + return PassTimingInfo::TheTimeInfo->getPassTimer(P); return nullptr; } -Timer *getPassTimer(StringRef PassName) { - PassTimingInfo::init(); - if (PassTimingInfo::TheTimeInfo) - return PassTimingInfo::TheTimeInfo->getPassTimer(PassName, - nullptr); +Timer *getPassTimer(PassInstanceID Pass) { + PassTimingInfo::init(); + if (PassTimingInfo::TheTimeInfo) + return PassTimingInfo::TheTimeInfo->getPassTimer(Pass); return nullptr; } /// If timing is enabled, report the times collected up to now and then reset /// them. void reportAndResetTimings() { - if (PassTimingInfo::TheTimeInfo) - PassTimingInfo::TheTimeInfo->print(); + if (PassTimingInfo::TheTimeInfo) + PassTimingInfo::TheTimeInfo->print(); if (PassTimingInfo::TheTimeInfo) PassTimingInfo::TheTimeInfo->print(); } +static inline void startPassTimer(PassInstanceID PassID, bool only_triggered) { + Timer* MyTimer = getPassTimer(PassID); + if (MyTimer && !MyTimer->isRunning()) + if (!only_triggered || MyTimer->hasTriggered()) + MyTimer->startTimer(); +} + +static inline void stopPassTimer(PassInstanceID PassID) { + Timer* MyTimer = getPassTimer(PassID); + if (MyTimer && MyTimer->isRunning()) + MyTimer->stopTimer(); +} + +bool runTimerBeforePass(PassInstanceID PassID, Any IR, PassExecutionLocation PLoc) { + // first stop the pass-manager timer if still running + PassInstanceID PMID = PLoc.getPM(); + if (!PMID.emptyInstance()) + stopPassTimer(PMID); + // then start pass timer + startPassTimer(PassID, /* only_triggered */ false); + // we are not going to skip this pass, thus return true + return true; +} + +void stopTimerAfterPass(PassInstanceID PassID, Any IR, PassExecutionLocation PLoc) { + // stop the timer for this pass + stopPassTimer(PassID); + // restart pass-manager timer if it was running before + PassInstanceID PMID = PLoc.getPM(); + if (!PMID.emptyInstance()) + startPassTimer(PMID, /* only_triggered */ true); +} + +void startTimerForPassManager(PassInstanceID PassID, Any IR, PassExecutionLocation) { + startPassTimer(PassID, /* only_triggered */ false); +} + +void stopTimerForPassManager(PassInstanceID PassID, Any IR, PassExecutionLocation) { + stopPassTimer(PassID); +} + } // namespace llvm Index: lib/Passes/PassBuilder.cpp =================================================================== --- lib/Passes/PassBuilder.cpp +++ lib/Passes/PassBuilder.cpp @@ -57,6 +57,7 @@ #include "llvm/IR/Dominators.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/PassManager.h" +#include "llvm/IR/PassTimingInfo.h" #include "llvm/IR/Verifier.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Regex.h" @@ -1915,4 +1916,14 @@ registerPassInstrumentation([](PassInstrumentationImpl &PI) { PI.registerAfterPassCallback(PrintIR::printAfterPass); }); + if (llvm::TimePassesIsEnabled) { + registerPassInstrumentation([](PassInstrumentationImpl &PI) { + PI.registerBeforePassCallback(llvm::runTimerBeforePass); + PI.registerAfterPassCallback(llvm::stopTimerAfterPass); + PI.registerBeforeAnalysisCallback(llvm::runTimerBeforePass); + PI.registerAfterAnalysisCallback(llvm::stopTimerAfterPass); + PI.registerStartPassManagerCallback(llvm::startTimerForPassManager); + PI.registerFinishPassManagerCallback(llvm::stopTimerForPassManager); + }); + } } Index: test/Other/time-passes.ll =================================================================== --- test/Other/time-passes.ll +++ test/Other/time-passes.ll @@ -1,5 +1,7 @@ ; RUN: opt < %s -disable-output -instcombine -instcombine -licm -time-passes 2>&1 | FileCheck %s --check-prefix=TIME --check-prefix=TIME-LEGACY -; RUN: opt < %s -disable-output -instcombine -instcombine -licm -licm -time-passes 2>&1 | FileCheck %s --check-prefix=TIME --check-prefix=TIME-LEGACY --check-prefix=TIME-DOUBLE-LICM +; RUN: opt < %s -disable-output -instcombine -instcombine -licm -licm -time-passes 2>&1 | FileCheck %s --check-prefix=TIME --check-prefix=TIME-LEGACY --check-prefix=TIME-DOUBLE-LICM-LEGACY +; RUN: opt < %s -disable-output -passes='instcombine,instcombine,loop(licm)' -time-passes 2>&1 | FileCheck %s --check-prefix=TIME --check-prefix=TIME-NEW +; RUN: opt < %s -disable-output -passes='instcombine,loop(licm),instcombine,loop(licm)' -time-passes 2>&1 | FileCheck %s --check-prefix=TIME --check-prefix=TIME-NEW -check-prefix=TIME-DOUBLE-LICM-NEW ; ; TIME: Pass execution timing report ; TIME: Total Execution Time: @@ -7,7 +9,7 @@ ; TIME-LEGACY-DAG: Combine redundant instructions{{$}} ; TIME-LEGACY-DAG: Combine redundant instructions #2 ; TIME-LEGACY-DAG: Loop Invariant Code Motion{{$}} -; TIME-DOUBLE-LICM-DAG: Loop Invariant Code Motion #2 +; TIME-DOUBLE-LICM-LEGACY-DAG: Loop Invariant Code Motion #2 ; TIME-LEGACY-DAG: Scalar Evolution Analysis ; TIME-LEGACY-DAG: Loop-Closed SSA Form Pass ; TIME-LEGACY-DAG: LCSSA Verifier @@ -16,6 +18,17 @@ ; TIME-LEGACY-DAG: Dominator Tree Construction ; TIME-LEGACY-DAG: Module Verifier ; TIME-LEGACY-DAG: Target Library Information +; TIME-NEW-DAG: InstCombinePass{{$}} +; TIME-NEW-DAG: InstCombinePass #2 +; TIME-NEW-DAG: LICMPass{{$}} +; TIME-DOUBLE-LICM-NEW-DAG: LICMPass #2 +; TIME-NEW-DAG: LCSSAPass +; TIME-NEW-DAG: LoopSimplifyPass +; TIME-NEW-DAG: ScalarEvolutionAnalysis +; TIME-NEW-DAG: LoopAnalysis +; TIME-NEW-DAG: VerifierPass +; TIME-NEW-DAG: DominatorTreeAnalysis +; TIME-NEW-DAG: TargetLibraryAnalysis ; TIME: Total{{$}} define i32 @foo() {