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
16using namespace mlir;
17
18namespace {
19struct 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(Val: 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(Val: 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(Val: 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(Val: 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(Val: 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(Val: false)};
61
62 /// Add an IR printing instrumentation if enabled by any 'print-ir' flags.
63 void addPrinterInstrumentation(PassManager &pm);
64
65 //===--------------------------------------------------------------------===//
66 // Pass Statistics
67 //===--------------------------------------------------------------------===//
68 llvm::cl::opt<bool> passStatistics{
69 "mlir-pass-statistics",
70 llvm::cl::desc("Display the statistics of each pass")};
71 llvm::cl::opt<PassDisplayMode> passStatisticsDisplayMode{
72 "mlir-pass-statistics-display",
73 llvm::cl::desc("Display method for pass statistics"),
74 llvm::cl::init(Val: PassDisplayMode::Pipeline),
75 llvm::cl::values(
76 clEnumValN(
77 PassDisplayMode::List, "list",
78 "display the results in a merged list sorted by pass name"),
79 clEnumValN(PassDisplayMode::Pipeline, "pipeline",
80 "display the results with a nested pipeline view"))};
81};
82} // namespace
83
84static llvm::ManagedStatic<PassManagerOptions> options;
85
86/// Add an IR printing instrumentation if enabled by any 'print-ir' flags.
87void PassManagerOptions::addPrinterInstrumentation(PassManager &pm) {
88 std::function<bool(Pass *, Operation *)> shouldPrintBeforePass;
89 std::function<bool(Pass *, Operation *)> shouldPrintAfterPass;
90
91 // Handle print-before.
92 if (printBeforeAll) {
93 // If we are printing before all, then just return true for the filter.
94 shouldPrintBeforePass = [](Pass *, Operation *) { return true; };
95 } else if (printBefore.hasAnyOccurrences()) {
96 // Otherwise if there are specific passes to print before, then check to see
97 // if the pass info for the current pass is included in the list.
98 shouldPrintBeforePass = [&](Pass *pass, Operation *) {
99 auto *passInfo = pass->lookupPassInfo();
100 return passInfo && printBefore.contains(entry: passInfo);
101 };
102 }
103
104 // Handle print-after.
105 if (printAfterAll || printAfterFailure) {
106 // If we are printing after all or failure, then just return true for the
107 // filter.
108 shouldPrintAfterPass = [](Pass *, Operation *) { return true; };
109 } else if (printAfter.hasAnyOccurrences()) {
110 // Otherwise if there are specific passes to print after, then check to see
111 // if the pass info for the current pass is included in the list.
112 shouldPrintAfterPass = [&](Pass *pass, Operation *) {
113 auto *passInfo = pass->lookupPassInfo();
114 return passInfo && printAfter.contains(entry: passInfo);
115 };
116 }
117
118 // If there are no valid printing filters, then just return.
119 if (!shouldPrintBeforePass && !shouldPrintAfterPass)
120 return;
121
122 // Otherwise, add the IR printing instrumentation.
123 pm.enableIRPrinting(shouldPrintBeforePass, shouldPrintAfterPass,
124 printModuleScope, printAfterOnlyOnChange: printAfterChange, printAfterOnlyOnFailure: printAfterFailure,
125 out&: llvm::errs());
126}
127
128void mlir::registerPassManagerCLOptions() {
129 // Make sure that the options struct has been constructed.
130 *options;
131}
132
133LogicalResult mlir::applyPassManagerCLOptions(PassManager &pm) {
134 if (!options.isConstructed())
135 return failure();
136
137 // Generate a reproducer on crash/failure.
138 if (options->reproducerFile.getNumOccurrences())
139 pm.enableCrashReproducerGeneration(outputFile: options->reproducerFile,
140 genLocalReproducer: options->localReproducer);
141
142 // Enable statistics dumping.
143 if (options->passStatistics)
144 pm.enableStatistics(displayMode: options->passStatisticsDisplayMode);
145
146 if (options->printModuleScope && pm.getContext()->isMultithreadingEnabled()) {
147 emitError(UnknownLoc::get(pm.getContext()))
148 << "IR print for module scope can't be setup on a pass-manager "
149 "without disabling multi-threading first.\n";
150 return failure();
151 }
152
153 // Add the IR printing instrumentation.
154 options->addPrinterInstrumentation(pm);
155 return success();
156}
157
158void mlir::applyDefaultTimingPassManagerCLOptions(PassManager &pm) {
159 // Create a temporary timing manager for the PM to own, apply its CL options,
160 // and pass it to the PM.
161 auto tm = std::make_unique<DefaultTimingManager>();
162 applyDefaultTimingManagerCLOptions(tm&: *tm);
163 pm.enableTiming(tm: std::move(tm));
164}
165

source code of mlir/lib/Pass/PassManagerOptions.cpp