16810c8bdSRiver Riddle //===- PassManagerOptions.cpp - PassManager Command Line Options ----------===//
26810c8bdSRiver Riddle //
330857107SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
456222a06SMehdi Amini // See https://llvm.org/LICENSE.txt for license information.
556222a06SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66810c8bdSRiver Riddle //
756222a06SMehdi Amini //===----------------------------------------------------------------------===//
86810c8bdSRiver Riddle
96810c8bdSRiver Riddle #include "mlir/Pass/Pass.h"
106810c8bdSRiver Riddle #include "mlir/Pass/PassManager.h"
116810c8bdSRiver Riddle #include "mlir/Pass/PassRegistry.h"
1233f908c4SFabian Schuiki #include "mlir/Support/Timing.h"
136810c8bdSRiver Riddle #include "llvm/Support/CommandLine.h"
146810c8bdSRiver Riddle #include "llvm/Support/ManagedStatic.h"
156810c8bdSRiver Riddle
166810c8bdSRiver Riddle using namespace mlir;
176810c8bdSRiver Riddle
186810c8bdSRiver Riddle namespace {
196810c8bdSRiver Riddle struct PassManagerOptions {
206810c8bdSRiver Riddle //===--------------------------------------------------------------------===//
217a7dcc17SRiver Riddle // Crash Reproducer Generator
227a7dcc17SRiver Riddle //===--------------------------------------------------------------------===//
237a7dcc17SRiver Riddle llvm::cl::opt<std::string> reproducerFile{
24fb16ed25SAndrzej Warzynski "mlir-pass-pipeline-crash-reproducer",
257a7dcc17SRiver Riddle llvm::cl::desc("Generate a .mlir reproducer file at the given output path"
267a7dcc17SRiver Riddle " if the pass manager crashes or fails")};
27983382f1SRiver Riddle llvm::cl::opt<bool> localReproducer{
28fb16ed25SAndrzej Warzynski "mlir-pass-pipeline-local-reproducer",
29983382f1SRiver Riddle llvm::cl::desc("When generating a crash reproducer, attempt to generated "
30983382f1SRiver Riddle "a reproducer with the smallest pipeline."),
31983382f1SRiver Riddle llvm::cl::init(false)};
327a7dcc17SRiver Riddle
337a7dcc17SRiver Riddle //===--------------------------------------------------------------------===//
346810c8bdSRiver Riddle // IR Printing
356810c8bdSRiver Riddle //===--------------------------------------------------------------------===//
36fb16ed25SAndrzej Warzynski PassNameCLParser printBefore{"mlir-print-ir-before",
37b245e951SRiver Riddle "Print IR before specified passes"};
38fb16ed25SAndrzej Warzynski PassNameCLParser printAfter{"mlir-print-ir-after",
39b245e951SRiver Riddle "Print IR after specified passes"};
40b245e951SRiver Riddle llvm::cl::opt<bool> printBeforeAll{
41fb16ed25SAndrzej Warzynski "mlir-print-ir-before-all", llvm::cl::desc("Print IR before each pass"),
42b245e951SRiver Riddle llvm::cl::init(false)};
43fb16ed25SAndrzej Warzynski llvm::cl::opt<bool> printAfterAll{"mlir-print-ir-after-all",
44b245e951SRiver Riddle llvm::cl::desc("Print IR after each pass"),
45b245e951SRiver Riddle llvm::cl::init(false)};
468904e910SRiver Riddle llvm::cl::opt<bool> printAfterChange{
47fb16ed25SAndrzej Warzynski "mlir-print-ir-after-change",
488904e910SRiver Riddle llvm::cl::desc(
498904e910SRiver Riddle "When printing the IR after a pass, only print if the IR changed"),
508904e910SRiver Riddle llvm::cl::init(false)};
5164ce90e1SRiver Riddle llvm::cl::opt<bool> printAfterFailure{
52fb16ed25SAndrzej Warzynski "mlir-print-ir-after-failure",
5364ce90e1SRiver Riddle llvm::cl::desc(
5464ce90e1SRiver Riddle "When printing the IR after a pass, only print if the pass failed"),
5564ce90e1SRiver Riddle llvm::cl::init(false)};
56b245e951SRiver Riddle llvm::cl::opt<bool> printModuleScope{
57fb16ed25SAndrzej Warzynski "mlir-print-ir-module-scope",
58b245e951SRiver Riddle llvm::cl::desc("When printing IR for print-ir-[before|after]{-all} "
5900c6ef86SRiver Riddle "always print the top-level operation"),
60b245e951SRiver Riddle llvm::cl::init(false)};
616810c8bdSRiver Riddle
626810c8bdSRiver Riddle /// Add an IR printing instrumentation if enabled by any 'print-ir' flags.
636810c8bdSRiver Riddle void addPrinterInstrumentation(PassManager &pm);
646810c8bdSRiver Riddle
656810c8bdSRiver Riddle //===--------------------------------------------------------------------===//
6633a64540SRiver Riddle // Pass Statistics
6733a64540SRiver Riddle //===--------------------------------------------------------------------===//
6833a64540SRiver Riddle llvm::cl::opt<bool> passStatistics{
69fb16ed25SAndrzej Warzynski "mlir-pass-statistics",
70fb16ed25SAndrzej Warzynski llvm::cl::desc("Display the statistics of each pass")};
7133a64540SRiver Riddle llvm::cl::opt<PassDisplayMode> passStatisticsDisplayMode{
72fb16ed25SAndrzej Warzynski "mlir-pass-statistics-display",
7333a64540SRiver Riddle llvm::cl::desc("Display method for pass statistics"),
7433a64540SRiver Riddle llvm::cl::init(PassDisplayMode::Pipeline),
7533a64540SRiver Riddle llvm::cl::values(
7633a64540SRiver Riddle clEnumValN(
7733a64540SRiver Riddle PassDisplayMode::List, "list",
7833a64540SRiver Riddle "display the results in a merged list sorted by pass name"),
7933a64540SRiver Riddle clEnumValN(PassDisplayMode::Pipeline, "pipeline",
80b245e951SRiver Riddle "display the results with a nested pipeline view"))};
81b245e951SRiver Riddle };
82be0a7e9fSMehdi Amini } // namespace
83b245e951SRiver Riddle
848938dea4SRiver Riddle static llvm::ManagedStatic<PassManagerOptions> options;
856810c8bdSRiver Riddle
866810c8bdSRiver Riddle /// Add an IR printing instrumentation if enabled by any 'print-ir' flags.
addPrinterInstrumentation(PassManager & pm)876810c8bdSRiver Riddle void PassManagerOptions::addPrinterInstrumentation(PassManager &pm) {
88da53000fSRiver Riddle std::function<bool(Pass *, Operation *)> shouldPrintBeforePass;
89da53000fSRiver Riddle std::function<bool(Pass *, Operation *)> shouldPrintAfterPass;
906810c8bdSRiver Riddle
916810c8bdSRiver Riddle // Handle print-before.
926810c8bdSRiver Riddle if (printBeforeAll) {
936810c8bdSRiver Riddle // If we are printing before all, then just return true for the filter.
94da53000fSRiver Riddle shouldPrintBeforePass = [](Pass *, Operation *) { return true; };
959274ed66SRiver Riddle } else if (printBefore.hasAnyOccurrences()) {
966810c8bdSRiver Riddle // Otherwise if there are specific passes to print before, then check to see
976810c8bdSRiver Riddle // if the pass info for the current pass is included in the list.
98da53000fSRiver Riddle shouldPrintBeforePass = [&](Pass *pass, Operation *) {
996810c8bdSRiver Riddle auto *passInfo = pass->lookupPassInfo();
1009274ed66SRiver Riddle return passInfo && printBefore.contains(passInfo);
1016810c8bdSRiver Riddle };
1026810c8bdSRiver Riddle }
1036810c8bdSRiver Riddle
1046810c8bdSRiver Riddle // Handle print-after.
10564ce90e1SRiver Riddle if (printAfterAll || printAfterFailure) {
10664ce90e1SRiver Riddle // If we are printing after all or failure, then just return true for the
10764ce90e1SRiver Riddle // filter.
108da53000fSRiver Riddle shouldPrintAfterPass = [](Pass *, Operation *) { return true; };
1099274ed66SRiver Riddle } else if (printAfter.hasAnyOccurrences()) {
1106810c8bdSRiver Riddle // Otherwise if there are specific passes to print after, then check to see
1116810c8bdSRiver Riddle // if the pass info for the current pass is included in the list.
112da53000fSRiver Riddle shouldPrintAfterPass = [&](Pass *pass, Operation *) {
1136810c8bdSRiver Riddle auto *passInfo = pass->lookupPassInfo();
1149274ed66SRiver Riddle return passInfo && printAfter.contains(passInfo);
1156810c8bdSRiver Riddle };
1166810c8bdSRiver Riddle }
1176810c8bdSRiver Riddle
1186810c8bdSRiver Riddle // If there are no valid printing filters, then just return.
1196810c8bdSRiver Riddle if (!shouldPrintBeforePass && !shouldPrintAfterPass)
1206810c8bdSRiver Riddle return;
1216810c8bdSRiver Riddle
1226810c8bdSRiver Riddle // Otherwise, add the IR printing instrumentation.
1236810c8bdSRiver Riddle pm.enableIRPrinting(shouldPrintBeforePass, shouldPrintAfterPass,
12464ce90e1SRiver Riddle printModuleScope, printAfterChange, printAfterFailure,
125*d98481a1SMehdi Amini llvm::errs());
1266810c8bdSRiver Riddle }
1276810c8bdSRiver Riddle
registerPassManagerCLOptions()1286810c8bdSRiver Riddle void mlir::registerPassManagerCLOptions() {
1298938dea4SRiver Riddle // Make sure that the options struct has been constructed.
1308938dea4SRiver Riddle *options;
1316810c8bdSRiver Riddle }
1326810c8bdSRiver Riddle
applyPassManagerCLOptions(PassManager & pm)1336810c8bdSRiver Riddle void mlir::applyPassManagerCLOptions(PassManager &pm) {
1348938dea4SRiver Riddle if (!options.isConstructed())
1358938dea4SRiver Riddle return;
1368938dea4SRiver Riddle
1377a7dcc17SRiver Riddle // Generate a reproducer on crash/failure.
1388938dea4SRiver Riddle if (options->reproducerFile.getNumOccurrences())
139983382f1SRiver Riddle pm.enableCrashReproducerGeneration(options->reproducerFile,
140983382f1SRiver Riddle options->localReproducer);
1417a7dcc17SRiver Riddle
14233a64540SRiver Riddle // Enable statistics dumping.
1438938dea4SRiver Riddle if (options->passStatistics)
1448938dea4SRiver Riddle pm.enableStatistics(options->passStatisticsDisplayMode);
14533a64540SRiver Riddle
1466810c8bdSRiver Riddle // Add the IR printing instrumentation.
1478938dea4SRiver Riddle options->addPrinterInstrumentation(pm);
14833f908c4SFabian Schuiki }
1496810c8bdSRiver Riddle
applyDefaultTimingPassManagerCLOptions(PassManager & pm)15033f908c4SFabian Schuiki void mlir::applyDefaultTimingPassManagerCLOptions(PassManager &pm) {
15133f908c4SFabian Schuiki // Create a temporary timing manager for the PM to own, apply its CL options,
15233f908c4SFabian Schuiki // and pass it to the PM.
15333f908c4SFabian Schuiki auto tm = std::make_unique<DefaultTimingManager>();
15433f908c4SFabian Schuiki applyDefaultTimingManagerCLOptions(*tm);
15533f908c4SFabian Schuiki pm.enableTiming(std::move(tm));
1566810c8bdSRiver Riddle }
157