[NFC][PassTiming] factor out generic PassTimingInfo

Moving PassTimingInfo from legacy pass manager code into a separate header.
Making it suitable for both legacy and new pass manager.
Adding a test on -time-passes main functionality.

llvm-svn: 340872
This commit is contained in:
Fedor Sergeev 2018-08-28 21:06:51 +00:00
parent da787801e8
commit 3dcc0c90de
9 changed files with 221 additions and 97 deletions

View File

@ -508,7 +508,6 @@ public:
}
};
Timer *getPassTimer(Pass *);
}
#endif

View File

@ -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 <string>
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 <typename PassInfoT> class PassTimingInfo {
StringMap<Timer *> 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

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -44,6 +44,7 @@ add_llvm_library(LLVMCore
Pass.cpp
PassManager.cpp
PassRegistry.cpp
PassTimingInfo.cpp
SafepointIRVerifier.cpp
ProfileSummary.cpp
Statepoint.cpp

View File

@ -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 @@ char PassManagerImpl::ID = 0;
} // 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<sys::SmartMutex<true> > TimingInfoMutex;
class TimingInfo {
DenseMap<Pass*, Timer*> 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<true> 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 @@ void FunctionPassManagerImpl::releaseMemoryOnTheFly() {
// 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 @@ Pass* MPPassManager::getOnTheFlyPass(Pass *MP, AnalysisID PI, Function &F){
/// 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 @@ bool PassManager::run(Module &M) {
return PM->run(M);
}
//===----------------------------------------------------------------------===//
// TimingInfo implementation
bool llvm::TimePassesIsEnabled = false;
static cl::opt<bool, true> 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<TimingInfo> 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
//

132
lib/IR/PassTimingInfo.cpp Normal file
View File

@ -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 <string>
using namespace llvm;
namespace llvm {
//===----------------------------------------------------------------------===//
// TimingInfo implementation
bool TimePassesIsEnabled = false;
static cl::opt<bool, true> EnableTiming(
"time-passes", cl::location(TimePassesIsEnabled), cl::Hidden,
cl::desc("Time each pass, printing elapsed time for each on exit"));
namespace {
static ManagedStatic<sys::SmartMutex<true>> TimingInfoMutex;
}
template <typename PassT>
PassTimingInfo<PassT>::PassTimingInfo()
: TG("pass", "... Pass execution timing report ...") {}
template <typename PassT> PassTimingInfo<PassT>::~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 <typename PassT> void PassTimingInfo<PassT>::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<PassTimingInfo> TTI;
TheTimeInfo = &*TTI;
}
/// Prints out timing information and then resets the timers.
template <typename PassT> void PassTimingInfo<PassT>::print() {
TG.print(*CreateInfoOutputFile());
}
/// Return the timer for the specified pass if it exists.
template <> Timer *PassTimingInfo<StringRef>::getPassTimer(StringRef PassName) {
init();
sys::SmartScopedLock<true> Lock(*TimingInfoMutex);
Timer *&T = TimingData[PassName];
if (!T)
T = new Timer(PassName, PassName, TG);
return T;
}
template <> Timer *PassTimingInfo<Pass *>::getPassTimer(Pass *P) {
if (P->getAsPMDataManager())
return nullptr;
init();
sys::SmartScopedLock<true> 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 <typename PassInfoT>
PassTimingInfo<PassInfoT> *PassTimingInfo<PassInfoT>::TheTimeInfo;
template class PassTimingInfo<Pass *>;
template class PassTimingInfo<StringRef>;
Timer *getPassTimer(Pass *P) {
PassTimingInfo<Pass *>::init();
if (PassTimingInfo<Pass *>::TheTimeInfo)
return PassTimingInfo<Pass *>::TheTimeInfo->getPassTimer(P);
return nullptr;
}
Timer *getPassTimer(StringRef PassName) {
PassTimingInfo<StringRef>::init();
if (PassTimingInfo<StringRef>::TheTimeInfo)
return PassTimingInfo<StringRef>::TheTimeInfo->getPassTimer(PassName);
return nullptr;
}
/// If timing is enabled, report the times collected up to now and then reset
/// them.
void reportAndResetTimings() {
if (PassTimingInfo<StringRef>::TheTimeInfo)
PassTimingInfo<StringRef>::TheTimeInfo->print();
if (PassTimingInfo<Pass *>::TheTimeInfo)
PassTimingInfo<Pass *>::TheTimeInfo->print();
}
} // namespace llvm

15
test/Other/time-passes.ll Normal file
View File

@ -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
}