mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[Legacy][TimePasses] allow -time-passes reporting into a custom stream
As a followup to newpm -time-passes fix (D59366), now adding a similar functionality to legacy time-passes. Enhancing llvm::reportAndResetTimings to accept an optional stream for reporting output. By default it still reports into the stream created by CreateInfoOutputFile (-info-output-file). Also fixing to actually reset after printing as declared. Reviewed By: philip.pfaffe Differential Revision: https://reviews.llvm.org/D59416 llvm-svn: 356824
This commit is contained in:
parent
2bf165c415
commit
839e3bf0f9
@ -29,8 +29,9 @@ class PassInstrumentationCallbacks;
|
|||||||
class raw_ostream;
|
class raw_ostream;
|
||||||
|
|
||||||
/// If -time-passes has been specified, report the timings immediately and then
|
/// If -time-passes has been specified, report the timings immediately and then
|
||||||
/// reset the timers to zero.
|
/// reset the timers to zero. By default it uses the stream created by
|
||||||
void reportAndResetTimings();
|
/// CreateInfoOutputFile().
|
||||||
|
void reportAndResetTimings(raw_ostream *OutStream = nullptr);
|
||||||
|
|
||||||
/// Request the timer for this legacy-pass-manager's pass instance.
|
/// Request the timer for this legacy-pass-manager's pass instance.
|
||||||
Timer *getPassTimer(Pass *);
|
Timer *getPassTimer(Pass *);
|
||||||
@ -64,8 +65,8 @@ class TimePassesHandler {
|
|||||||
SmallVector<Timer *, 8> TimerStack;
|
SmallVector<Timer *, 8> TimerStack;
|
||||||
|
|
||||||
/// Custom output stream to print timing information into.
|
/// Custom output stream to print timing information into.
|
||||||
/// By default (== nullptr) we emit time report into the stream controlled by
|
/// By default (== nullptr) we emit time report into the stream created by
|
||||||
/// -info-output-file.
|
/// CreateInfoOutputFile().
|
||||||
raw_ostream *OutStream = nullptr;
|
raw_ostream *OutStream = nullptr;
|
||||||
|
|
||||||
bool Enabled;
|
bool Enabled;
|
||||||
|
@ -205,8 +205,9 @@ public:
|
|||||||
Description.assign(NewDescription.begin(), NewDescription.end());
|
Description.assign(NewDescription.begin(), NewDescription.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print any started timers in this group.
|
/// Print any started timers in this group, optionally resetting timers after
|
||||||
void print(raw_ostream &OS);
|
/// printing them.
|
||||||
|
void print(raw_ostream &OS, bool ResetAfterPrint = false);
|
||||||
|
|
||||||
/// Clear all timers in this group.
|
/// Clear all timers in this group.
|
||||||
void clear();
|
void clear();
|
||||||
@ -233,7 +234,7 @@ private:
|
|||||||
friend void PrintStatisticsJSON(raw_ostream &OS);
|
friend void PrintStatisticsJSON(raw_ostream &OS);
|
||||||
void addTimer(Timer &T);
|
void addTimer(Timer &T);
|
||||||
void removeTimer(Timer &T);
|
void removeTimer(Timer &T);
|
||||||
void prepareToPrintList();
|
void prepareToPrintList(bool reset_time = false);
|
||||||
void PrintQueuedTimers(raw_ostream &OS);
|
void PrintQueuedTimers(raw_ostream &OS);
|
||||||
void printJSONValue(raw_ostream &OS, const PrintRecord &R,
|
void printJSONValue(raw_ostream &OS, const PrintRecord &R,
|
||||||
const char *suffix, double Value);
|
const char *suffix, double Value);
|
||||||
|
@ -77,7 +77,8 @@ public:
|
|||||||
static void init();
|
static void init();
|
||||||
|
|
||||||
/// Prints out timing information and then resets the timers.
|
/// Prints out timing information and then resets the timers.
|
||||||
void print();
|
/// By default it uses the stream created by CreateInfoOutputFile().
|
||||||
|
void print(raw_ostream *OutStream = nullptr);
|
||||||
|
|
||||||
/// Returns the timer for the specified pass if it exists.
|
/// Returns the timer for the specified pass if it exists.
|
||||||
Timer *getPassTimer(Pass *, PassInstanceID);
|
Timer *getPassTimer(Pass *, PassInstanceID);
|
||||||
@ -111,7 +112,9 @@ void PassTimingInfo::init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Prints out timing information and then resets the timers.
|
/// Prints out timing information and then resets the timers.
|
||||||
void PassTimingInfo::print() { TG.print(*CreateInfoOutputFile()); }
|
void PassTimingInfo::print(raw_ostream *OutStream) {
|
||||||
|
TG.print(OutStream ? *OutStream : *CreateInfoOutputFile(), true);
|
||||||
|
}
|
||||||
|
|
||||||
Timer *PassTimingInfo::newPassTimer(StringRef PassID, StringRef PassDesc) {
|
Timer *PassTimingInfo::newPassTimer(StringRef PassID, StringRef PassDesc) {
|
||||||
unsigned &num = PassIDCountMap[PassID];
|
unsigned &num = PassIDCountMap[PassID];
|
||||||
@ -153,9 +156,9 @@ Timer *getPassTimer(Pass *P) {
|
|||||||
|
|
||||||
/// If timing is enabled, report the times collected up to now and then reset
|
/// If timing is enabled, report the times collected up to now and then reset
|
||||||
/// them.
|
/// them.
|
||||||
void reportAndResetTimings() {
|
void reportAndResetTimings(raw_ostream *OutStream) {
|
||||||
if (legacy::PassTimingInfo::TheTimeInfo)
|
if (legacy::PassTimingInfo::TheTimeInfo)
|
||||||
legacy::PassTimingInfo::TheTimeInfo->print();
|
legacy::PassTimingInfo::TheTimeInfo->print(OutStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -188,8 +191,7 @@ void TimePassesHandler::setOutStream(raw_ostream &Out) {
|
|||||||
void TimePassesHandler::print() {
|
void TimePassesHandler::print() {
|
||||||
if (!Enabled)
|
if (!Enabled)
|
||||||
return;
|
return;
|
||||||
TG.print(OutStream ? *OutStream : *CreateInfoOutputFile());
|
TG.print(OutStream ? *OutStream : *CreateInfoOutputFile(), true);
|
||||||
TG.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVM_DUMP_METHOD void TimePassesHandler::dump() const {
|
LLVM_DUMP_METHOD void TimePassesHandler::dump() const {
|
||||||
|
@ -347,7 +347,7 @@ void TimerGroup::PrintQueuedTimers(raw_ostream &OS) {
|
|||||||
TimersToPrint.clear();
|
TimersToPrint.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerGroup::prepareToPrintList() {
|
void TimerGroup::prepareToPrintList(bool ResetTime) {
|
||||||
// See if any of our timers were started, if so add them to TimersToPrint.
|
// See if any of our timers were started, if so add them to TimersToPrint.
|
||||||
for (Timer *T = FirstTimer; T; T = T->Next) {
|
for (Timer *T = FirstTimer; T; T = T->Next) {
|
||||||
if (!T->hasTriggered()) continue;
|
if (!T->hasTriggered()) continue;
|
||||||
@ -357,15 +357,20 @@ void TimerGroup::prepareToPrintList() {
|
|||||||
|
|
||||||
TimersToPrint.emplace_back(T->Time, T->Name, T->Description);
|
TimersToPrint.emplace_back(T->Time, T->Name, T->Description);
|
||||||
|
|
||||||
|
if (ResetTime)
|
||||||
|
T->clear();
|
||||||
|
|
||||||
if (WasRunning)
|
if (WasRunning)
|
||||||
T->startTimer();
|
T->startTimer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerGroup::print(raw_ostream &OS) {
|
void TimerGroup::print(raw_ostream &OS, bool ResetAfterPrint) {
|
||||||
sys::SmartScopedLock<true> L(*TimerLock);
|
{
|
||||||
|
// After preparing the timers we can free the lock
|
||||||
prepareToPrintList();
|
sys::SmartScopedLock<true> L(*TimerLock);
|
||||||
|
prepareToPrintList(ResetAfterPrint);
|
||||||
|
}
|
||||||
|
|
||||||
// If any timers were started, print the group.
|
// If any timers were started, print the group.
|
||||||
if (!TimersToPrint.empty())
|
if (!TimersToPrint.empty())
|
||||||
@ -405,7 +410,7 @@ void TimerGroup::printJSONValue(raw_ostream &OS, const PrintRecord &R,
|
|||||||
const char *TimerGroup::printJSONValues(raw_ostream &OS, const char *delim) {
|
const char *TimerGroup::printJSONValues(raw_ostream &OS, const char *delim) {
|
||||||
sys::SmartScopedLock<true> L(*TimerLock);
|
sys::SmartScopedLock<true> L(*TimerLock);
|
||||||
|
|
||||||
prepareToPrintList();
|
prepareToPrintList(false);
|
||||||
for (const PrintRecord &R : TimersToPrint) {
|
for (const PrintRecord &R : TimersToPrint) {
|
||||||
OS << delim;
|
OS << delim;
|
||||||
delim = ",\n";
|
delim = ",\n";
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <llvm/ADT/SmallString.h>
|
#include <llvm/ADT/SmallString.h>
|
||||||
|
#include "llvm/IR/LegacyPassManager.h"
|
||||||
#include <llvm/IR/LLVMContext.h>
|
#include <llvm/IR/LLVMContext.h>
|
||||||
#include <llvm/IR/Module.h>
|
#include <llvm/IR/Module.h>
|
||||||
#include <llvm/IR/PassInstrumentation.h>
|
#include <llvm/IR/PassInstrumentation.h>
|
||||||
@ -17,7 +18,97 @@
|
|||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Define dummy passes for legacy pass manager run.
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
|
void initializePass1Pass(PassRegistry &);
|
||||||
|
void initializePass2Pass(PassRegistry &);
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
struct Pass1 : public ModulePass {
|
||||||
|
static char ID;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Pass1() : ModulePass(ID) {}
|
||||||
|
bool runOnModule(Module &M) override { return false; }
|
||||||
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||||
|
AU.setPreservesAll();
|
||||||
|
}
|
||||||
|
StringRef getPassName() const override { return "Pass1"; }
|
||||||
|
};
|
||||||
|
char Pass1::ID;
|
||||||
|
|
||||||
|
struct Pass2 : public ModulePass {
|
||||||
|
static char ID;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Pass2() : ModulePass(ID) {}
|
||||||
|
bool runOnModule(Module &M) override { return false; }
|
||||||
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||||
|
AU.setPreservesAll();
|
||||||
|
}
|
||||||
|
StringRef getPassName() const override { return "Pass2"; }
|
||||||
|
};
|
||||||
|
char Pass2::ID;
|
||||||
|
} // namespace
|
||||||
|
} // namespace llvm
|
||||||
|
|
||||||
|
INITIALIZE_PASS(Pass1, "Pass1", "Pass1", false, false)
|
||||||
|
INITIALIZE_PASS(Pass2, "Pass2", "Pass2", false, false)
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
TEST(TimePassesTest, LegacyCustomOut) {
|
||||||
|
PassInstrumentationCallbacks PIC;
|
||||||
|
PassInstrumentation PI(&PIC);
|
||||||
|
|
||||||
|
LLVMContext Context;
|
||||||
|
Module M("TestModule", Context);
|
||||||
|
|
||||||
|
SmallString<0> TimePassesStr;
|
||||||
|
raw_svector_ostream ReportStream(TimePassesStr);
|
||||||
|
|
||||||
|
// Setup pass manager
|
||||||
|
legacy::PassManager PM1;
|
||||||
|
PM1.add(new llvm::Pass1());
|
||||||
|
PM1.add(new llvm::Pass2());
|
||||||
|
|
||||||
|
// Enable time-passes and run passes.
|
||||||
|
TimePassesIsEnabled = true;
|
||||||
|
PM1.run(M);
|
||||||
|
|
||||||
|
// Generating report.
|
||||||
|
reportAndResetTimings(&ReportStream);
|
||||||
|
|
||||||
|
// There should be Pass1 and Pass2 in the report
|
||||||
|
EXPECT_FALSE(TimePassesStr.empty());
|
||||||
|
EXPECT_TRUE(TimePassesStr.str().contains("report"));
|
||||||
|
EXPECT_TRUE(TimePassesStr.str().contains("Pass1"));
|
||||||
|
EXPECT_TRUE(TimePassesStr.str().contains("Pass2"));
|
||||||
|
|
||||||
|
// Clear and generate report again.
|
||||||
|
TimePassesStr.clear();
|
||||||
|
reportAndResetTimings(&ReportStream);
|
||||||
|
|
||||||
|
// Since we did not run any passes since last print, report should be empty.
|
||||||
|
EXPECT_TRUE(TimePassesStr.empty());
|
||||||
|
|
||||||
|
// Now run just a single pass to populate timers again.
|
||||||
|
legacy::PassManager PM2;
|
||||||
|
PM2.add(new llvm::Pass2());
|
||||||
|
PM2.run(M);
|
||||||
|
|
||||||
|
// Generate report again.
|
||||||
|
reportAndResetTimings(&ReportStream);
|
||||||
|
|
||||||
|
// There should be Pass2 in this report and no Pass1.
|
||||||
|
EXPECT_FALSE(TimePassesStr.str().empty());
|
||||||
|
EXPECT_TRUE(TimePassesStr.str().contains("report"));
|
||||||
|
EXPECT_FALSE(TimePassesStr.str().contains("Pass1"));
|
||||||
|
EXPECT_TRUE(TimePassesStr.str().contains("Pass2"));
|
||||||
|
}
|
||||||
|
|
||||||
class MyPass1 : public PassInfoMixin<MyPass1> {};
|
class MyPass1 : public PassInfoMixin<MyPass1> {};
|
||||||
class MyPass2 : public PassInfoMixin<MyPass2> {};
|
class MyPass2 : public PassInfoMixin<MyPass2> {};
|
||||||
@ -40,7 +131,7 @@ TEST(TimePassesTest, CustomOut) {
|
|||||||
TimePasses->setOutStream(ReportStream);
|
TimePasses->setOutStream(ReportStream);
|
||||||
TimePasses->registerCallbacks(PIC);
|
TimePasses->registerCallbacks(PIC);
|
||||||
|
|
||||||
// Running some passes to trigger the timers.
|
// Pretending that passes are running to trigger the timers.
|
||||||
PI.runBeforePass(Pass1, M);
|
PI.runBeforePass(Pass1, M);
|
||||||
PI.runBeforePass(Pass2, M);
|
PI.runBeforePass(Pass2, M);
|
||||||
PI.runAfterPass(Pass2, M);
|
PI.runAfterPass(Pass2, M);
|
||||||
@ -61,7 +152,7 @@ TEST(TimePassesTest, CustomOut) {
|
|||||||
// Since we did not run any passes since last print, report should be empty.
|
// Since we did not run any passes since last print, report should be empty.
|
||||||
EXPECT_TRUE(TimePassesStr.empty());
|
EXPECT_TRUE(TimePassesStr.empty());
|
||||||
|
|
||||||
// Now run just a single pass to populate timers again.
|
// Now trigger just a single pass to populate timers again.
|
||||||
PI.runBeforePass(Pass2, M);
|
PI.runBeforePass(Pass2, M);
|
||||||
PI.runAfterPass(Pass2, M);
|
PI.runAfterPass(Pass2, M);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user