Refactor pass timing so that it is toggled on the passmanager via 'enableTiming'. This also makes the pipeline view the default display mode.

PiperOrigin-RevId: 238079916
diff --git a/g3doc/WritingAPass.md b/g3doc/WritingAPass.md
index 510d4a9..bdffdb5 100644
--- a/g3doc/WritingAPass.md
+++ b/g3doc/WritingAPass.md
@@ -402,10 +402,11 @@
 The PassTiming instrumentation provides timing information about the execution
 of passes and computation of analyses. This provides a quick glimpse into what
 passes are taking the most time to execute, as well as how much of an effect
-your pass has on the total execution time of the pipeline. This instrumentation
-is made available in mlir-opt via the `-pass-timing` and `-pass-timing-display`
-flags. `-pass-timing-display` allows for toggling between the different display
-modes for the timing results. The available display modes are described below:
+your pass has on the total execution time of the pipeline. Users can enable this
+instrumentation directly on the PassManager via `enableTiming`. This
+instrumentation is also made available in mlir-opt via the `-pass-timing` flag.
+The PassTiming instrumentation provides several different display modes for the
+timing results, each of which is described below:
 
 ##### List Display Mode
 
@@ -439,11 +440,10 @@
 the internal pass pipeline that is being executed in the pass manager. This view
 is useful for understanding specifically which parts of the pipeline are taking
 the most time, and can also be used to identify when analyses are being
-invalidated and recomputed. This display mode is available in mlir-opt via
-`-pass-timing-display=pipeline`.
+invalidated and recomputed. This is the default display mode.
 
 ```shell
-$ mlir-opt foo.mlir -cse -canonicalize -convert-to-llvmir -pass-timing -pass-timing-display=pipeline
+$ mlir-opt foo.mlir -cse -canonicalize -convert-to-llvmir -pass-timing
 
 ===-------------------------------------------------------------------------===
                       ... Pass execution timing report ...
diff --git a/include/mlir/Pass/PassManager.h b/include/mlir/Pass/PassManager.h
index 9f30061..8802002 100644
--- a/include/mlir/Pass/PassManager.h
+++ b/include/mlir/Pass/PassManager.h
@@ -34,6 +34,19 @@
 class ModulePassExecutor;
 } // end namespace detail
 
+/// An enum describing the different display modes for the pass timing
+/// information within the pass manager.
+enum class PassTimingDisplayMode {
+  // In this mode the results are displayed in a list sorted by total time,
+  // with each pass/analysis instance aggregated into one unique result.
+  List,
+
+  // In this mode the results are displayed in a nested pipeline view that
+  // mirrors the internal pass pipeline that is being executed in the pass
+  // manager.
+  Pipeline,
+};
+
 /// The main pass manager and pipeline builder.
 class PassManager {
 public:
@@ -41,6 +54,14 @@
   PassManager(bool verifyPasses = true);
   ~PassManager();
 
+  /// Run the passes within this manager on the provided module.
+  LLVM_NODISCARD
+  LogicalResult run(Module *module);
+
+  //===--------------------------------------------------------------------===//
+  // Pipeline Building
+  //===--------------------------------------------------------------------===//
+
   /// Add an opaque pass pointer to the current manager. This takes ownership
   /// over the provided pass pointer.
   void addPass(Pass *pass);
@@ -54,14 +75,22 @@
   /// executor if necessary.
   void addPass(FunctionPassBase *pass);
 
-  /// Run the passes within this manager on the provided module.
-  LLVM_NODISCARD
-  LogicalResult run(Module *module);
+  //===--------------------------------------------------------------------===//
+  // Instrumentations
+  //===--------------------------------------------------------------------===//
 
   /// Add the provided instrumentation to the pass manager. This takes ownership
   /// over the given pointer.
   void addInstrumentation(PassInstrumentation *pi);
 
+  /// Add an instrumentation to time the execution of passes and the computation
+  /// of analyses.
+  /// Note: Timing should be enabled after all other instrumentations to avoid
+  /// any potential "ghost" timing from other instrumentations being
+  /// unintentionally included in the timing results.
+  void enableTiming(
+      PassTimingDisplayMode displayMode = PassTimingDisplayMode::Pipeline);
+
 private:
   /// A stack of nested pass executors on sub-module IR units, e.g. function.
   llvm::SmallVector<detail::PassExecutor *, 1> nestedExecutorStack;
@@ -70,7 +99,10 @@
   std::unique_ptr<detail::ModulePassExecutor> mpe;
 
   /// Flag that specifies if the IR should be verified after each pass has run.
-  bool verifyPasses;
+  bool verifyPasses : 1;
+
+  /// Flag that specifies if pass timing is enabled.
+  bool passTiming : 1;
 
   /// A manager for pass instrumentations.
   std::unique_ptr<PassInstrumentor> instrumentor;
diff --git a/include/mlir/Pass/PassTiming.h b/include/mlir/Pass/PassTiming.h
deleted file mode 100644
index 6a5dbc2..0000000
--- a/include/mlir/Pass/PassTiming.h
+++ /dev/null
@@ -1,109 +0,0 @@
-//===- PassTiming.h ---------------------------------------------*- C++ -*-===//
-//
-// Copyright 2019 The MLIR Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-// =============================================================================
-//
-// Pass and analysis execution timing instrumentation.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef MLIR_PASS_PASSTIMING_H_
-#define MLIR_PASS_PASSTIMING_H_
-
-#include "mlir/Pass/PassInstrumentation.h"
-#include "llvm/ADT/MapVector.h"
-
-namespace llvm {
-class Timer;
-} // end namespace llvm
-
-namespace mlir {
-class Module;
-class Pass;
-
-class PassTiming : public PassInstrumentation {
-public:
-  enum DisplayMode {
-    // In this mode the results are displayed in a list sorted by total time,
-    // with each pass/analysis instance aggregated into one unique result.
-    List,
-
-    // In this mode the results are displayed in a nested pipeline view that
-    // mirrors the internal pass pipeline that is being executed in the pass
-    // manager.
-    Pipeline,
-  };
-
-  PassTiming(DisplayMode displayMode);
-  ~PassTiming();
-
-  /// Print and clear the timing results.
-  void print();
-
-private:
-  /// Setup the instrumentation hooks.
-  void runBeforePass(Pass *pass, const llvm::Any &) override {
-    startPassTimer(pass);
-  }
-  void runAfterPass(Pass *pass, const llvm::Any &) override {
-    stopPassTimer(pass);
-  }
-  void runAfterPassFailed(Pass *pass, const llvm::Any &) override {
-    stopPassTimer(pass);
-  }
-  void runBeforeAnalysis(llvm::StringRef name, AnalysisID *id,
-                         const llvm::Any &) override {
-    startAnalysisTimer(name, id);
-  }
-  void runAfterAnalysis(llvm::StringRef name, AnalysisID *id,
-                        const llvm::Any &) override {
-    stopAnalysisTimer(name, id);
-  }
-
-  /// Start a new timer for the given pass.
-  void startPassTimer(Pass *pass);
-
-  /// Stop a timer for the given pass.
-  void stopPassTimer(Pass *pass);
-
-  /// Start a new timer for the given analysis.
-  void startAnalysisTimer(llvm::StringRef name, AnalysisID *id);
-
-  /// Stop a timer for the given analysis.
-  void stopAnalysisTimer(llvm::StringRef name, AnalysisID *id);
-
-  /// Print the timing result in list mode.
-  void printResultsAsList(llvm::raw_ostream &os);
-
-  /// Print the timing result in pipeline mode.
-  void printResultsAsPipeline(llvm::raw_ostream &os);
-
-  /// Mapping between pass and a respective timer.
-  llvm::MapVector<Pass *, std::unique_ptr<llvm::Timer>> passTimers;
-
-  /// Mapping between [analysis id, pass] and a respective timer.
-  llvm::DenseMap<std::pair<AnalysisID *, Pass *>, std::unique_ptr<llvm::Timer>>
-      analysisTimers;
-
-  /// A pointer to the currently active pass, or null.
-  Pass *activePass = nullptr;
-
-  /// The display mode to use when printing the timing results.
-  DisplayMode displayMode;
-};
-
-} // end namespace mlir
-
-#endif // MLIR_PASS_PASSTIMING_H_
diff --git a/lib/Pass/Pass.cpp b/lib/Pass/Pass.cpp
index 581225b..4d75c452 100644
--- a/lib/Pass/Pass.cpp
+++ b/lib/Pass/Pass.cpp
@@ -169,10 +169,17 @@
 } // end anonymous namespace
 
 PassManager::PassManager(bool verifyPasses)
-    : mpe(new ModulePassExecutor()), verifyPasses(verifyPasses) {}
+    : mpe(new ModulePassExecutor()), verifyPasses(verifyPasses),
+      passTiming(false) {}
 
 PassManager::~PassManager() {}
 
+/// Run the passes within this manager on the provided module.
+LogicalResult PassManager::run(Module *module) {
+  ModuleAnalysisManager mam(module, instrumentor.get());
+  return mpe->run(module, mam);
+}
+
 /// Add an opaque pass pointer to the current manager. This takes ownership
 /// over the provided pass pointer.
 void PassManager::addPass(Pass *pass) {
@@ -220,12 +227,6 @@
     fpe->addPass(new FunctionVerifier());
 }
 
-/// Run the passes within this manager on the provided module.
-LogicalResult PassManager::run(Module *module) {
-  ModuleAnalysisManager mam(module, instrumentor.get());
-  return mpe->run(module, mam);
-}
-
 /// Add the provided instrumentation to the pass manager. This takes ownership
 /// over the given pointer.
 void PassManager::addInstrumentation(PassInstrumentation *pi) {
diff --git a/lib/Pass/PassTiming.cpp b/lib/Pass/PassTiming.cpp
index c164255..18dacd7 100644
--- a/lib/Pass/PassTiming.cpp
+++ b/lib/Pass/PassTiming.cpp
@@ -15,8 +15,9 @@
 // limitations under the License.
 // =============================================================================
 
-#include "mlir/Pass/PassTiming.h"
 #include "PassDetail.h"
+#include "mlir/Pass/PassManager.h"
+#include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Support/Format.h"
@@ -36,9 +37,65 @@
   return isa<ModuleToFunctionPassAdaptor>(pass);
 }
 
-PassTiming::PassTiming(DisplayMode displayMode) : displayMode(displayMode) {}
+namespace {
+struct PassTiming : public PassInstrumentation {
+  PassTiming(PassTimingDisplayMode displayMode) : displayMode(displayMode) {}
+  ~PassTiming() { print(); }
 
-PassTiming::~PassTiming() { print(); }
+  /// Setup the instrumentation hooks.
+  void runBeforePass(Pass *pass, const llvm::Any &) override {
+    startPassTimer(pass);
+  }
+  void runAfterPass(Pass *pass, const llvm::Any &) override {
+    stopPassTimer(pass);
+  }
+  void runAfterPassFailed(Pass *pass, const llvm::Any &) override {
+    stopPassTimer(pass);
+  }
+  void runBeforeAnalysis(llvm::StringRef name, AnalysisID *id,
+                         const llvm::Any &) override {
+    startAnalysisTimer(name, id);
+  }
+  void runAfterAnalysis(llvm::StringRef name, AnalysisID *id,
+                        const llvm::Any &) override {
+    stopAnalysisTimer(name, id);
+  }
+
+  /// Print and clear the timing results.
+  void print();
+
+  /// Start a new timer for the given pass.
+  void startPassTimer(Pass *pass);
+
+  /// Stop a timer for the given pass.
+  void stopPassTimer(Pass *pass);
+
+  /// Start a new timer for the given analysis.
+  void startAnalysisTimer(llvm::StringRef name, AnalysisID *id);
+
+  /// Stop a timer for the given analysis.
+  void stopAnalysisTimer(llvm::StringRef name, AnalysisID *id);
+
+  /// Print the timing result in list mode.
+  void printResultsAsList(llvm::raw_ostream &os);
+
+  /// Print the timing result in pipeline mode.
+  void printResultsAsPipeline(llvm::raw_ostream &os);
+
+  /// Mapping between pass and a respective timer.
+  llvm::MapVector<Pass *, std::unique_ptr<llvm::Timer>> passTimers;
+
+  /// Mapping between [analysis id, pass] and a respective timer.
+  llvm::DenseMap<std::pair<AnalysisID *, Pass *>, std::unique_ptr<llvm::Timer>>
+      analysisTimers;
+
+  /// A pointer to the currently active pass, or null.
+  Pass *activePass = nullptr;
+
+  /// The display mode to use when printing the timing results.
+  PassTimingDisplayMode displayMode;
+};
+} // end anonymous namespace
 
 /// Print out the current timing information.
 void PassTiming::print() {
@@ -47,10 +104,10 @@
     return;
 
   switch (displayMode) {
-  case DisplayMode::List:
+  case PassTimingDisplayMode::List:
     printResultsAsList(*llvm::CreateInfoOutputFile());
     break;
-  case DisplayMode::Pipeline:
+  case PassTimingDisplayMode::Pipeline:
     printResultsAsPipeline(*llvm::CreateInfoOutputFile());
     break;
   }
@@ -232,3 +289,17 @@
   printTimer("Total\n", pipelineTotal);
   os.flush();
 }
+
+//===----------------------------------------------------------------------===//
+// PassManager
+//===----------------------------------------------------------------------===//
+
+/// Add an instrumentation to time the execution of passes and the computation
+/// of analyses.
+void PassManager::enableTiming(PassTimingDisplayMode displayMode) {
+  // Check if pass timing is already enabled.
+  if (passTiming)
+    return;
+  addInstrumentation(new PassTiming(displayMode));
+  passTiming = true;
+}
diff --git a/tools/mlir-opt/mlir-opt.cpp b/tools/mlir-opt/mlir-opt.cpp
index b85db6a..c9deafb 100644
--- a/tools/mlir-opt/mlir-opt.cpp
+++ b/tools/mlir-opt/mlir-opt.cpp
@@ -30,7 +30,6 @@
 #include "mlir/Parser.h"
 #include "mlir/Pass/Pass.h"
 #include "mlir/Pass/PassManager.h"
-#include "mlir/Pass/PassTiming.h"
 #include "mlir/Support/FileUtilities.h"
 #include "mlir/TensorFlow/ControlFlowOps.h"
 #include "mlir/TensorFlow/Passes.h"
@@ -78,12 +77,12 @@
     passTiming("pass-timing",
                cl::desc("Display the execution times of each pass"));
 
-static cl::opt<PassTiming::DisplayMode> passTimingDisplayMode(
+static cl::opt<PassTimingDisplayMode> passTimingDisplayMode(
     "pass-timing-display", cl::desc("Display method for pass timing data"),
-    cl::init(PassTiming::DisplayMode::List),
-    cl::values(clEnumValN(PassTiming::DisplayMode::List, "list",
+    cl::init(PassTimingDisplayMode::Pipeline),
+    cl::values(clEnumValN(PassTimingDisplayMode::List, "list",
                           "display the results in a list sorted by total time"),
-               clEnumValN(PassTiming::DisplayMode::Pipeline, "pipeline",
+               clEnumValN(PassTimingDisplayMode::Pipeline, "pipeline",
                           "display the results with a nested pipeline view")));
 
 static std::vector<const mlir::PassRegistryEntry *> *passList;
@@ -153,7 +152,7 @@
   // potential "ghost" timing from other instrumentations being unintentionally
   // included in the timing results.
   if (passTiming)
-    pm.addInstrumentation(new PassTiming(passTimingDisplayMode));
+    pm.enableTiming(passTimingDisplayMode);
 
   if (failed(pm.run(module.get())))
     return OptFailure;