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 "llvm/Support/CommandLine.h" 13 #include "llvm/Support/ManagedStatic.h" 14 15 using namespace mlir; 16 17 namespace { 18 struct PassManagerOptions { 19 //===--------------------------------------------------------------------===// 20 // Crash Reproducer Generator 21 //===--------------------------------------------------------------------===// 22 llvm::cl::opt<std::string> reproducerFile{ 23 "pass-pipeline-crash-reproducer", 24 llvm::cl::desc("Generate a .mlir reproducer file at the given output path" 25 " if the pass manager crashes or fails")}; 26 llvm::cl::opt<bool> localReproducer{ 27 "pass-pipeline-local-reproducer", 28 llvm::cl::desc("When generating a crash reproducer, attempt to generated " 29 "a reproducer with the smallest pipeline."), 30 llvm::cl::init(false)}; 31 32 //===--------------------------------------------------------------------===// 33 // IR Printing 34 //===--------------------------------------------------------------------===// 35 PassPipelineCLParser printBefore{"print-ir-before", 36 "Print IR before specified passes"}; 37 PassPipelineCLParser printAfter{"print-ir-after", 38 "Print IR after specified passes"}; 39 llvm::cl::opt<bool> printBeforeAll{ 40 "print-ir-before-all", llvm::cl::desc("Print IR before each pass"), 41 llvm::cl::init(false)}; 42 llvm::cl::opt<bool> printAfterAll{"print-ir-after-all", 43 llvm::cl::desc("Print IR after each pass"), 44 llvm::cl::init(false)}; 45 llvm::cl::opt<bool> printAfterChange{ 46 "print-ir-after-change", 47 llvm::cl::desc( 48 "When printing the IR after a pass, only print if the IR changed"), 49 llvm::cl::init(false)}; 50 llvm::cl::opt<bool> printModuleScope{ 51 "print-ir-module-scope", 52 llvm::cl::desc("When printing IR for print-ir-[before|after]{-all} " 53 "always print the top-level module operation"), 54 llvm::cl::init(false)}; 55 56 /// Add an IR printing instrumentation if enabled by any 'print-ir' flags. 57 void addPrinterInstrumentation(PassManager &pm); 58 59 //===--------------------------------------------------------------------===// 60 // Pass Timing 61 //===--------------------------------------------------------------------===// 62 llvm::cl::opt<bool> passTiming{ 63 "pass-timing", 64 llvm::cl::desc("Display the execution times of each pass")}; 65 llvm::cl::opt<PassDisplayMode> passTimingDisplayMode{ 66 "pass-timing-display", 67 llvm::cl::desc("Display method for pass timing data"), 68 llvm::cl::init(PassDisplayMode::Pipeline), 69 llvm::cl::values( 70 clEnumValN(PassDisplayMode::List, "list", 71 "display the results in a list sorted by total time"), 72 clEnumValN(PassDisplayMode::Pipeline, "pipeline", 73 "display the results with a nested pipeline view"))}; 74 75 //===--------------------------------------------------------------------===// 76 // Pass Statistics 77 //===--------------------------------------------------------------------===// 78 llvm::cl::opt<bool> passStatistics{ 79 "pass-statistics", llvm::cl::desc("Display the statistics of each pass")}; 80 llvm::cl::opt<PassDisplayMode> passStatisticsDisplayMode{ 81 "pass-statistics-display", 82 llvm::cl::desc("Display method for pass statistics"), 83 llvm::cl::init(PassDisplayMode::Pipeline), 84 llvm::cl::values( 85 clEnumValN( 86 PassDisplayMode::List, "list", 87 "display the results in a merged list sorted by pass name"), 88 clEnumValN(PassDisplayMode::Pipeline, "pipeline", 89 "display the results with a nested pipeline view"))}; 90 91 /// Add a pass timing instrumentation if enabled by 'pass-timing' flags. 92 void addTimingInstrumentation(PassManager &pm); 93 }; 94 } // end anonymous namespace 95 96 static llvm::ManagedStatic<PassManagerOptions> options; 97 98 /// Add an IR printing instrumentation if enabled by any 'print-ir' flags. 99 void PassManagerOptions::addPrinterInstrumentation(PassManager &pm) { 100 std::function<bool(Pass *, Operation *)> shouldPrintBeforePass; 101 std::function<bool(Pass *, Operation *)> shouldPrintAfterPass; 102 103 // Handle print-before. 104 if (printBeforeAll) { 105 // If we are printing before all, then just return true for the filter. 106 shouldPrintBeforePass = [](Pass *, Operation *) { return true; }; 107 } else if (printBefore.hasAnyOccurrences()) { 108 // Otherwise if there are specific passes to print before, then check to see 109 // if the pass info for the current pass is included in the list. 110 shouldPrintBeforePass = [&](Pass *pass, Operation *) { 111 auto *passInfo = pass->lookupPassInfo(); 112 return passInfo && printBefore.contains(passInfo); 113 }; 114 } 115 116 // Handle print-after. 117 if (printAfterAll) { 118 // If we are printing after all, then just return true for the filter. 119 shouldPrintAfterPass = [](Pass *, Operation *) { return true; }; 120 } else if (printAfter.hasAnyOccurrences()) { 121 // Otherwise if there are specific passes to print after, then check to see 122 // if the pass info for the current pass is included in the list. 123 shouldPrintAfterPass = [&](Pass *pass, Operation *) { 124 auto *passInfo = pass->lookupPassInfo(); 125 return passInfo && printAfter.contains(passInfo); 126 }; 127 } 128 129 // If there are no valid printing filters, then just return. 130 if (!shouldPrintBeforePass && !shouldPrintAfterPass) 131 return; 132 133 // Otherwise, add the IR printing instrumentation. 134 pm.enableIRPrinting(shouldPrintBeforePass, shouldPrintAfterPass, 135 printModuleScope, printAfterChange, llvm::errs()); 136 } 137 138 /// Add a pass timing instrumentation if enabled by 'pass-timing' flags. 139 void PassManagerOptions::addTimingInstrumentation(PassManager &pm) { 140 if (passTiming) 141 pm.enableTiming( 142 std::make_unique<PassManager::PassTimingConfig>(passTimingDisplayMode)); 143 } 144 145 void mlir::registerPassManagerCLOptions() { 146 // Make sure that the options struct has been constructed. 147 *options; 148 } 149 150 void mlir::applyPassManagerCLOptions(PassManager &pm) { 151 if (!options.isConstructed()) 152 return; 153 154 // Generate a reproducer on crash/failure. 155 if (options->reproducerFile.getNumOccurrences()) 156 pm.enableCrashReproducerGeneration(options->reproducerFile, 157 options->localReproducer); 158 159 // Enable statistics dumping. 160 if (options->passStatistics) 161 pm.enableStatistics(options->passStatisticsDisplayMode); 162 163 // Add the IR printing instrumentation. 164 options->addPrinterInstrumentation(pm); 165 166 // Note: The pass timing instrumentation should be added last to avoid any 167 // potential "ghost" timing from other instrumentations being unintentionally 168 // included in the timing results. 169 options->addTimingInstrumentation(pm); 170 } 171