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<PassTimingDisplayMode> passTimingDisplayMode{ 73 "pass-timing-display", 74 llvm::cl::desc("Display method for pass timing data"), 75 llvm::cl::init(PassTimingDisplayMode::Pipeline), 76 llvm::cl::values( 77 clEnumValN(PassTimingDisplayMode::List, "list", 78 "display the results in a list sorted by total time"), 79 clEnumValN(PassTimingDisplayMode::Pipeline, "pipeline", 80 "display the results with a nested pipeline view"))}; 81 82 /// Add a pass timing instrumentation if enabled by 'pass-timing' flags. 83 void addTimingInstrumentation(PassManager &pm); 84 }; 85 } // end anonymous namespace 86 87 static llvm::ManagedStatic<llvm::Optional<PassManagerOptions>> options; 88 89 /// Add an IR printing instrumentation if enabled by any 'print-ir' flags. 90 void PassManagerOptions::addPrinterInstrumentation(PassManager &pm) { 91 std::function<bool(Pass *)> shouldPrintBeforePass, shouldPrintAfterPass; 92 93 // Handle print-before. 94 if (printBeforeAll) { 95 // If we are printing before all, then just return true for the filter. 96 shouldPrintBeforePass = [](Pass *) { return true; }; 97 } else if (printBefore.hasAnyOccurrences()) { 98 // Otherwise if there are specific passes to print before, then check to see 99 // if the pass info for the current pass is included in the list. 100 shouldPrintBeforePass = [&](Pass *pass) { 101 auto *passInfo = pass->lookupPassInfo(); 102 return passInfo && printBefore.contains(passInfo); 103 }; 104 } 105 106 // Handle print-after. 107 if (printAfterAll) { 108 // If we are printing after all, then just return true for the filter. 109 shouldPrintAfterPass = [](Pass *) { return true; }; 110 } else if (printAfter.hasAnyOccurrences()) { 111 // Otherwise if there are specific passes to print after, then check to see 112 // if the pass info for the current pass is included in the list. 113 shouldPrintAfterPass = [&](Pass *pass) { 114 auto *passInfo = pass->lookupPassInfo(); 115 return passInfo && printAfter.contains(passInfo); 116 }; 117 } 118 119 // If there are no valid printing filters, then just return. 120 if (!shouldPrintBeforePass && !shouldPrintAfterPass) 121 return; 122 123 // Otherwise, add the IR printing instrumentation. 124 pm.enableIRPrinting(shouldPrintBeforePass, shouldPrintAfterPass, 125 printModuleScope, llvm::errs()); 126 } 127 128 /// Add a pass timing instrumentation if enabled by 'pass-timing' flags. 129 void PassManagerOptions::addTimingInstrumentation(PassManager &pm) { 130 if (passTiming) 131 pm.enableTiming(passTimingDisplayMode); 132 } 133 134 void mlir::registerPassManagerCLOptions() { 135 // Reset the options instance if it hasn't been enabled yet. 136 if (!options->hasValue()) 137 options->emplace(); 138 } 139 140 void mlir::applyPassManagerCLOptions(PassManager &pm) { 141 // Generate a reproducer on crash/failure. 142 if ((*options)->reproducerFile.getNumOccurrences()) 143 pm.enableCrashReproducerGeneration((*options)->reproducerFile); 144 145 // Disable multi-threading. 146 if ((*options)->disableThreads) 147 pm.disableMultithreading(); 148 149 // Add the IR printing instrumentation. 150 (*options)->addPrinterInstrumentation(pm); 151 152 // Note: The pass timing instrumentation should be added last to avoid any 153 // potential "ghost" timing from other instrumentations being unintentionally 154 // included in the timing results. 155 (*options)->addTimingInstrumentation(pm); 156 } 157