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