diff --git a/mlir/docs/Diagnostics.md b/mlir/docs/Diagnostics.md --- a/mlir/docs/Diagnostics.md +++ b/mlir/docs/Diagnostics.md @@ -200,7 +200,9 @@ ## Diagnostic Configuration Options Several options are provided to help control and enhance the behavior of -diagnostics. These options are listed below: +diagnostics. These options can be configured via the MLIRContext, and registered +to the command line with the `registerMLIRContextCLOptions` method. These +options are listed below: ### Print Operation On Diagnostic diff --git a/mlir/include/mlir/IR/AsmState.h b/mlir/include/mlir/IR/AsmState.h --- a/mlir/include/mlir/IR/AsmState.h +++ b/mlir/include/mlir/IR/AsmState.h @@ -55,6 +55,14 @@ std::unique_ptr impl; }; +//===----------------------------------------------------------------------===// +// AsmPrinter CommandLine Options +//===----------------------------------------------------------------------===// + +/// Register a set of useful command-line options that can be used to configure +/// various flags within the AsmPrinter. +void registerAsmPrinterCLOptions(); + } // end namespace mlir #endif // MLIR_IR_ASMSTATE_H_ diff --git a/mlir/include/mlir/IR/MLIRContext.h b/mlir/include/mlir/IR/MLIRContext.h --- a/mlir/include/mlir/IR/MLIRContext.h +++ b/mlir/include/mlir/IR/MLIRContext.h @@ -100,6 +100,16 @@ MLIRContext(const MLIRContext &) = delete; void operator=(const MLIRContext &) = delete; }; + +//===----------------------------------------------------------------------===// +// MLIRContext CommandLine Options +//===----------------------------------------------------------------------===// + +/// Register a set of useful command-line options that can be used to configure +/// various flags within the MLIRContext. These flags are used when constructing +/// an MLIR context for initialization. +void registerMLIRContextCLOptions(); + } // end namespace mlir #endif // MLIR_IR_MLIRCONTEXT_H diff --git a/mlir/lib/IR/AsmPrinter.cpp b/mlir/lib/IR/AsmPrinter.cpp --- a/mlir/lib/IR/AsmPrinter.cpp +++ b/mlir/lib/IR/AsmPrinter.cpp @@ -63,50 +63,66 @@ // OpPrintingFlags //===----------------------------------------------------------------------===// -static llvm::cl::opt printElementsAttrWithHexIfLarger( - "mlir-print-elementsattrs-with-hex-if-larger", - llvm::cl::desc( - "Print DenseElementsAttrs with a hex string that have " - "more elements than the given upper limit (use -1 to disable)"), - llvm::cl::init(100)); - -static llvm::cl::opt elideElementsAttrIfLarger( - "mlir-elide-elementsattrs-if-larger", - llvm::cl::desc("Elide ElementsAttrs with \"...\" that have " - "more elements than the given upper limit")); - -static llvm::cl::opt - printDebugInfoOpt("mlir-print-debuginfo", - llvm::cl::desc("Print debug info in MLIR output"), - llvm::cl::init(false)); - -static llvm::cl::opt printPrettyDebugInfoOpt( - "mlir-pretty-debuginfo", - llvm::cl::desc("Print pretty debug info in MLIR output"), - llvm::cl::init(false)); - -// Use the generic op output form in the operation printer even if the custom -// form is defined. -static llvm::cl::opt - printGenericOpFormOpt("mlir-print-op-generic", - llvm::cl::desc("Print the generic op form"), - llvm::cl::init(false), llvm::cl::Hidden); - -static llvm::cl::opt printLocalScopeOpt( - "mlir-print-local-scope", - llvm::cl::desc("Print assuming in local scope by default"), - llvm::cl::init(false), llvm::cl::Hidden); +namespace { +/// This struct contains command line options that can be used to initialize +/// various bits of the AsmPrinter. This uses a struct wrapper to avoid the need +/// for global command line options. +struct AsmPrinterOptions { + llvm::cl::opt printElementsAttrWithHexIfLarger{ + "mlir-print-elementsattrs-with-hex-if-larger", + llvm::cl::desc( + "Print DenseElementsAttrs with a hex string that have " + "more elements than the given upper limit (use -1 to disable)")}; + + llvm::cl::opt elideElementsAttrIfLarger{ + "mlir-elide-elementsattrs-if-larger", + llvm::cl::desc("Elide ElementsAttrs with \"...\" that have " + "more elements than the given upper limit")}; + + llvm::cl::opt printDebugInfoOpt{ + "mlir-print-debuginfo", llvm::cl::init(false), + llvm::cl::desc("Print debug info in MLIR output")}; + + llvm::cl::opt printPrettyDebugInfoOpt{ + "mlir-pretty-debuginfo", llvm::cl::init(false), + llvm::cl::desc("Print pretty debug info in MLIR output")}; + + // Use the generic op output form in the operation printer even if the custom + // form is defined. + llvm::cl::opt printGenericOpFormOpt{ + "mlir-print-op-generic", llvm::cl::init(false), + llvm::cl::desc("Print the generic op form"), llvm::cl::Hidden}; + + llvm::cl::opt printLocalScopeOpt{ + "mlir-print-local-scope", llvm::cl::init(false), + llvm::cl::desc("Print assuming in local scope by default"), + llvm::cl::Hidden}; +}; +} // end anonymous namespace + +static llvm::ManagedStatic clOptions; + +/// Register a set of useful command-line options that can be used to configure +/// various flags within the AsmPrinter. +void mlir::registerAsmPrinterCLOptions() { + // Make sure that the options struct has been initialized. + *clOptions; +} /// Initialize the printing flags with default supplied by the cl::opts above. OpPrintingFlags::OpPrintingFlags() - : elementsAttrElementLimit( - elideElementsAttrIfLarger.getNumOccurrences() - ? Optional(elideElementsAttrIfLarger) - : Optional()), - printDebugInfoFlag(printDebugInfoOpt), - printDebugInfoPrettyFormFlag(printPrettyDebugInfoOpt), - printGenericOpFormFlag(printGenericOpFormOpt), - printLocalScope(printLocalScopeOpt) {} + : printDebugInfoFlag(false), printDebugInfoPrettyFormFlag(false), + printGenericOpFormFlag(false), printLocalScope(false) { + // Initialize based upon command line options, if they are available. + if (!clOptions.isConstructed()) + return; + if (clOptions->elideElementsAttrIfLarger.getNumOccurrences()) + elementsAttrElementLimit = clOptions->elideElementsAttrIfLarger; + printDebugInfoFlag = clOptions->printDebugInfoOpt; + printDebugInfoPrettyFormFlag = clOptions->printPrettyDebugInfoOpt; + printGenericOpFormFlag = clOptions->printGenericOpFormOpt; + printLocalScope = clOptions->printLocalScopeOpt; +} /// Enable the elision of large elements attributes, by printing a '...' /// instead of the element data, when the number of elements is greater than @@ -169,6 +185,23 @@ /// Return if the printer should use local scope when dumping the IR. bool OpPrintingFlags::shouldUseLocalScope() const { return printLocalScope; } +/// Returns true if an ElementsAttr with the given number of elements should be +/// printed with hex. +static bool shouldPrintElementsAttrWithHex(int64_t numElements) { + // Check to see if a command line option was provided for the limit. + if (clOptions.isConstructed()) { + if (clOptions->printElementsAttrWithHexIfLarger.getNumOccurrences()) { + // -1 is used to disable hex printing. + if (clOptions->printElementsAttrWithHexIfLarger == -1) + return false; + return numElements > clOptions->printElementsAttrWithHexIfLarger; + } + } + + // Otherwise, default to printing with hex if the number of elements is >100. + return numElements > 100; +} + //===----------------------------------------------------------------------===// // NewLineCounter //===----------------------------------------------------------------------===// @@ -1451,8 +1484,7 @@ } // Check to see if we should format this attribute as a hex string. - if (allowHex && printElementsAttrWithHexIfLarger != -1 && - numElements > printElementsAttrWithHexIfLarger) { + if (allowHex && shouldPrintElementsAttrWithHex(numElements)) { ArrayRef rawData = attr.getRawData(); os << '"' << "0x" << llvm::toHex(StringRef(rawData.data(), rawData.size())) << "\""; diff --git a/mlir/lib/IR/CMakeLists.txt b/mlir/lib/IR/CMakeLists.txt --- a/mlir/lib/IR/CMakeLists.txt +++ b/mlir/lib/IR/CMakeLists.txt @@ -1,6 +1,3 @@ -# TODO: Remove the need for global constructors within IR/ -add_flag_if_supported("-Wno-global-constructors" WNO_GLOBAL_CONSTRUCTOR_MLIR_IR) - file(GLOB globbed *.c *.cpp) add_mlir_library(MLIRIR ${globbed} diff --git a/mlir/lib/IR/MLIRContext.cpp b/mlir/lib/IR/MLIRContext.cpp --- a/mlir/lib/IR/MLIRContext.cpp +++ b/mlir/lib/IR/MLIRContext.cpp @@ -42,16 +42,68 @@ using llvm::hash_combine; using llvm::hash_combine_range; -static llvm::cl::opt clPrintOpOnDiagnostic( - "mlir-print-op-on-diagnostic", - llvm::cl::desc("When a diagnostic is emitted on an operation, also print " - "the operation as an attached note"), - llvm::cl::init(true)); +//===----------------------------------------------------------------------===// +// MLIRContext CommandLine Options +//===----------------------------------------------------------------------===// + +namespace { +/// This struct contains command line options that can be used to initialize +/// various bits of an MLIRContext. This uses a struct wrapper to avoid the need +/// for global command line options. +struct MLIRContextOptions { + llvm::cl::opt printOpOnDiagnostic{ + "mlir-print-op-on-diagnostic", + llvm::cl::desc("When a diagnostic is emitted on an operation, also print " + "the operation as an attached note"), + llvm::cl::init(true)}; + + llvm::cl::opt printStackTraceOnDiagnostic{ + "mlir-print-stacktrace-on-diagnostic", + llvm::cl::desc("When a diagnostic is emitted, also print the stack trace " + "as an attached note")}; +}; +} // end anonymous namespace + +static llvm::ManagedStatic clOptions; + +/// Register a set of useful command-line options that can be used to configure +/// various flags within the MLIRContext. These flags are used when constructing +/// an MLIR context for initialization. +void mlir::registerMLIRContextCLOptions() { + // Make sure that the options struct has been initialized. + *clOptions; +} -static llvm::cl::opt clPrintStackTraceOnDiagnostic( - "mlir-print-stacktrace-on-diagnostic", - llvm::cl::desc("When a diagnostic is emitted, also print the stack trace " - "as an attached note")); +//===----------------------------------------------------------------------===// +// Builtin Dialect +//===----------------------------------------------------------------------===// + +namespace { +/// A builtin dialect to define types/etc that are necessary for the validity of +/// the IR. +struct BuiltinDialect : public Dialect { + BuiltinDialect(MLIRContext *context) : Dialect(/*name=*/"", context) { + addAttributes(); + addAttributes(); + + addTypes(); + + // TODO: These operations should be moved to a different dialect when they + // have been fully decoupled from the core. + addOperations(); + } +}; +} // end anonymous namespace. + +//===----------------------------------------------------------------------===// +// AffineMap and IntegerSet hashing +//===----------------------------------------------------------------------===// /// A utility function to safely get or create a uniqued instance within the /// given set container. @@ -81,27 +133,6 @@ } namespace { -/// A builtin dialect to define types/etc that are necessary for the validity of -/// the IR. -struct BuiltinDialect : public Dialect { - BuiltinDialect(MLIRContext *context) : Dialect(/*name=*/"", context) { - addAttributes(); - addAttributes(); - - addTypes(); - - // TODO: These operations should be moved to a different dialect when they - // have been fully decoupled from the core. - addOperations(); - } -}; - struct AffineMapKeyInfo : DenseMapInfo { // Affine maps are uniqued based on their dim/symbol counts and affine // expressions. @@ -155,6 +186,10 @@ }; } // end anonymous namespace. +//===----------------------------------------------------------------------===// +// MLIRContextImpl +//===----------------------------------------------------------------------===// + namespace mlir { /// This is the implementation of the MLIRContext class, using the pImpl idiom. /// This class is completely private to this file, so everything is public. @@ -184,10 +219,10 @@ /// If the operation should be attached to diagnostics printed via the /// Operation::emit methods. - bool printOpOnDiagnostic; + bool printOpOnDiagnostic = true; /// If the current stack trace should be attached when emitting diagnostics. - bool printStackTraceOnDiagnostic; + bool printStackTraceOnDiagnostic = false; //===--------------------------------------------------------------------===// // Other @@ -253,10 +288,13 @@ UnknownLoc unknownLocAttr; public: - MLIRContextImpl() - : printOpOnDiagnostic(clPrintOpOnDiagnostic), - printStackTraceOnDiagnostic(clPrintStackTraceOnDiagnostic), - identifiers(identifierAllocator) {} + MLIRContextImpl() : identifiers(identifierAllocator) { + // Initialize values based on the command line flags if they were provided. + if (clOptions.isConstructed()) { + printOpOnDiagnostic = clOptions->printOpOnDiagnostic; + printStackTraceOnDiagnostic = clOptions->printStackTraceOnDiagnostic; + } + } }; } // end namespace mlir @@ -397,9 +435,7 @@ /// Set the flag specifying if we should attach the operation to diagnostics /// emitted via Operation::emit. void MLIRContext::printOpOnDiagnostic(bool enable) { - // Let the command line option take priority. - if (!clPrintOpOnDiagnostic.getNumOccurrences()) - impl->printOpOnDiagnostic = enable; + impl->printOpOnDiagnostic = enable; } /// Return true if we should attach the current stacktrace to diagnostics when @@ -411,9 +447,7 @@ /// Set the flag specifying if we should attach the current stacktrace when /// emitting diagnostics. void MLIRContext::printStackTraceOnDiagnostic(bool enable) { - // Let the command line option take priority. - if (!clPrintStackTraceOnDiagnostic.getNumOccurrences()) - impl->printStackTraceOnDiagnostic = enable; + impl->printStackTraceOnDiagnostic = enable; } /// Return information about all registered operations. This isn't very diff --git a/mlir/lib/Pass/PassManagerOptions.cpp b/mlir/lib/Pass/PassManagerOptions.cpp --- a/mlir/lib/Pass/PassManagerOptions.cpp +++ b/mlir/lib/Pass/PassManagerOptions.cpp @@ -96,7 +96,7 @@ }; } // end anonymous namespace -static llvm::ManagedStatic> options; +static llvm::ManagedStatic options; /// Add an IR printing instrumentation if enabled by any 'print-ir' flags. void PassManagerOptions::addPrinterInstrumentation(PassManager &pm) { @@ -145,29 +145,31 @@ } void mlir::registerPassManagerCLOptions() { - // Reset the options instance if it hasn't been enabled yet. - if (!options->hasValue()) - options->emplace(); + // Make sure that the options struct has been constructed. + *options; } void mlir::applyPassManagerCLOptions(PassManager &pm) { + if (!options.isConstructed()) + return; + // Generate a reproducer on crash/failure. - if ((*options)->reproducerFile.getNumOccurrences()) - pm.enableCrashReproducerGeneration((*options)->reproducerFile); + if (options->reproducerFile.getNumOccurrences()) + pm.enableCrashReproducerGeneration(options->reproducerFile); // Disable multi-threading. - if ((*options)->disableThreads) + if (options->disableThreads) pm.disableMultithreading(); // Enable statistics dumping. - if ((*options)->passStatistics) - pm.enableStatistics((*options)->passStatisticsDisplayMode); + if (options->passStatistics) + pm.enableStatistics(options->passStatisticsDisplayMode); // Add the IR printing instrumentation. - (*options)->addPrinterInstrumentation(pm); + options->addPrinterInstrumentation(pm); // Note: The pass timing instrumentation should be added last to avoid any // potential "ghost" timing from other instrumentations being unintentionally // included in the timing results. - (*options)->addTimingInstrumentation(pm); + options->addTimingInstrumentation(pm); } diff --git a/mlir/test/IR/print-op-on-diagnostic.mlir b/mlir/test/IR/print-op-on-diagnostic.mlir --- a/mlir/test/IR/print-op-on-diagnostic.mlir +++ b/mlir/test/IR/print-op-on-diagnostic.mlir @@ -1,7 +1,7 @@ -// RUN: mlir-opt %s -verify-diagnostics -mlir-print-op-on-diagnostic +// RUN: not mlir-opt %s -mlir-print-op-on-diagnostic 2>&1 | FileCheck %s // This file tests the functionality of 'mlir-print-op-on-diagnostic'. -// expected-error@below {{invalid to use 'test.invalid_attr'}} -// expected-note@below {{see current operation: "module"()}} +// CHECK: {{invalid to use 'test.invalid_attr'}} +// CHECK: {{see current operation: "module"()}} module attributes {test.invalid_attr} {} diff --git a/mlir/tools/mlir-opt/mlir-opt.cpp b/mlir/tools/mlir-opt/mlir-opt.cpp --- a/mlir/tools/mlir-opt/mlir-opt.cpp +++ b/mlir/tools/mlir-opt/mlir-opt.cpp @@ -10,10 +10,11 @@ // //===----------------------------------------------------------------------===// -#include "mlir/InitAllDialects.h" -#include "mlir/InitAllPasses.h" +#include "mlir/IR/AsmState.h" #include "mlir/IR/Dialect.h" #include "mlir/IR/MLIRContext.h" +#include "mlir/InitAllDialects.h" +#include "mlir/InitAllPasses.h" #include "mlir/Pass/Pass.h" #include "mlir/Pass/PassManager.h" #include "mlir/Support/FileUtilities.h" @@ -138,7 +139,9 @@ registerTestPasses(); InitLLVM y(argc, argv); - // Register any pass manager command line options. + // Register any command line options. + registerAsmPrinterCLOptions(); + registerMLIRContextCLOptions(); registerPassManagerCLOptions(); PassPipelineCLParser passPipeline("", "Compiler passes to run"); diff --git a/mlir/tools/mlir-translate/mlir-translate.cpp b/mlir/tools/mlir-translate/mlir-translate.cpp --- a/mlir/tools/mlir-translate/mlir-translate.cpp +++ b/mlir/tools/mlir-translate/mlir-translate.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "mlir/IR/AsmState.h" #include "mlir/IR/Diagnostics.h" #include "mlir/IR/MLIRContext.h" #include "mlir/InitAllDialects.h" @@ -63,7 +64,8 @@ llvm::cl::opt translationRequested("", llvm::cl::desc("Translation to perform"), llvm::cl::Required); - + registerAsmPrinterCLOptions(); + registerMLIRContextCLOptions(); llvm::cl::ParseCommandLineOptions(argc, argv, "MLIR translation driver\n"); std::string errorMessage;