[mlir][IR] Manually register command line options for MLIRContext and AsmPrinter

Summary: This revision makes the registration of command line options for these two files manual with `registerMLIRContextCLOptions` and `registerAsmPrinterCLOptions` methods. This removes the last remaining static constructors within lib/.

Differential Revision: https://reviews.llvm.org/D77960
This commit is contained in:
River Riddle 2020-04-11 23:11:51 -07:00
parent 1fc6efaf6a
commit 8938dea44a
10 changed files with 192 additions and 102 deletions

View File

@ -200,7 +200,9 @@ destroyed.
## 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

View File

@ -55,6 +55,14 @@ private:
std::unique_ptr<detail::AsmStateImpl> 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_

View File

@ -100,6 +100,16 @@ private:
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

View File

@ -63,50 +63,66 @@ OpAsmPrinter::~OpAsmPrinter() {}
// OpPrintingFlags
//===----------------------------------------------------------------------===//
static llvm::cl::opt<int> 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));
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<int64_t> 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)")};
static llvm::cl::opt<unsigned> elideElementsAttrIfLarger(
"mlir-elide-elementsattrs-if-larger",
llvm::cl::desc("Elide ElementsAttrs with \"...\" that have "
"more elements than the given upper limit"));
llvm::cl::opt<unsigned> 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<bool>
printDebugInfoOpt("mlir-print-debuginfo",
llvm::cl::desc("Print debug info in MLIR output"),
llvm::cl::init(false));
llvm::cl::opt<bool> printDebugInfoOpt{
"mlir-print-debuginfo", llvm::cl::init(false),
llvm::cl::desc("Print debug info in MLIR output")};
static llvm::cl::opt<bool> printPrettyDebugInfoOpt(
"mlir-pretty-debuginfo",
llvm::cl::desc("Print pretty debug info in MLIR output"),
llvm::cl::init(false));
llvm::cl::opt<bool> 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.
static llvm::cl::opt<bool>
printGenericOpFormOpt("mlir-print-op-generic",
llvm::cl::desc("Print the generic op form"),
llvm::cl::init(false), llvm::cl::Hidden);
// Use the generic op output form in the operation printer even if the custom
// form is defined.
llvm::cl::opt<bool> printGenericOpFormOpt{
"mlir-print-op-generic", llvm::cl::init(false),
llvm::cl::desc("Print the generic op form"), llvm::cl::Hidden};
static llvm::cl::opt<bool> printLocalScopeOpt(
"mlir-print-local-scope",
llvm::cl::desc("Print assuming in local scope by default"),
llvm::cl::init(false), llvm::cl::Hidden);
llvm::cl::opt<bool> 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<AsmPrinterOptions> 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<int64_t>(elideElementsAttrIfLarger)
: Optional<int64_t>()),
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 @@ bool OpPrintingFlags::shouldPrintGenericOpForm() const {
/// 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 @@ void ModulePrinter::printDenseElementsAttr(DenseElementsAttr attr,
}
// Check to see if we should format this attribute as a hex string.
if (allowHex && printElementsAttrWithHexIfLarger != -1 &&
numElements > printElementsAttrWithHexIfLarger) {
if (allowHex && shouldPrintElementsAttrWithHex(numElements)) {
ArrayRef<char> rawData = attr.getRawData();
os << '"' << "0x" << llvm::toHex(StringRef(rawData.data(), rawData.size()))
<< "\"";

View File

@ -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}

View File

@ -42,16 +42,68 @@ using namespace mlir::detail;
using llvm::hash_combine;
using llvm::hash_combine_range;
static llvm::cl::opt<bool> 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
//===----------------------------------------------------------------------===//
static llvm::cl::opt<bool> clPrintStackTraceOnDiagnostic(
"mlir-print-stacktrace-on-diagnostic",
llvm::cl::desc("When a diagnostic is emitted, also print the stack trace "
"as an attached note"));
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<bool> 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<bool> 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<MLIRContextOptions> 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;
}
//===----------------------------------------------------------------------===//
// 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<AffineMapAttr, ArrayAttr, BoolAttr, DenseElementsAttr,
DictionaryAttr, FloatAttr, SymbolRefAttr, IntegerAttr,
IntegerSetAttr, OpaqueAttr, OpaqueElementsAttr,
SparseElementsAttr, StringAttr, TypeAttr, UnitAttr>();
addAttributes<CallSiteLoc, FileLineColLoc, FusedLoc, NameLoc, OpaqueLoc,
UnknownLoc>();
addTypes<ComplexType, FloatType, FunctionType, IndexType, IntegerType,
MemRefType, UnrankedMemRefType, NoneType, OpaqueType,
RankedTensorType, TupleType, UnrankedTensorType, VectorType>();
// TODO: These operations should be moved to a different dialect when they
// have been fully decoupled from the core.
addOperations<FuncOp, ModuleOp, ModuleTerminatorOp>();
}
};
} // 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 @@ static ValueT safeGetOrCreate(DenseSet<ValueT, DenseInfoT> &container,
}
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<AffineMapAttr, ArrayAttr, BoolAttr, DenseElementsAttr,
DictionaryAttr, FloatAttr, SymbolRefAttr, IntegerAttr,
IntegerSetAttr, OpaqueAttr, OpaqueElementsAttr,
SparseElementsAttr, StringAttr, TypeAttr, UnitAttr>();
addAttributes<CallSiteLoc, FileLineColLoc, FusedLoc, NameLoc, OpaqueLoc,
UnknownLoc>();
addTypes<ComplexType, FloatType, FunctionType, IndexType, IntegerType,
MemRefType, UnrankedMemRefType, NoneType, OpaqueType,
RankedTensorType, TupleType, UnrankedTensorType, VectorType>();
// TODO: These operations should be moved to a different dialect when they
// have been fully decoupled from the core.
addOperations<FuncOp, ModuleOp, ModuleTerminatorOp>();
}
};
struct AffineMapKeyInfo : DenseMapInfo<AffineMap> {
// Affine maps are uniqued based on their dim/symbol counts and affine
// expressions.
@ -155,6 +186,10 @@ struct IntegerSetKeyInfo : DenseMapInfo<IntegerSet> {
};
} // 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 @@ public:
/// 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 @@ public:
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 @@ bool MLIRContext::shouldPrintOpOnDiagnostic() {
/// 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 @@ bool MLIRContext::shouldPrintStackTraceOnDiagnostic() {
/// 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

View File

@ -96,7 +96,7 @@ struct PassManagerOptions {
};
} // end anonymous namespace
static llvm::ManagedStatic<Optional<PassManagerOptions>> options;
static llvm::ManagedStatic<PassManagerOptions> options;
/// Add an IR printing instrumentation if enabled by any 'print-ir' flags.
void PassManagerOptions::addPrinterInstrumentation(PassManager &pm) {
@ -145,29 +145,31 @@ void PassManagerOptions::addTimingInstrumentation(PassManager &pm) {
}
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);
}

View File

@ -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} {}

View File

@ -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 @@ int main(int argc, char **argv) {
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");

View File

@ -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 @@ int main(int argc, char **argv) {
llvm::cl::opt<const TranslateFunction *, false, TranslationParser>
translationRequested("", llvm::cl::desc("Translation to perform"),
llvm::cl::Required);
registerAsmPrinterCLOptions();
registerMLIRContextCLOptions();
llvm::cl::ParseCommandLineOptions(argc, argv, "MLIR translation driver\n");
std::string errorMessage;