Index: include/llvm/IR/PassTimingInfo.h =================================================================== --- include/llvm/IR/PassTimingInfo.h +++ include/llvm/IR/PassTimingInfo.h @@ -26,6 +26,7 @@ class Pass; class PassInstrumentationCallbacks; +class raw_ostream; /// If -time-passes has been specified, report the timings immediately and then /// reset the timers to zero. @@ -62,10 +63,17 @@ /// Stack of currently active timers. SmallVector TimerStack; - bool Enabled; + /// Custom output stream to print timing information into. + /// By default we emit it into the stream controlled by -info-output-file. + raw_ostream *OutStream = nullptr; + + bool Enabled = false; public: - TimePassesHandler(bool Enabled = TimePassesIsEnabled); + /// We construct this object in a disabled form. + /// To start the timing collection and reports explicit enable() call is + /// required. + TimePassesHandler(); /// Destructor handles the print action if it has not been handled before. ~TimePassesHandler() { @@ -84,6 +92,10 @@ void registerCallbacks(PassInstrumentationCallbacks &PIC); + /// Enable timers collection and set the output stream for subsequent + /// reporting. + void enable(raw_ostream &OutStream); + private: /// Dumps information for running/triggered timers, useful for debugging LLVM_DUMP_METHOD void dump() const; Index: include/llvm/Passes/StandardInstrumentations.h =================================================================== --- include/llvm/Passes/StandardInstrumentations.h +++ include/llvm/Passes/StandardInstrumentations.h @@ -63,6 +63,8 @@ StandardInstrumentations() = default; void registerCallbacks(PassInstrumentationCallbacks &PIC); + + TimePassesHandler &getTimePasses() { return TimePasses; } }; } // namespace llvm Index: lib/IR/PassTimingInfo.cpp =================================================================== --- lib/IR/PassTimingInfo.cpp +++ lib/IR/PassTimingInfo.cpp @@ -178,10 +178,20 @@ return *(Pair.first->second.get()); } -TimePassesHandler::TimePassesHandler(bool Enabled) - : TG("pass", "... Pass execution timing report ..."), Enabled(Enabled) {} +TimePassesHandler::TimePassesHandler() + : TG("pass", "... Pass execution timing report ...") {} + +void TimePassesHandler::enable(raw_ostream &Out) { + Enabled = true; + OutStream = &Out; +} -void TimePassesHandler::print() { TG.print(*CreateInfoOutputFile()); } +void TimePassesHandler::print() { + if (!Enabled) + return; + assert(OutStream && "output stream can not be null"); + TG.print(*OutStream); +} LLVM_DUMP_METHOD void TimePassesHandler::dump() const { dbgs() << "Dumping timers for " << getTypeName() Index: test/Other/time-passes.ll =================================================================== --- test/Other/time-passes.ll +++ test/Other/time-passes.ll @@ -4,6 +4,16 @@ ; 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 ; RUN: opt < %s -disable-output -passes='default' -time-passes 2>&1 | FileCheck %s --check-prefix=TIME ; +; The following 4 test runs verify -info-output-file interaction (default goes to stderr, '-' goes to stdout). +; RUN: opt < %s -disable-output -O2 -time-passes -info-output-file='-' 2>/dev/null | FileCheck %s --check-prefix=TIME +; RUN: opt < %s -disable-output -passes='default' -time-passes -info-output-file='-' 2>/dev/null | FileCheck %s --check-prefix=TIME +; +; RUN: rm -f %t; opt < %s -disable-output -O2 -time-passes -info-output-file=%t +; RUN: cat %t | FileCheck %s --check-prefix=TIME +; +; RUN: rm -f %t; opt < %s -disable-output -passes='default' -time-passes -info-output-file=%t +; RUN: cat %t | FileCheck %s --check-prefix=TIME +; ; TIME: Pass execution timing report ; TIME: Total Execution Time: ; TIME: Name Index: tools/opt/NewPMDriver.cpp =================================================================== --- tools/opt/NewPMDriver.cpp +++ tools/opt/NewPMDriver.cpp @@ -15,6 +15,7 @@ #include "NewPMDriver.h" #include "Debugify.h" #include "PassPrinters.h" +#include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringRef.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/CGSCCPassManager.h" @@ -257,8 +258,14 @@ P->CSAction = PGOOptions::CSIRUse; } } + + // Setting up standard instrumentations. + const bool StreamNeeded = TimePassesIsEnabled; + std::unique_ptr InfoStream = (StreamNeeded ? CreateInfoOutputFile() : nullptr); PassInstrumentationCallbacks PIC; StandardInstrumentations SI; + if (TimePassesIsEnabled) + SI.getTimePasses().enable(*InfoStream); SI.registerCallbacks(PIC); PassBuilder PB(TM, P, &PIC);