185 lines · cpp
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-exception6//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 16using namespace mlir;17 18namespace {19struct PassManagerOptions {20 //===--------------------------------------------------------------------===//21 // Crash Reproducer Generator22 //===--------------------------------------------------------------------===//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 Printing35 //===--------------------------------------------------------------------===//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 Statistics72 //===--------------------------------------------------------------------===//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} // namespace88 89static llvm::ManagedStatic<PassManagerOptions> options;90 91/// Add an IR printing instrumentation if enabled by any 'print-ir' flags.92void 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 see102 // 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 the112 // 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 see116 // 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 140void mlir::registerPassManagerCLOptions() {141 // Make sure that the options struct has been constructed.142 *options;143}144 145LogicalResult mlir::applyPassManagerCLOptions(PassManager &pm) {146 if (!options.isConstructed())147 return failure();148 149 if (options->reproducerFile.getNumOccurrences() && options->localReproducer &&150 pm.getContext()->isMultithreadingEnabled()) {151 emitError(UnknownLoc::get(pm.getContext()))152 << "Local crash reproduction may not be used without disabling "153 "mutli-threading first.";154 return failure();155 }156 157 // Generate a reproducer on crash/failure.158 if (options->reproducerFile.getNumOccurrences())159 pm.enableCrashReproducerGeneration(options->reproducerFile,160 options->localReproducer);161 162 // Enable statistics dumping.163 if (options->passStatistics)164 pm.enableStatistics(options->passStatisticsDisplayMode);165 166 if (options->printModuleScope && pm.getContext()->isMultithreadingEnabled()) {167 emitError(UnknownLoc::get(pm.getContext()))168 << "IR print for module scope can't be setup on a pass-manager "169 "without disabling multi-threading first.\n";170 return failure();171 }172 173 // Add the IR printing instrumentation.174 options->addPrinterInstrumentation(pm);175 return success();176}177 178void mlir::applyDefaultTimingPassManagerCLOptions(PassManager &pm) {179 // Create a temporary timing manager for the PM to own, apply its CL options,180 // and pass it to the PM.181 auto tm = std::make_unique<DefaultTimingManager>();182 applyDefaultTimingManagerCLOptions(*tm);183 pm.enableTiming(std::move(tm));184}185