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