xref: /llvm-project/mlir/lib/Pass/PassManagerOptions.cpp (revision 7f1968625a607fb49a2b9a67f3c8fb2892cf4839)
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 "mlir/Support/Timing.h"
13 #include "llvm/Support/CommandLine.h"
14 #include "llvm/Support/ManagedStatic.h"
15 
16 using namespace mlir;
17 
18 namespace {
19 struct PassManagerOptions {
20   //===--------------------------------------------------------------------===//
21   // Crash Reproducer Generator
22   //===--------------------------------------------------------------------===//
23   llvm::cl::opt<std::string> reproducerFile{
24       "mlir-pass-pipeline-crash-reproducer",
25       llvm::cl::desc("Generate a .mlir reproducer file at the given output path"
26                      " if the pass manager crashes or fails")};
27   llvm::cl::opt<bool> localReproducer{
28       "mlir-pass-pipeline-local-reproducer",
29       llvm::cl::desc("When generating a crash reproducer, attempt to generated "
30                      "a reproducer with the smallest pipeline."),
31       llvm::cl::init(false)};
32 
33   //===--------------------------------------------------------------------===//
34   // IR Printing
35   //===--------------------------------------------------------------------===//
36   PassNameCLParser printBefore{"mlir-print-ir-before",
37                                "Print IR before specified passes"};
38   PassNameCLParser printAfter{"mlir-print-ir-after",
39                               "Print IR after specified passes"};
40   llvm::cl::opt<bool> printBeforeAll{
41       "mlir-print-ir-before-all", llvm::cl::desc("Print IR before each pass"),
42       llvm::cl::init(false)};
43   llvm::cl::opt<bool> printAfterAll{"mlir-print-ir-after-all",
44                                     llvm::cl::desc("Print IR after each pass"),
45                                     llvm::cl::init(false)};
46   llvm::cl::opt<bool> printAfterChange{
47       "mlir-print-ir-after-change",
48       llvm::cl::desc(
49           "When printing the IR after a pass, only print if the IR changed"),
50       llvm::cl::init(false)};
51   llvm::cl::opt<bool> printAfterFailure{
52       "mlir-print-ir-after-failure",
53       llvm::cl::desc(
54           "When printing the IR after a pass, only print if the pass failed"),
55       llvm::cl::init(false)};
56   llvm::cl::opt<bool> printModuleScope{
57       "mlir-print-ir-module-scope",
58       llvm::cl::desc("When printing IR for print-ir-[before|after]{-all} "
59                      "always print the top-level operation"),
60       llvm::cl::init(false)};
61   llvm::cl::opt<std::string> printTreeDir{
62       "mlir-print-ir-tree-dir",
63       llvm::cl::desc("When printing the IR before/after a pass, print file "
64                      "tree rooted at this directory. Use in conjunction with "
65                      "mlir-print-ir-* flags")};
66 
67   /// Add an IR printing instrumentation if enabled by any 'print-ir' flags.
68   void addPrinterInstrumentation(PassManager &pm);
69 
70   //===--------------------------------------------------------------------===//
71   // Pass Statistics
72   //===--------------------------------------------------------------------===//
73   llvm::cl::opt<bool> passStatistics{
74       "mlir-pass-statistics",
75       llvm::cl::desc("Display the statistics of each pass")};
76   llvm::cl::opt<PassDisplayMode> passStatisticsDisplayMode{
77       "mlir-pass-statistics-display",
78       llvm::cl::desc("Display method for pass statistics"),
79       llvm::cl::init(PassDisplayMode::Pipeline),
80       llvm::cl::values(
81           clEnumValN(
82               PassDisplayMode::List, "list",
83               "display the results in a merged list sorted by pass name"),
84           clEnumValN(PassDisplayMode::Pipeline, "pipeline",
85                      "display the results with a nested pipeline view"))};
86 };
87 } // namespace
88 
89 static llvm::ManagedStatic<PassManagerOptions> options;
90 
91 /// Add an IR printing instrumentation if enabled by any 'print-ir' flags.
92 void PassManagerOptions::addPrinterInstrumentation(PassManager &pm) {
93   std::function<bool(Pass *, Operation *)> shouldPrintBeforePass;
94   std::function<bool(Pass *, Operation *)> shouldPrintAfterPass;
95 
96   // Handle print-before.
97   if (printBeforeAll) {
98     // If we are printing before all, then just return true for the filter.
99     shouldPrintBeforePass = [](Pass *, Operation *) { return true; };
100   } else if (printBefore.hasAnyOccurrences()) {
101     // Otherwise if there are specific passes to print before, then check to see
102     // if the pass info for the current pass is included in the list.
103     shouldPrintBeforePass = [&](Pass *pass, Operation *) {
104       auto *passInfo = pass->lookupPassInfo();
105       return passInfo && printBefore.contains(passInfo);
106     };
107   }
108 
109   // Handle print-after.
110   if (printAfterAll || printAfterFailure) {
111     // If we are printing after all or failure, then just return true for the
112     // filter.
113     shouldPrintAfterPass = [](Pass *, Operation *) { return true; };
114   } else if (printAfter.hasAnyOccurrences()) {
115     // Otherwise if there are specific passes to print after, then check to see
116     // if the pass info for the current pass is included in the list.
117     shouldPrintAfterPass = [&](Pass *pass, Operation *) {
118       auto *passInfo = pass->lookupPassInfo();
119       return passInfo && printAfter.contains(passInfo);
120     };
121   }
122 
123   // If there are no valid printing filters, then just return.
124   if (!shouldPrintBeforePass && !shouldPrintAfterPass)
125     return;
126 
127   // Otherwise, add the IR printing instrumentation.
128   if (!printTreeDir.empty()) {
129     pm.enableIRPrintingToFileTree(shouldPrintBeforePass, shouldPrintAfterPass,
130                                   printModuleScope, printAfterChange,
131                                   printAfterFailure, printTreeDir);
132     return;
133   }
134 
135   pm.enableIRPrinting(shouldPrintBeforePass, shouldPrintAfterPass,
136                       printModuleScope, printAfterChange, printAfterFailure,
137                       llvm::errs());
138 }
139 
140 void mlir::registerPassManagerCLOptions() {
141   // Make sure that the options struct has been constructed.
142   *options;
143 }
144 
145 LogicalResult mlir::applyPassManagerCLOptions(PassManager &pm) {
146   if (!options.isConstructed())
147     return failure();
148 
149   // Generate a reproducer on crash/failure.
150   if (options->reproducerFile.getNumOccurrences())
151     pm.enableCrashReproducerGeneration(options->reproducerFile,
152                                        options->localReproducer);
153 
154   // Enable statistics dumping.
155   if (options->passStatistics)
156     pm.enableStatistics(options->passStatisticsDisplayMode);
157 
158   if (options->printModuleScope && pm.getContext()->isMultithreadingEnabled()) {
159     emitError(UnknownLoc::get(pm.getContext()))
160         << "IR print for module scope can't be setup on a pass-manager "
161            "without disabling multi-threading first.\n";
162     return failure();
163   }
164 
165   // Add the IR printing instrumentation.
166   options->addPrinterInstrumentation(pm);
167   return success();
168 }
169 
170 void mlir::applyDefaultTimingPassManagerCLOptions(PassManager &pm) {
171   // Create a temporary timing manager for the PM to own, apply its CL options,
172   // and pass it to the PM.
173   auto tm = std::make_unique<DefaultTimingManager>();
174   applyDefaultTimingManagerCLOptions(*tm);
175   pm.enableTiming(std::move(tm));
176 }
177