Index: include/llvm/IR/LegacyPassManagers.h =================================================================== --- include/llvm/IR/LegacyPassManagers.h +++ include/llvm/IR/LegacyPassManagers.h @@ -508,7 +508,6 @@ } }; -Timer *getPassTimer(Pass *); } #endif Index: include/llvm/IR/PassTimingInfo.h =================================================================== --- /dev/null +++ include/llvm/IR/PassTimingInfo.h @@ -0,0 +1,69 @@ +//===- PassTimingInfo.h - pass execution timing -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This header defines classes/functions to handle pass execution timing +/// information with an interface suitable for both pass managers. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_PASSTIMINGINFO_H +#define LLVM_IR_PASSTIMINGINFO_H + +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Timer.h" +#include + +namespace llvm { + +class Pass; +class TimerGroup; + +/// Provides a generic interface for collecting pass timing information. +/// Legacy pass managers should specialize with \p PassInfo*. +/// New pass managers should specialize with \p StringRef. +template class PassTimingInfo { + StringMap TimingData; + TimerGroup TG; + +public: + /// Default constructor for yet-inactive timeinfo. + /// Use \p init() to activate it. + PassTimingInfo(); + + /// Print out timing information and release timers. + ~PassTimingInfo(); + + /// Initializes the static \p TheTimeInfo member to a non-null value when + /// -time-passes is enabled. Leaves it null otherwise. + /// + /// This method may be called multiple times. + static void init(); + + /// Prints out timing information and then resets the timers. + void print(); + + /// Returns the timer for the specified pass if it exists. + Timer *getPassTimer(PassInfoT); + + static PassTimingInfo *TheTimeInfo; +}; + +Timer *getPassTimer(Pass *); +Timer *getPassTimer(StringRef); + +/// 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; + +} // namespace llvm + +#endif Index: lib/Analysis/CallGraphSCCPass.cpp =================================================================== --- lib/Analysis/CallGraphSCCPass.cpp +++ lib/Analysis/CallGraphSCCPass.cpp @@ -27,6 +27,7 @@ #include "llvm/IR/LegacyPassManagers.h" #include "llvm/IR/Module.h" #include "llvm/IR/OptBisect.h" +#include "llvm/IR/PassTimingInfo.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" Index: lib/Analysis/LoopPass.cpp =================================================================== --- lib/Analysis/LoopPass.cpp +++ lib/Analysis/LoopPass.cpp @@ -20,6 +20,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/OptBisect.h" #include "llvm/IR/PassManager.h" +#include "llvm/IR/PassTimingInfo.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" Index: lib/Analysis/RegionPass.cpp =================================================================== --- lib/Analysis/RegionPass.cpp +++ lib/Analysis/RegionPass.cpp @@ -15,6 +15,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/RegionPass.h" #include "llvm/IR/OptBisect.h" +#include "llvm/IR/PassTimingInfo.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" Index: lib/IR/CMakeLists.txt =================================================================== --- lib/IR/CMakeLists.txt +++ lib/IR/CMakeLists.txt @@ -44,6 +44,7 @@ Pass.cpp PassManager.cpp PassRegistry.cpp + PassTimingInfo.cpp SafepointIRVerifier.cpp ProfileSummary.cpp Statepoint.cpp Index: lib/IR/LegacyPassManager.cpp =================================================================== --- lib/IR/LegacyPassManager.cpp +++ lib/IR/LegacyPassManager.cpp @@ -20,6 +20,7 @@ #include "llvm/IR/LegacyPassManagers.h" #include "llvm/IR/LegacyPassNameParser.h" #include "llvm/IR/Module.h" +#include "llvm/IR/PassTimingInfo.h" #include "llvm/Support/Chrono.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -494,65 +495,6 @@ } // End of legacy namespace } // End of llvm namespace -namespace { - -//===----------------------------------------------------------------------===// -/// TimingInfo Class - This class is used to calculate information about the -/// amount of time each pass takes to execute. This only happens when -/// -time-passes is enabled on the command line. -/// - -static ManagedStatic > TimingInfoMutex; - -class TimingInfo { - DenseMap TimingData; - TimerGroup TG; -public: - // Use 'create' member to get this. - TimingInfo() : TG("pass", "... Pass execution timing report ...") {} - - // TimingDtor - Print out information about timing information - ~TimingInfo() { - // Delete all of the timers, which accumulate their info into the - // TimerGroup. - for (auto &I : TimingData) - delete I.second; - // TimerGroup is deleted next, printing the report. - } - - // createTheTimeInfo - This method either initializes the TheTimeInfo pointer - // to a non-null value (if the -time-passes option is enabled) or it leaves it - // null. It may be called multiple times. - static void createTheTimeInfo(); - - // print - Prints out timing information and then resets the timers. - void print() { - TG.print(*CreateInfoOutputFile()); - } - - /// getPassTimer - Return the timer for the specified pass if it exists. - Timer *getPassTimer(Pass *P) { - if (P->getAsPMDataManager()) - return nullptr; - - sys::SmartScopedLock Lock(*TimingInfoMutex); - Timer *&T = TimingData[P]; - if (!T) { - StringRef PassName = P->getPassName(); - StringRef PassArgument; - if (const PassInfo *PI = Pass::lookupPassInfo(P->getPassID())) - PassArgument = PI->getPassArgument(); - T = new Timer(PassArgument.empty() ? PassName : PassArgument, PassName, - TG); - } - return T; - } -}; - -} // End of anon namespace - -static TimingInfo *TheTimeInfo; - //===----------------------------------------------------------------------===// // PMTopLevelManager implementation @@ -1527,7 +1469,6 @@ // Return true if any function is modified by a pass. bool FunctionPassManagerImpl::run(Function &F) { bool Changed = false; - TimingInfo::createTheTimeInfo(); initializeAllAnalysisInfo(); for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) { @@ -1763,7 +1704,6 @@ /// whether any of the passes modifies the module, and if so, return true. bool PassManagerImpl::run(Module &M) { bool Changed = false; - TimingInfo::createTheTimeInfo(); dumpArguments(); dumpPasses(); @@ -1807,41 +1747,6 @@ return PM->run(M); } -//===----------------------------------------------------------------------===// -// TimingInfo implementation - -bool llvm::TimePassesIsEnabled = false; -static cl::opt EnableTiming( - "time-passes", cl::location(TimePassesIsEnabled), cl::Hidden, - cl::desc("Time each pass, printing elapsed time for each on exit")); - -// createTheTimeInfo - This method either initializes the TheTimeInfo pointer to -// a non-null value (if the -time-passes option is enabled) or it leaves it -// null. It may be called multiple times. -void TimingInfo::createTheTimeInfo() { - if (!TimePassesIsEnabled || TheTimeInfo) return; - - // Constructed the first time this is called, iff -time-passes is enabled. - // This guarantees that the object will be constructed before static globals, - // thus it will be destroyed before them. - static ManagedStatic TTI; - TheTimeInfo = &*TTI; -} - -/// If TimingInfo is enabled then start pass timer. -Timer *llvm::getPassTimer(Pass *P) { - if (TheTimeInfo) - return TheTimeInfo->getPassTimer(P); - return nullptr; -} - -/// If timing is enabled, report the times collected up to now and then reset -/// them. -void llvm::reportAndResetTimings() { - if (TheTimeInfo) - TheTimeInfo->print(); -} - //===----------------------------------------------------------------------===// // PMStack implementation // Index: lib/IR/PassTimingInfo.cpp =================================================================== --- /dev/null +++ lib/IR/PassTimingInfo.cpp @@ -0,0 +1,132 @@ +//===- PassTimingInfo.cpp - LLVM Pass Timing Implementation ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the LLVM Pass Timing infrastructure for both +// new and legacy pass managers. +// +// TimingInfo Class - This class is used to calculate information about the +// amount of time each pass takes to execute. This only happens when +// -time-passes is enabled on the command line. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/PassTimingInfo.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Pass.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Support/Timer.h" +#include "llvm/Support/raw_ostream.h" +#include + +using namespace llvm; + +namespace llvm { + +//===----------------------------------------------------------------------===// +// TimingInfo implementation + +bool TimePassesIsEnabled = false; +static cl::opt EnableTiming( + "time-passes", cl::location(TimePassesIsEnabled), cl::Hidden, + cl::desc("Time each pass, printing elapsed time for each on exit")); + +namespace { +static ManagedStatic> TimingInfoMutex; +} + +template +PassTimingInfo::PassTimingInfo() + : TG("pass", "... Pass execution timing report ...") {} + +template PassTimingInfo::~PassTimingInfo() { + // Deleting the timers accumulates their info into the TG member. + // Then TG member is (implicitly) deleted, actually printing the report. + for (auto &I : TimingData) + delete I.getValue(); +} + +template void PassTimingInfo::init() { + if (!TimePassesIsEnabled || TheTimeInfo) + return; + + // Constructed the first time this is called, iff -time-passes is enabled. + // This guarantees that the object will be constructed before static globals, + // thus it will be destroyed before them. + static ManagedStatic TTI; + TheTimeInfo = &*TTI; +} + +/// Prints out timing information and then resets the timers. +template void PassTimingInfo::print() { + TG.print(*CreateInfoOutputFile()); +} + +/// Return the timer for the specified pass if it exists. +template <> Timer *PassTimingInfo::getPassTimer(StringRef PassName) { + init(); + sys::SmartScopedLock Lock(*TimingInfoMutex); + Timer *&T = TimingData[PassName]; + if (!T) + T = new Timer(PassName, PassName, TG); + return T; +} + +template <> Timer *PassTimingInfo::getPassTimer(Pass *P) { + if (P->getAsPMDataManager()) + return nullptr; + + init(); + sys::SmartScopedLock Lock(*TimingInfoMutex); + StringRef PassName = P->getPassName(); + Timer *&T = TimingData[PassName]; + + if (!T) { + StringRef PassArgument; + if (const PassInfo *PI = Pass::lookupPassInfo(P->getPassID())) + PassArgument = PI->getPassArgument(); + T = new Timer(PassArgument.empty() ? PassName : PassArgument, PassName, TG); + } + return T; +} + +template +PassTimingInfo *PassTimingInfo::TheTimeInfo; + +template class PassTimingInfo; +template class PassTimingInfo; + +Timer *getPassTimer(Pass *P) { + PassTimingInfo::init(); + if (PassTimingInfo::TheTimeInfo) + return PassTimingInfo::TheTimeInfo->getPassTimer(P); + return nullptr; +} + +Timer *getPassTimer(StringRef PassName) { + PassTimingInfo::init(); + if (PassTimingInfo::TheTimeInfo) + return PassTimingInfo::TheTimeInfo->getPassTimer(PassName); + 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(); +} + +} // namespace llvm Index: test/Other/time-passes.ll =================================================================== --- /dev/null +++ test/Other/time-passes.ll @@ -0,0 +1,15 @@ +; RUN: opt < %s -disable-output -instcombine -time-passes 2>&1 | FileCheck %s --check-prefix=TIME --check-prefix=TIME-LEGACY +; +; TIME: Pass execution timing report +; TIME: Total Execution Time: +; TIME: Name +; TIME-LEGACY-DAG: Combine redundant instructions +; TIME-LEGACY-DAG: Dominator Tree Construction +; TIME-LEGACY-DAG: Module Verifier +; TIME-LEGACY-DAG: Target Library Information +; TIME: 100{{.*}} Total{{$}} + +define i32 @foo() { + %res = add i32 5, 4 + ret i32 %res +}