[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
GitOrigin-RevId: 43083111a257f39282df92f3879dbaec54191337
diff --git a/include/llvm/IR/LegacyPassManagers.h b/include/llvm/IR/LegacyPassManagers.h
index f6752f2..c0b98dc 100644
--- a/include/llvm/IR/LegacyPassManagers.h
+++ b/include/llvm/IR/LegacyPassManagers.h
@@ -508,7 +508,6 @@
   }
 };
 
-Timer *getPassTimer(Pass *);
 }
 
 #endif
diff --git a/include/llvm/IR/PassTimingInfo.h b/include/llvm/IR/PassTimingInfo.h
new file mode 100644
index 0000000..5f3bdcd
--- /dev/null
+++ b/include/llvm/IR/PassTimingInfo.h
@@ -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
diff --git a/lib/Analysis/CallGraphSCCPass.cpp b/lib/Analysis/CallGraphSCCPass.cpp
index 4c33c42..df65255 100644
--- a/lib/Analysis/CallGraphSCCPass.cpp
+++ b/lib/Analysis/CallGraphSCCPass.cpp
@@ -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"
diff --git a/lib/Analysis/LoopPass.cpp b/lib/Analysis/LoopPass.cpp
index 07a151c..f4f00f0 100644
--- a/lib/Analysis/LoopPass.cpp
+++ b/lib/Analysis/LoopPass.cpp
@@ -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"
diff --git a/lib/Analysis/RegionPass.cpp b/lib/Analysis/RegionPass.cpp
index ed17df2..a101ff1 100644
--- a/lib/Analysis/RegionPass.cpp
+++ b/lib/Analysis/RegionPass.cpp
@@ -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"
diff --git a/lib/IR/CMakeLists.txt b/lib/IR/CMakeLists.txt
index 0a78a0f..a194b84 100644
--- a/lib/IR/CMakeLists.txt
+++ b/lib/IR/CMakeLists.txt
@@ -44,6 +44,7 @@
   Pass.cpp
   PassManager.cpp
   PassRegistry.cpp
+  PassTimingInfo.cpp
   SafepointIRVerifier.cpp
   ProfileSummary.cpp
   Statepoint.cpp
diff --git a/lib/IR/LegacyPassManager.cpp b/lib/IR/LegacyPassManager.cpp
index d11a2b3..dbef00a 100644
--- a/lib/IR/LegacyPassManager.cpp
+++ b/lib/IR/LegacyPassManager.cpp
@@ -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 @@
 } // 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 @@
 // 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 @@
 /// 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();
@@ -1808,41 +1748,6 @@
 }
 
 //===----------------------------------------------------------------------===//
-// 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
 //
 
diff --git a/lib/IR/PassTimingInfo.cpp b/lib/IR/PassTimingInfo.cpp
new file mode 100644
index 0000000..c1efc65
--- /dev/null
+++ b/lib/IR/PassTimingInfo.cpp
@@ -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
diff --git a/test/Other/time-passes.ll b/test/Other/time-passes.ll
new file mode 100644
index 0000000..30325de
--- /dev/null
+++ b/test/Other/time-passes.ll
@@ -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
+}