xref: /llvm-project/mlir/lib/Pass/PassManagerOptions.cpp (revision 7f1968625a607fb49a2b9a67f3c8fb2892cf4839)
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)};
619ad5da2dSChristopher Bate   llvm::cl::opt<std::string> printTreeDir{
629ad5da2dSChristopher Bate       "mlir-print-ir-tree-dir",
639ad5da2dSChristopher Bate       llvm::cl::desc("When printing the IR before/after a pass, print file "
64*7f196862SJeremy Kun                      "tree rooted at this directory. Use in conjunction with "
65*7f196862SJeremy Kun                      "mlir-print-ir-* flags")};
666810c8bdSRiver Riddle 
676810c8bdSRiver Riddle   /// Add an IR printing instrumentation if enabled by any 'print-ir' flags.
686810c8bdSRiver Riddle   void addPrinterInstrumentation(PassManager &pm);
696810c8bdSRiver Riddle 
706810c8bdSRiver Riddle   //===--------------------------------------------------------------------===//
7133a64540SRiver Riddle   // Pass Statistics
7233a64540SRiver Riddle   //===--------------------------------------------------------------------===//
7333a64540SRiver Riddle   llvm::cl::opt<bool> passStatistics{
74fb16ed25SAndrzej Warzynski       "mlir-pass-statistics",
75fb16ed25SAndrzej Warzynski       llvm::cl::desc("Display the statistics of each pass")};
7633a64540SRiver Riddle   llvm::cl::opt<PassDisplayMode> passStatisticsDisplayMode{
77fb16ed25SAndrzej Warzynski       "mlir-pass-statistics-display",
7833a64540SRiver Riddle       llvm::cl::desc("Display method for pass statistics"),
7933a64540SRiver Riddle       llvm::cl::init(PassDisplayMode::Pipeline),
8033a64540SRiver Riddle       llvm::cl::values(
8133a64540SRiver Riddle           clEnumValN(
8233a64540SRiver Riddle               PassDisplayMode::List, "list",
8333a64540SRiver Riddle               "display the results in a merged list sorted by pass name"),
8433a64540SRiver Riddle           clEnumValN(PassDisplayMode::Pipeline, "pipeline",
85b245e951SRiver Riddle                      "display the results with a nested pipeline view"))};
86b245e951SRiver Riddle };
87be0a7e9fSMehdi Amini } // namespace
88b245e951SRiver Riddle 
898938dea4SRiver Riddle static llvm::ManagedStatic<PassManagerOptions> options;
906810c8bdSRiver Riddle 
916810c8bdSRiver Riddle /// Add an IR printing instrumentation if enabled by any 'print-ir' flags.
926810c8bdSRiver Riddle void PassManagerOptions::addPrinterInstrumentation(PassManager &pm) {
93da53000fSRiver Riddle   std::function<bool(Pass *, Operation *)> shouldPrintBeforePass;
94da53000fSRiver Riddle   std::function<bool(Pass *, Operation *)> shouldPrintAfterPass;
956810c8bdSRiver Riddle 
966810c8bdSRiver Riddle   // Handle print-before.
976810c8bdSRiver Riddle   if (printBeforeAll) {
986810c8bdSRiver Riddle     // If we are printing before all, then just return true for the filter.
99da53000fSRiver Riddle     shouldPrintBeforePass = [](Pass *, Operation *) { return true; };
1009274ed66SRiver Riddle   } else if (printBefore.hasAnyOccurrences()) {
1016810c8bdSRiver Riddle     // Otherwise if there are specific passes to print before, then check to see
1026810c8bdSRiver Riddle     // if the pass info for the current pass is included in the list.
103da53000fSRiver Riddle     shouldPrintBeforePass = [&](Pass *pass, Operation *) {
1046810c8bdSRiver Riddle       auto *passInfo = pass->lookupPassInfo();
1059274ed66SRiver Riddle       return passInfo && printBefore.contains(passInfo);
1066810c8bdSRiver Riddle     };
1076810c8bdSRiver Riddle   }
1086810c8bdSRiver Riddle 
1096810c8bdSRiver Riddle   // Handle print-after.
11064ce90e1SRiver Riddle   if (printAfterAll || printAfterFailure) {
11164ce90e1SRiver Riddle     // If we are printing after all or failure, then just return true for the
11264ce90e1SRiver Riddle     // filter.
113da53000fSRiver Riddle     shouldPrintAfterPass = [](Pass *, Operation *) { return true; };
1149274ed66SRiver Riddle   } else if (printAfter.hasAnyOccurrences()) {
1156810c8bdSRiver Riddle     // Otherwise if there are specific passes to print after, then check to see
1166810c8bdSRiver Riddle     // if the pass info for the current pass is included in the list.
117da53000fSRiver Riddle     shouldPrintAfterPass = [&](Pass *pass, Operation *) {
1186810c8bdSRiver Riddle       auto *passInfo = pass->lookupPassInfo();
1199274ed66SRiver Riddle       return passInfo && printAfter.contains(passInfo);
1206810c8bdSRiver Riddle     };
1216810c8bdSRiver Riddle   }
1226810c8bdSRiver Riddle 
1236810c8bdSRiver Riddle   // If there are no valid printing filters, then just return.
1246810c8bdSRiver Riddle   if (!shouldPrintBeforePass && !shouldPrintAfterPass)
1256810c8bdSRiver Riddle     return;
1266810c8bdSRiver Riddle 
1276810c8bdSRiver Riddle   // Otherwise, add the IR printing instrumentation.
1289ad5da2dSChristopher Bate   if (!printTreeDir.empty()) {
1299ad5da2dSChristopher Bate     pm.enableIRPrintingToFileTree(shouldPrintBeforePass, shouldPrintAfterPass,
1309ad5da2dSChristopher Bate                                   printModuleScope, printAfterChange,
1319ad5da2dSChristopher Bate                                   printAfterFailure, printTreeDir);
1329ad5da2dSChristopher Bate     return;
1339ad5da2dSChristopher Bate   }
1349ad5da2dSChristopher Bate 
1356810c8bdSRiver Riddle   pm.enableIRPrinting(shouldPrintBeforePass, shouldPrintAfterPass,
13664ce90e1SRiver Riddle                       printModuleScope, printAfterChange, printAfterFailure,
137d98481a1SMehdi Amini                       llvm::errs());
1386810c8bdSRiver Riddle }
1396810c8bdSRiver Riddle 
1406810c8bdSRiver Riddle void mlir::registerPassManagerCLOptions() {
1418938dea4SRiver Riddle   // Make sure that the options struct has been constructed.
1428938dea4SRiver Riddle   *options;
1436810c8bdSRiver Riddle }
1446810c8bdSRiver Riddle 
145470f3ceeSKai Sasaki LogicalResult mlir::applyPassManagerCLOptions(PassManager &pm) {
1468938dea4SRiver Riddle   if (!options.isConstructed())
147470f3ceeSKai Sasaki     return failure();
1488938dea4SRiver Riddle 
1497a7dcc17SRiver Riddle   // Generate a reproducer on crash/failure.
1508938dea4SRiver Riddle   if (options->reproducerFile.getNumOccurrences())
151983382f1SRiver Riddle     pm.enableCrashReproducerGeneration(options->reproducerFile,
152983382f1SRiver Riddle                                        options->localReproducer);
1537a7dcc17SRiver Riddle 
15433a64540SRiver Riddle   // Enable statistics dumping.
1558938dea4SRiver Riddle   if (options->passStatistics)
1568938dea4SRiver Riddle     pm.enableStatistics(options->passStatisticsDisplayMode);
15733a64540SRiver Riddle 
158470f3ceeSKai Sasaki   if (options->printModuleScope && pm.getContext()->isMultithreadingEnabled()) {
159470f3ceeSKai Sasaki     emitError(UnknownLoc::get(pm.getContext()))
160470f3ceeSKai Sasaki         << "IR print for module scope can't be setup on a pass-manager "
161470f3ceeSKai Sasaki            "without disabling multi-threading first.\n";
162470f3ceeSKai Sasaki     return failure();
163470f3ceeSKai Sasaki   }
164470f3ceeSKai Sasaki 
1656810c8bdSRiver Riddle   // Add the IR printing instrumentation.
1668938dea4SRiver Riddle   options->addPrinterInstrumentation(pm);
167470f3ceeSKai Sasaki   return success();
16833f908c4SFabian Schuiki }
1696810c8bdSRiver Riddle 
17033f908c4SFabian Schuiki void mlir::applyDefaultTimingPassManagerCLOptions(PassManager &pm) {
17133f908c4SFabian Schuiki   // Create a temporary timing manager for the PM to own, apply its CL options,
17233f908c4SFabian Schuiki   // and pass it to the PM.
17333f908c4SFabian Schuiki   auto tm = std::make_unique<DefaultTimingManager>();
17433f908c4SFabian Schuiki   applyDefaultTimingManagerCLOptions(*tm);
17533f908c4SFabian Schuiki   pm.enableTiming(std::move(tm));
1766810c8bdSRiver Riddle }
177