[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
diff --git a/llvm/unittests/IR/TimePassesTest.cpp b/llvm/unittests/IR/TimePassesTest.cpp
index 7014436..a766522 100644
--- a/llvm/unittests/IR/TimePassesTest.cpp
+++ b/llvm/unittests/IR/TimePassesTest.cpp
@@ -8,6 +8,7 @@
 
 #include <gtest/gtest.h>
 #include <llvm/ADT/SmallString.h>
+#include "llvm/IR/LegacyPassManager.h"
 #include <llvm/IR/LLVMContext.h>
 #include <llvm/IR/Module.h>
 #include <llvm/IR/PassInstrumentation.h>
@@ -17,7 +18,97 @@
 
 using namespace llvm;
 
+//===----------------------------------------------------------------------===//
+// Define dummy passes for legacy pass manager run.
+
+namespace llvm {
+
+void initializePass1Pass(PassRegistry &);
+void initializePass2Pass(PassRegistry &);
+
 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 MyPass2 : public PassInfoMixin<MyPass2> {};
@@ -40,7 +131,7 @@
   TimePasses->setOutStream(ReportStream);
   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(Pass2, M);
   PI.runAfterPass(Pass2, M);
@@ -61,7 +152,7 @@
   // 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.
+  // Now trigger just a single pass to populate timers again.
   PI.runBeforePass(Pass2, M);
   PI.runAfterPass(Pass2, M);