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