Index: include/llvm/IR/PassTimingInfo.h =================================================================== --- include/llvm/IR/PassTimingInfo.h +++ include/llvm/IR/PassTimingInfo.h @@ -21,6 +21,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Timer.h" #include "llvm/Support/TypeName.h" +#include "llvm/Support/raw_ostream.h" #include namespace llvm { @@ -62,6 +63,10 @@ /// Stack of currently active timers. SmallVector TimerStack; + /// Custom output stream to print timing information into. + /// By default we emit it into the stream controlled by -info-output-file. + raw_ostream* OutStream; + bool Enabled; public: @@ -84,6 +89,9 @@ void registerCallbacks(PassInstrumentationCallbacks &PIC); + /// Set the non-default output stream. + void setOutStream(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 @@ -179,9 +179,19 @@ } TimePassesHandler::TimePassesHandler(bool Enabled) - : TG("pass", "... Pass execution timing report ..."), Enabled(Enabled) {} + : TG("pass", "... Pass execution timing report ..."), OutStream(), + Enabled(Enabled) {} -void TimePassesHandler::print() { TG.print(*CreateInfoOutputFile()); } +void TimePassesHandler::setOutStream(raw_ostream* Out) { + assert(Out && "output stream can not be null"); + OutStream = Out; +} + +void TimePassesHandler::print() { + if (!Enabled || OutStream) + return; + 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().setOutStream(InfoStream.get()); SI.registerCallbacks(PIC); PassBuilder PB(TM, P, &PIC);