diff --git a/mlir/include/mlir-c/BuiltinAttributes.h b/mlir/include/mlir-c/BuiltinAttributes.h --- a/mlir/include/mlir-c/BuiltinAttributes.h +++ b/mlir/include/mlir-c/BuiltinAttributes.h @@ -453,15 +453,6 @@ MLIR_CAPI_EXPORTED const void * mlirDenseElementsAttrGetRawData(MlirAttribute attr); -//===----------------------------------------------------------------------===// -// Opaque elements attribute. -//===----------------------------------------------------------------------===// - -// TODO: expose Dialect to the bindings and implement accessors here. - -/// Checks whether the given attribute is an opaque elements attribute. -MLIR_CAPI_EXPORTED bool mlirAttributeIsAOpaqueElements(MlirAttribute attr); - //===----------------------------------------------------------------------===// // Sparse elements attribute. //===----------------------------------------------------------------------===// diff --git a/mlir/include/mlir/IR/BuiltinAttributes.td b/mlir/include/mlir/IR/BuiltinAttributes.td --- a/mlir/include/mlir/IR/BuiltinAttributes.td +++ b/mlir/include/mlir/IR/BuiltinAttributes.td @@ -738,68 +738,6 @@ let skipDefaultBuilders = 1; } -//===----------------------------------------------------------------------===// -// OpaqueElementsAttr -//===----------------------------------------------------------------------===// - -def Builtin_OpaqueElementsAttr : Builtin_Attr< - "OpaqueElements", [ElementsAttrInterface] - > { - let summary = "An opaque representation of a multi-dimensional array"; - let description = [{ - Syntax: - - ``` - opaque-elements-attribute ::= `opaque` `<` dialect-namespace `,` - hex-string-literal `>` `:` - ( tensor-type | vector-type ) - ``` - - An opaque elements attribute is an elements attribute where the content of - the value is opaque. The representation of the constant stored by this - elements attribute is only understood, and thus decodable, by the dialect - that created it. - - Note: The parsed string literal must be in hexadecimal form. - - Examples: - - ```mlir - opaque<"foo_dialect", "0xDEADBEEF"> : tensor<10xi32> - ``` - }]; - - // TODO: Provide a way to avoid copying content of large opaque - // tensors This will likely require a new reference attribute kind. - let parameters = (ins "StringAttr":$dialect, - StringRefParameter<"">:$value, - AttributeSelfTypeParameter<"", "ShapedType">:$type); - let builders = [ - AttrBuilderWithInferredContext<(ins "StringAttr":$dialect, - "ShapedType":$type, - "StringRef":$value), [{ - return $_get(dialect.getContext(), dialect, value, type); - }]>, - AttrBuilderWithInferredContext<(ins "Dialect *":$dialect, - "ShapedType":$type, - "StringRef":$value), [{ - MLIRContext *ctxt = dialect->getContext(); - StringAttr dialectName = StringAttr::get(ctxt, dialect->getNamespace()); - return $_get(ctxt, dialectName, value, type); - }]> - ]; - let extraClassDeclaration = [{ - using ValueType = StringRef; - - /// Decodes the attribute value using dialect-specific decoding hook. - /// Returns false if decoding is successful. If not, returns true and leaves - /// 'result' argument unspecified. - bool decode(ElementsAttr &result); - }]; - let genVerifyDecl = 1; - let skipDefaultBuilders = 1; -} - //===----------------------------------------------------------------------===// // SparseElementsAttr //===----------------------------------------------------------------------===// diff --git a/mlir/include/mlir/Interfaces/DecodeAttributesInterfaces.h b/mlir/include/mlir/Interfaces/DecodeAttributesInterfaces.h deleted file mode 100644 --- a/mlir/include/mlir/Interfaces/DecodeAttributesInterfaces.h +++ /dev/null @@ -1,37 +0,0 @@ -//===- DecodeAttributesInterfaces.h - DecodeAttributes Interfaces -*- C++ -*-=// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -#ifndef MLIR_INTERFACES_DECODEATTRIBUTESINTERFACES_H_ -#define MLIR_INTERFACES_DECODEATTRIBUTESINTERFACES_H_ - -#include "mlir/IR/BuiltinAttributes.h" -#include "mlir/IR/DialectInterface.h" -#include "mlir/Support/LogicalResult.h" - -namespace mlir { - -/// Define an interface to decode opaque constant tensor. -class DialectDecodeAttributesInterface - : public DialectInterface::Base { -public: - DialectDecodeAttributesInterface(Dialect *dialect) : Base(dialect) {} - - /// Registered hook to decode opaque constants associated with this - /// dialect. The hook function attempts to decode an opaque constant tensor - /// into a tensor with non-opaque content. If decoding is successful, this - /// method returns success() and sets 'output' attribute. If not, it returns - /// failure() and leaves 'output' unspecified. The default hook fails to - /// decode. - virtual LogicalResult decode(OpaqueElementsAttr input, - ElementsAttr &output) const { - return failure(); - } -}; - -} // namespace mlir - -#endif // MLIR_INTERFACES_DECODEATTRIBUTESINTERFACES_H_ diff --git a/mlir/lib/CAPI/IR/BuiltinAttributes.cpp b/mlir/lib/CAPI/IR/BuiltinAttributes.cpp --- a/mlir/lib/CAPI/IR/BuiltinAttributes.cpp +++ b/mlir/lib/CAPI/IR/BuiltinAttributes.cpp @@ -591,14 +591,6 @@ unwrap(attr).cast().getRawData().data()); } -//===----------------------------------------------------------------------===// -// Opaque elements attribute. -//===----------------------------------------------------------------------===// - -bool mlirAttributeIsAOpaqueElements(MlirAttribute attr) { - return unwrap(attr).isa(); -} - //===----------------------------------------------------------------------===// // Sparse elements attribute. //===----------------------------------------------------------------------===// 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 @@ -1720,19 +1720,6 @@ printKeywordOrString(symbolRef, os); } -// Print out a valid ElementsAttr that is succinct and can represent any -// potential shape/type, for use when eliding a large ElementsAttr. -// -// We choose to use an opaque ElementsAttr literal with conspicuous content to -// hopefully alert readers to the fact that this has been elided. -// -// Unfortunately, neither of the strings of an opaque ElementsAttr literal will -// accept the string "elided". The first string must be a registered dialect -// name and the latter must be a hex constant. -static void printElidedElementsAttr(raw_ostream &os) { - os << R"(opaque<"elided_large_const", "0xDEADBEEF">)"; -} - LogicalResult AsmPrinter::Impl::printAlias(Attribute attr) { return success(state && succeeded(state->getAliasState().getAlias(attr, os))); } @@ -1829,47 +1816,23 @@ printSymbolReference(nestedRef.getValue(), os); } - } else if (auto opaqueAttr = attr.dyn_cast()) { - if (printerFlags.shouldElideElementsAttr(opaqueAttr)) { - printElidedElementsAttr(os); - } else { - os << "opaque<" << opaqueAttr.getDialect() << ", "; - printHexString(opaqueAttr.getValue()); - os << ">"; - } - } else if (auto intOrFpEltAttr = attr.dyn_cast()) { - if (printerFlags.shouldElideElementsAttr(intOrFpEltAttr)) { - printElidedElementsAttr(os); - } else { - os << "dense<"; - printDenseIntOrFPElementsAttr(intOrFpEltAttr, /*allowHex=*/true); - os << '>'; - } - + os << "dense<"; + printDenseIntOrFPElementsAttr(intOrFpEltAttr, /*allowHex=*/true); + os << '>'; } else if (auto strEltAttr = attr.dyn_cast()) { - if (printerFlags.shouldElideElementsAttr(strEltAttr)) { - printElidedElementsAttr(os); - } else { - os << "dense<"; - printDenseStringElementsAttr(strEltAttr); - os << '>'; - } - + os << "dense<"; + printDenseStringElementsAttr(strEltAttr); + os << '>'; } else if (auto sparseEltAttr = attr.dyn_cast()) { - if (printerFlags.shouldElideElementsAttr(sparseEltAttr.getIndices()) || - printerFlags.shouldElideElementsAttr(sparseEltAttr.getValues())) { - printElidedElementsAttr(os); - } else { - os << "sparse<"; - DenseIntElementsAttr indices = sparseEltAttr.getIndices(); - if (indices.getNumElements() != 0) { - printDenseIntOrFPElementsAttr(indices, /*allowHex=*/false); - os << ", "; - printDenseElementsAttr(sparseEltAttr.getValues(), /*allowHex=*/true); - } - os << '>'; + os << "sparse<"; + DenseIntElementsAttr indices = sparseEltAttr.getIndices(); + if (indices.getNumElements() != 0) { + printDenseIntOrFPElementsAttr(indices, /*allowHex=*/false); + os << ", "; + printDenseElementsAttr(sparseEltAttr.getValues(), /*allowHex=*/true); } + os << '>'; } else if (auto denseArrayAttr = attr.dyn_cast()) { typeElision = AttrTypeElision::Must; switch (denseArrayAttr.getElementType()) { @@ -1920,15 +1883,15 @@ static void printDenseElementsAttrImpl(bool isSplat, ShapedType type, raw_ostream &os, function_ref printEltFn) { - // Special case for 0-d and splat tensors. - if (isSplat) - return printEltFn(0); - // Special case for degenerate tensors. - auto numElements = type.getNumElements(); + int64_t numElements = type.getNumElements(); if (numElements == 0) return; + // Special case for 0-d and splat tensors. + if (isSplat) + return printEltFn(0); + // We use a mixed-radix counter to iterate through the shape. When we bump a // non-least-significant digit, we emit a close bracket. When we next emit an // element we re-open all closed brackets. @@ -1980,10 +1943,12 @@ DenseIntOrFPElementsAttr attr, bool allowHex) { auto type = attr.getType(); auto elementType = type.getElementType(); + bool printAsSplat = + attr.isSplat() || printerFlags.shouldElideElementsAttr(attr); // Check to see if we should format this attribute as a hex string. auto numElements = type.getNumElements(); - if (!attr.isSplat() && allowHex && + if (!printAsSplat && allowHex && shouldPrintElementsAttrWithHex(numElements)) { ArrayRef rawData = attr.getRawData(); if (llvm::support::endian::system_endianness() == @@ -2010,7 +1975,7 @@ if (complexElementType.isa()) { bool isSigned = !complexElementType.isUnsignedInteger(); auto valueIt = attr.value_begin>(); - printDenseElementsAttrImpl(attr.isSplat(), type, os, [&](unsigned index) { + printDenseElementsAttrImpl(printAsSplat, type, os, [&](unsigned index) { auto complexValue = *(valueIt + index); os << "("; printDenseIntElement(complexValue.real(), os, isSigned); @@ -2020,7 +1985,7 @@ }); } else { auto valueIt = attr.value_begin>(); - printDenseElementsAttrImpl(attr.isSplat(), type, os, [&](unsigned index) { + printDenseElementsAttrImpl(printAsSplat, type, os, [&](unsigned index) { auto complexValue = *(valueIt + index); os << "("; printFloatValue(complexValue.real(), os); @@ -2032,13 +1997,13 @@ } else if (elementType.isIntOrIndex()) { bool isSigned = !elementType.isUnsignedInteger(); auto valueIt = attr.value_begin(); - printDenseElementsAttrImpl(attr.isSplat(), type, os, [&](unsigned index) { + printDenseElementsAttrImpl(printAsSplat, type, os, [&](unsigned index) { printDenseIntElement(*(valueIt + index), os, isSigned); }); } else { assert(elementType.isa() && "unexpected element type"); auto valueIt = attr.value_begin(); - printDenseElementsAttrImpl(attr.isSplat(), type, os, [&](unsigned index) { + printDenseElementsAttrImpl(printAsSplat, type, os, [&](unsigned index) { printFloatValue(*(valueIt + index), os); }); } @@ -2046,9 +2011,11 @@ void AsmPrinter::Impl::printDenseStringElementsAttr( DenseStringElementsAttr attr) { + bool printAsSplat = + attr.isSplat() || printerFlags.shouldElideElementsAttr(attr); ArrayRef data = attr.getRawStringData(); auto printFn = [&](unsigned index) { printEscapedString(data[index]); }; - printDenseElementsAttrImpl(attr.isSplat(), attr.getType(), os, printFn); + printDenseElementsAttrImpl(printAsSplat, attr.getType(), os, printFn); } void AsmPrinter::Impl::printType(Type type) { diff --git a/mlir/lib/IR/BuiltinAttributes.cpp b/mlir/lib/IR/BuiltinAttributes.cpp --- a/mlir/lib/IR/BuiltinAttributes.cpp +++ b/mlir/lib/IR/BuiltinAttributes.cpp @@ -16,7 +16,6 @@ #include "mlir/IR/Operation.h" #include "mlir/IR/SymbolTable.h" #include "mlir/IR/Types.h" -#include "mlir/Interfaces/DecodeAttributesInterfaces.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/Sequence.h" #include "llvm/Support/Endian.h" @@ -39,8 +38,8 @@ addAttributes(); + IntegerSetAttr, OpaqueAttr, SparseElementsAttr, StringAttr, + TypeAttr, UnitAttr>(); } //===----------------------------------------------------------------------===// @@ -1552,29 +1551,6 @@ attr.getType().cast().getElementType().isIntOrIndex(); } -//===----------------------------------------------------------------------===// -// OpaqueElementsAttr -//===----------------------------------------------------------------------===// - -bool OpaqueElementsAttr::decode(ElementsAttr &result) { - Dialect *dialect = getContext()->getLoadedDialect(getDialect()); - if (!dialect) - return true; - auto *interface = llvm::dyn_cast(dialect); - if (!interface) - return true; - return failed(interface->decode(*this, result)); -} - -LogicalResult -OpaqueElementsAttr::verify(function_ref emitError, - StringAttr dialect, StringRef value, - ShapedType type) { - if (!Dialect::isValidNamespace(dialect.strref())) - return emitError() << "invalid dialect namespace '" << dialect << "'"; - return success(); -} - //===----------------------------------------------------------------------===// // SparseElementsAttr //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Parser/AttributeParser.cpp b/mlir/lib/Parser/AttributeParser.cpp --- a/mlir/lib/Parser/AttributeParser.cpp +++ b/mlir/lib/Parser/AttributeParser.cpp @@ -138,10 +138,6 @@ return locAttr; } - // Parse an opaque elements attribute. - case Token::kw_opaque: - return parseOpaqueElementsAttr(type); - // Parse a sparse elements attribute. case Token::kw_sparse: return parseSparseElementsAttr(type); @@ -243,7 +239,6 @@ case Token::kw_dense: case Token::kw_false: case Token::kw_loc: - case Token::kw_opaque: case Token::kw_sparse: case Token::kw_true: case Token::kw_unit: @@ -928,37 +923,6 @@ return literalParser.getAttr(loc, type); } -/// Parse an opaque elements attribute. -Attribute Parser::parseOpaqueElementsAttr(Type attrType) { - SMLoc loc = getToken().getLoc(); - consumeToken(Token::kw_opaque); - if (parseToken(Token::less, "expected '<' after 'opaque'")) - return nullptr; - - if (getToken().isNot(Token::string)) - return (emitError("expected dialect namespace"), nullptr); - - std::string name = getToken().getStringValue(); - consumeToken(Token::string); - - if (parseToken(Token::comma, "expected ','")) - return nullptr; - - Token hexTok = getToken(); - if (parseToken(Token::string, "elements hex string should start with '0x'") || - parseToken(Token::greater, "expected '>'")) - return nullptr; - auto type = parseElementsLiteralType(attrType); - if (!type) - return nullptr; - - std::string data; - if (parseElementAttrHexValues(*this, hexTok, data)) - return nullptr; - return getChecked(loc, builder.getStringAttr(name), type, - data); -} - /// Shaped type for elements attribute. /// /// elements-literal-type ::= vector-type | ranked-tensor-type diff --git a/mlir/lib/Parser/Parser.h b/mlir/lib/Parser/Parser.h --- a/mlir/lib/Parser/Parser.h +++ b/mlir/lib/Parser/Parser.h @@ -265,9 +265,6 @@ /// or a float attribute. Attribute parseDecOrHexAttr(Type type, bool isNegative); - /// Parse an opaque elements attribute. - Attribute parseOpaqueElementsAttr(Type attrType); - /// Parse a dense elements attribute. Attribute parseDenseElementsAttr(Type attrType); ShapedType parseElementsLiteralType(Type type); diff --git a/mlir/lib/Parser/TokenKinds.def b/mlir/lib/Parser/TokenKinds.def --- a/mlir/lib/Parser/TokenKinds.def +++ b/mlir/lib/Parser/TokenKinds.def @@ -104,7 +104,6 @@ TOK_KEYWORD(mod) TOK_KEYWORD(none) TOK_KEYWORD(offset) -TOK_KEYWORD(opaque) TOK_KEYWORD(size) TOK_KEYWORD(sparse) TOK_KEYWORD(step) diff --git a/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp b/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp --- a/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp +++ b/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp @@ -705,7 +705,7 @@ /// Signal a completion for an attribute. void completeAttribute(const llvm::StringMap &aliases) override { appendSimpleCompletions({"affine_set", "affine_map", "dense", "false", - "loc", "opaque", "sparse", "true", "unit"}, + "loc", "sparse", "true", "unit"}, lsp::CompletionItemKind::Field, /*sortText=*/"1"); diff --git a/mlir/test/CAPI/ir.c b/mlir/test/CAPI/ir.c --- a/mlir/test/CAPI/ir.c +++ b/mlir/test/CAPI/ir.c @@ -466,7 +466,7 @@ mlirOperationPrintWithFlags(operation, flags, printToStderr, NULL); fprintf(stderr, "\n"); // clang-format off - // CHECK: Op print with all flags: %{{.*}} = "arith.constant"() {elts = opaque<"elided_large_const", "0xDEADBEEF"> : tensor<4xi32>, value = 0 : index} : () -> index loc(unknown) + // CHECK: Op print with all flags: %{{.*}} = "arith.constant"() {elts = dense<1> : tensor<4xi32>, value = 0 : index} : () -> index loc(unknown) // clang-format on mlirOpPrintingFlagsDestroy(flags); diff --git a/mlir/test/IR/attribute.mlir b/mlir/test/IR/attribute.mlir --- a/mlir/test/IR/attribute.mlir +++ b/mlir/test/IR/attribute.mlir @@ -691,9 +691,3 @@ } : () -> () return } - -// ----- - -// expected-error @+1 {{invalid dialect namespace '"string with space"'}} -#invalid_dialect = opaque<"string with space", "0xDEADBEEF"> : tensor<100xi32> - diff --git a/mlir/test/IR/elements-attr-interface.mlir b/mlir/test/IR/elements-attr-interface.mlir --- a/mlir/test/IR/elements-attr-interface.mlir +++ b/mlir/test/IR/elements-attr-interface.mlir @@ -20,12 +20,6 @@ // expected-error@below {{Test iterating `IntegerAttr`: 10 : i64, 11 : i64, 12 : i64, 13 : i64, 14 : i64}} arith.constant dense<[10, 11, 12, 13, 14]> : tensor<5xi64> -// expected-error@below {{Test iterating `int64_t`: unable to iterate type}} -// expected-error@below {{Test iterating `uint64_t`: unable to iterate type}} -// expected-error@below {{Test iterating `APInt`: unable to iterate type}} -// expected-error@below {{Test iterating `IntegerAttr`: unable to iterate type}} -arith.constant opaque<"_", "0xDEADBEEF"> : tensor<5xi64> - // Check that we don't crash on empty element attributes. // expected-error@below {{Test iterating `int64_t`: }} // expected-error@below {{Test iterating `uint64_t`: }} diff --git a/mlir/test/IR/invalid.mlir b/mlir/test/IR/invalid.mlir --- a/mlir/test/IR/invalid.mlir +++ b/mlir/test/IR/invalid.mlir @@ -769,27 +769,6 @@ // ----- -func.func @elementsattr_malformed_opaque() -> () { -^bb0: - "foo"(){bar = opaque<10, "0xQZz123"> : tensor<1xi8>} : () -> () // expected-error {{expected dialect namespace}} -} - -// ----- - -func.func @elementsattr_malformed_opaque1() -> () { -^bb0: - "foo"(){bar = opaque<"_", "0xQZz123"> : tensor<1xi8>} : () -> () // expected-error {{expected string containing hex digits starting with `0x`}} -} - -// ----- - -func.func @elementsattr_malformed_opaque2() -> () { -^bb0: - "foo"(){bar = opaque<"_", "00abc"> : tensor<1xi8>} : () -> () // expected-error {{expected string containing hex digits starting with `0x`}} -} - -// ----- - func.func @redundant_signature(%a : i32) -> () { ^bb0(%b : i32): // expected-error {{invalid block name in region with named arguments}} return @@ -871,14 +850,6 @@ // ----- -// Check ill-formed opaque tensor. -func.func @complex_loops() { - affine.for %i1 = 1 to 100 { - // expected-error @+1 {{expected '"' in string literal}} - "opaqueIntTensor"(){bar = opaque<"_", "0x686]> : tensor<2x1x4xi32>} : () -> () - -// ----- - func.func @mi() { // expected-error @+1 {{expected element literal of primitive type}} "fooi64"(){bar = sparse,[,[,1] diff --git a/mlir/test/IR/pretty-attributes.mlir b/mlir/test/IR/pretty-attributes.mlir --- a/mlir/test/IR/pretty-attributes.mlir +++ b/mlir/test/IR/pretty-attributes.mlir @@ -5,17 +5,14 @@ // tensor which passes don't look at directly, this isn't an issue. // RUN: mlir-opt %s -mlir-elide-elementsattrs-if-larger=2 | mlir-opt -// CHECK: opaque<"elided_large_const", "0xDEADBEEF"> : tensor<3xi32> +// CHECK: dense<1> : tensor<3xi32> "test.dense_attr"() {foo.dense_attr = dense<[1, 2, 3]> : tensor<3xi32>} : () -> () // CHECK: dense<[1, 2]> : tensor<2xi32> "test.non_elided_dense_attr"() {foo.dense_attr = dense<[1, 2]> : tensor<2xi32>} : () -> () -// CHECK: opaque<"elided_large_const", "0xDEADBEEF"> : vector<1x1x10xf16> +// CHECK: sparse<0, -2.000000e+00> : vector<1x1x10xf16> "test.sparse_attr"() {foo.sparse_attr = sparse<[[0, 0, 5]], -2.0> : vector<1x1x10xf16>} : () -> () -// CHECK: opaque<"elided_large_const", "0xDEADBEEF"> : tensor<100xf32> -"test.opaque_attr"() {foo.opaque_attr = opaque<"elided_large_const", "0xEBFE"> : tensor<100xf32> } : () -> () - // CHECK: dense<1> : tensor<3xi32> "test.dense_splat"() {foo.dense_attr = dense<1> : tensor<3xi32>} : () -> () diff --git a/mlir/test/python/ir/operation.py b/mlir/test/python/ir/operation.py --- a/mlir/test/python/ir/operation.py +++ b/mlir/test/python/ir/operation.py @@ -567,7 +567,7 @@ module.operation.print(enable_debug_info=True, use_local_scope=True) # Test get_asm with options. - # CHECK: value = opaque<"elided_large_const", "0xDEADBEEF"> : tensor<4xi32> + # CHECK: value = dense<1> : tensor<4xi32> # CHECK: "func.return"(%arg0) : (i32) -> () -:4:7 module.operation.print( large_elements_limit=2, diff --git a/mlir/utils/gdb-scripts/prettyprinters.py b/mlir/utils/gdb-scripts/prettyprinters.py --- a/mlir/utils/gdb-scripts/prettyprinters.py +++ b/mlir/utils/gdb-scripts/prettyprinters.py @@ -161,7 +161,6 @@ 'UnitAttr', 'DenseStringElementsAttr', 'DenseIntOrFPElementsAttr', - 'OpaqueElementsAttr', 'SparseElementsAttr', # mlir/IR/BuiltinTypes.h 'ComplexType',