1 //===- PassManagerOptions.cpp - PassManager Command Line Options ----------===// 2 // 3 // Copyright 2019 The MLIR Authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // ============================================================================= 17 18 #include "mlir/Pass/Pass.h" 19 #include "mlir/Pass/PassManager.h" 20 #include "mlir/Pass/PassRegistry.h" 21 #include "llvm/Support/CommandLine.h" 22 #include "llvm/Support/ManagedStatic.h" 23 24 using namespace mlir; 25 26 namespace { 27 struct PassManagerOptions { 28 //===--------------------------------------------------------------------===// 29 // Crash Reproducer Generator 30 //===--------------------------------------------------------------------===// 31 llvm::cl::opt<std::string> reproducerFile{ 32 "pass-pipeline-crash-reproducer", 33 llvm::cl::desc("Generate a .mlir reproducer file at the given output path" 34 " if the pass manager crashes or fails")}; 35 36 //===--------------------------------------------------------------------===// 37 // Multi-threading 38 //===--------------------------------------------------------------------===// 39 llvm::cl::opt<bool> disableThreads{ 40 "disable-pass-threading", 41 llvm::cl::desc("Disable multithreading in the pass manager"), 42 llvm::cl::init(false)}; 43 44 //===--------------------------------------------------------------------===// 45 // IR Printing 46 //===--------------------------------------------------------------------===// 47 PassPipelineCLParser printBefore{"print-ir-before", 48 "Print IR before specified passes"}; 49 PassPipelineCLParser printAfter{"print-ir-after", 50 "Print IR after specified passes"}; 51 llvm::cl::opt<bool> printBeforeAll{ 52 "print-ir-before-all", llvm::cl::desc("Print IR before each pass"), 53 llvm::cl::init(false)}; 54 llvm::cl::opt<bool> printAfterAll{"print-ir-after-all", 55 llvm::cl::desc("Print IR after each pass"), 56 llvm::cl::init(false)}; 57 llvm::cl::opt<bool> printModuleScope{ 58 "print-ir-module-scope", 59 llvm::cl::desc("When printing IR for print-ir-[before|after]{-all} " 60 "always print the top-level module operation"), 61 llvm::cl::init(false)}; 62 63 /// Add an IR printing instrumentation if enabled by any 'print-ir' flags. 64 void addPrinterInstrumentation(PassManager &pm); 65 66 //===--------------------------------------------------------------------===// 67 // Pass Timing 68 //===--------------------------------------------------------------------===// 69 llvm::cl::opt<bool> passTiming{ 70 "pass-timing", 71 llvm::cl::desc("Display the execution times of each pass")}; 72 llvm::cl::opt<PassDisplayMode> passTimingDisplayMode{ 73 "pass-timing-display", 74 llvm::cl::desc("Display method for pass timing data"), 75 llvm::cl::init(PassDisplayMode::Pipeline), 76 llvm::cl::values( 77 clEnumValN(PassDisplayMode::List, "list", 78 "display the results in a list sorted by total time"), 79 clEnumValN(PassDisplayMode::Pipeline, "pipeline", 80 "display the results with a nested pipeline view"))}; 81 82 //===--------------------------------------------------------------------===// 83 // Pass Statistics 84 //===--------------------------------------------------------------------===// 85 llvm::cl::opt<bool> passStatistics{ 86 "pass-statistics", llvm::cl::desc("Display the statistics of each pass")}; 87 llvm::cl::opt<PassDisplayMode> passStatisticsDisplayMode{ 88 "pass-statistics-display", 89 llvm::cl::desc("Display method for pass statistics"), 90 llvm::cl::init(PassDisplayMode::Pipeline), 91 llvm::cl::values( 92 clEnumValN( 93 PassDisplayMode::List, "list", 94 "display the results in a merged list sorted by pass name"), 95 clEnumValN(PassDisplayMode::Pipeline, "pipeline", 96 "display the results with a nested pipeline view"))}; 97 98 /// Add a pass timing instrumentation if enabled by 'pass-timing' flags. 99 void addTimingInstrumentation(PassManager &pm); 100 }; 101 } // end anonymous namespace 102 103 static llvm::ManagedStatic<llvm::Optional<PassManagerOptions>> options; 104 105 /// Add an IR printing instrumentation if enabled by any 'print-ir' flags. 106 void PassManagerOptions::addPrinterInstrumentation(PassManager &pm) { 107 std::function<bool(Pass *, Operation *)> shouldPrintBeforePass; 108 std::function<bool(Pass *, Operation *)> shouldPrintAfterPass; 109 110 // Handle print-before. 111 if (printBeforeAll) { 112 // If we are printing before all, then just return true for the filter. 113 shouldPrintBeforePass = [](Pass *, Operation *) { return true; }; 114 } else if (printBefore.hasAnyOccurrences()) { 115 // Otherwise if there are specific passes to print before, then check to see 116 // if the pass info for the current pass is included in the list. 117 shouldPrintBeforePass = [&](Pass *pass, Operation *) { 118 auto *passInfo = pass->lookupPassInfo(); 119 return passInfo && printBefore.contains(passInfo); 120 }; 121 } 122 123 // Handle print-after. 124 if (printAfterAll) { 125 // If we are printing after all, then just return true for the filter. 126 shouldPrintAfterPass = [](Pass *, Operation *) { return true; }; 127 } else if (printAfter.hasAnyOccurrences()) { 128 // Otherwise if there are specific passes to print after, then check to see 129 // if the pass info for the current pass is included in the list. 130 shouldPrintAfterPass = [&](Pass *pass, Operation *) { 131 auto *passInfo = pass->lookupPassInfo(); 132 return passInfo && printAfter.contains(passInfo); 133 }; 134 } 135 136 // If there are no valid printing filters, then just return. 137 if (!shouldPrintBeforePass && !shouldPrintAfterPass) 138 return; 139 140 // Otherwise, add the IR printing instrumentation. 141 pm.enableIRPrinting(shouldPrintBeforePass, shouldPrintAfterPass, 142 printModuleScope, llvm::errs()); 143 } 144 145 /// Add a pass timing instrumentation if enabled by 'pass-timing' flags. 146 void PassManagerOptions::addTimingInstrumentation(PassManager &pm) { 147 if (passTiming) 148 pm.enableTiming(passTimingDisplayMode); 149 } 150 151 void mlir::registerPassManagerCLOptions() { 152 // Reset the options instance if it hasn't been enabled yet. 153 if (!options->hasValue()) 154 options->emplace(); 155 } 156 157 void mlir::applyPassManagerCLOptions(PassManager &pm) { 158 // Generate a reproducer on crash/failure. 159 if ((*options)->reproducerFile.getNumOccurrences()) 160 pm.enableCrashReproducerGeneration((*options)->reproducerFile); 161 162 // Disable multi-threading. 163 if ((*options)->disableThreads) 164 pm.disableMultithreading(); 165 166 // Enable statistics dumping. 167 if ((*options)->passStatistics) 168 pm.enableStatistics((*options)->passStatisticsDisplayMode); 169 170 // Add the IR printing instrumentation. 171 (*options)->addPrinterInstrumentation(pm); 172 173 // Note: The pass timing instrumentation should be added last to avoid any 174 // potential "ghost" timing from other instrumentations being unintentionally 175 // included in the timing results. 176 (*options)->addTimingInstrumentation(pm); 177 } 178