• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- PassManagerOptions.cpp - PassManager Command Line Options ----------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "mlir/Pass/Pass.h"
10 #include "mlir/Pass/PassManager.h"
11 #include "mlir/Pass/PassRegistry.h"
12 #include "llvm/Support/CommandLine.h"
13 #include "llvm/Support/ManagedStatic.h"
14 
15 using namespace mlir;
16 
17 namespace {
18 struct PassManagerOptions {
19   //===--------------------------------------------------------------------===//
20   // Crash Reproducer Generator
21   //===--------------------------------------------------------------------===//
22   llvm::cl::opt<std::string> reproducerFile{
23       "pass-pipeline-crash-reproducer",
24       llvm::cl::desc("Generate a .mlir reproducer file at the given output path"
25                      " if the pass manager crashes or fails")};
26   llvm::cl::opt<bool> localReproducer{
27       "pass-pipeline-local-reproducer",
28       llvm::cl::desc("When generating a crash reproducer, attempt to generated "
29                      "a reproducer with the smallest pipeline."),
30       llvm::cl::init(false)};
31 
32   //===--------------------------------------------------------------------===//
33   // IR Printing
34   //===--------------------------------------------------------------------===//
35   PassPipelineCLParser printBefore{"print-ir-before",
36                                    "Print IR before specified passes"};
37   PassPipelineCLParser printAfter{"print-ir-after",
38                                   "Print IR after specified passes"};
39   llvm::cl::opt<bool> printBeforeAll{
40       "print-ir-before-all", llvm::cl::desc("Print IR before each pass"),
41       llvm::cl::init(false)};
42   llvm::cl::opt<bool> printAfterAll{"print-ir-after-all",
43                                     llvm::cl::desc("Print IR after each pass"),
44                                     llvm::cl::init(false)};
45   llvm::cl::opt<bool> printAfterChange{
46       "print-ir-after-change",
47       llvm::cl::desc(
48           "When printing the IR after a pass, only print if the IR changed"),
49       llvm::cl::init(false)};
50   llvm::cl::opt<bool> printModuleScope{
51       "print-ir-module-scope",
52       llvm::cl::desc("When printing IR for print-ir-[before|after]{-all} "
53                      "always print the top-level operation"),
54       llvm::cl::init(false)};
55 
56   /// Add an IR printing instrumentation if enabled by any 'print-ir' flags.
57   void addPrinterInstrumentation(PassManager &pm);
58 
59   //===--------------------------------------------------------------------===//
60   // Pass Timing
61   //===--------------------------------------------------------------------===//
62   llvm::cl::opt<bool> passTiming{
63       "pass-timing",
64       llvm::cl::desc("Display the execution times of each pass")};
65   llvm::cl::opt<PassDisplayMode> passTimingDisplayMode{
66       "pass-timing-display",
67       llvm::cl::desc("Display method for pass timing data"),
68       llvm::cl::init(PassDisplayMode::Pipeline),
69       llvm::cl::values(
70           clEnumValN(PassDisplayMode::List, "list",
71                      "display the results in a list sorted by total time"),
72           clEnumValN(PassDisplayMode::Pipeline, "pipeline",
73                      "display the results with a nested pipeline view"))};
74 
75   //===--------------------------------------------------------------------===//
76   // Pass Statistics
77   //===--------------------------------------------------------------------===//
78   llvm::cl::opt<bool> passStatistics{
79       "pass-statistics", llvm::cl::desc("Display the statistics of each pass")};
80   llvm::cl::opt<PassDisplayMode> passStatisticsDisplayMode{
81       "pass-statistics-display",
82       llvm::cl::desc("Display method for pass statistics"),
83       llvm::cl::init(PassDisplayMode::Pipeline),
84       llvm::cl::values(
85           clEnumValN(
86               PassDisplayMode::List, "list",
87               "display the results in a merged list sorted by pass name"),
88           clEnumValN(PassDisplayMode::Pipeline, "pipeline",
89                      "display the results with a nested pipeline view"))};
90 
91   /// Add a pass timing instrumentation if enabled by 'pass-timing' flags.
92   void addTimingInstrumentation(PassManager &pm);
93 };
94 } // end anonymous namespace
95 
96 static llvm::ManagedStatic<PassManagerOptions> options;
97 
98 /// Add an IR printing instrumentation if enabled by any 'print-ir' flags.
addPrinterInstrumentation(PassManager & pm)99 void PassManagerOptions::addPrinterInstrumentation(PassManager &pm) {
100   std::function<bool(Pass *, Operation *)> shouldPrintBeforePass;
101   std::function<bool(Pass *, Operation *)> shouldPrintAfterPass;
102 
103   // Handle print-before.
104   if (printBeforeAll) {
105     // If we are printing before all, then just return true for the filter.
106     shouldPrintBeforePass = [](Pass *, Operation *) { return true; };
107   } else if (printBefore.hasAnyOccurrences()) {
108     // Otherwise if there are specific passes to print before, then check to see
109     // if the pass info for the current pass is included in the list.
110     shouldPrintBeforePass = [&](Pass *pass, Operation *) {
111       auto *passInfo = pass->lookupPassInfo();
112       return passInfo && printBefore.contains(passInfo);
113     };
114   }
115 
116   // Handle print-after.
117   if (printAfterAll) {
118     // If we are printing after all, then just return true for the filter.
119     shouldPrintAfterPass = [](Pass *, Operation *) { return true; };
120   } else if (printAfter.hasAnyOccurrences()) {
121     // Otherwise if there are specific passes to print after, then check to see
122     // if the pass info for the current pass is included in the list.
123     shouldPrintAfterPass = [&](Pass *pass, Operation *) {
124       auto *passInfo = pass->lookupPassInfo();
125       return passInfo && printAfter.contains(passInfo);
126     };
127   }
128 
129   // If there are no valid printing filters, then just return.
130   if (!shouldPrintBeforePass && !shouldPrintAfterPass)
131     return;
132 
133   // Otherwise, add the IR printing instrumentation.
134   pm.enableIRPrinting(shouldPrintBeforePass, shouldPrintAfterPass,
135                       printModuleScope, printAfterChange, llvm::errs());
136 }
137 
138 /// Add a pass timing instrumentation if enabled by 'pass-timing' flags.
addTimingInstrumentation(PassManager & pm)139 void PassManagerOptions::addTimingInstrumentation(PassManager &pm) {
140   if (passTiming)
141     pm.enableTiming(
142         std::make_unique<PassManager::PassTimingConfig>(passTimingDisplayMode));
143 }
144 
registerPassManagerCLOptions()145 void mlir::registerPassManagerCLOptions() {
146   // Make sure that the options struct has been constructed.
147   *options;
148 }
149 
applyPassManagerCLOptions(PassManager & pm)150 void mlir::applyPassManagerCLOptions(PassManager &pm) {
151   if (!options.isConstructed())
152     return;
153 
154   // Generate a reproducer on crash/failure.
155   if (options->reproducerFile.getNumOccurrences())
156     pm.enableCrashReproducerGeneration(options->reproducerFile,
157                                        options->localReproducer);
158 
159   // Enable statistics dumping.
160   if (options->passStatistics)
161     pm.enableStatistics(options->passStatisticsDisplayMode);
162 
163   // Add the IR printing instrumentation.
164   options->addPrinterInstrumentation(pm);
165 
166   // Note: The pass timing instrumentation should be added last to avoid any
167   // potential "ghost" timing from other instrumentations being unintentionally
168   // included in the timing results.
169   options->addTimingInstrumentation(pm);
170 }
171