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