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.
//===----------------------------------------------------------------------===//
}
//===----------------------------------------------------------------------===//
-// OpaqueElementsAttr
-//===----------------------------------------------------------------------===//
-
-def Builtin_OpaqueElementsAttr : Builtin_Attr<
- "OpaqueElements", [ElementsAttrInterface, TypedAttrInterface]
- > {
- 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
//===----------------------------------------------------------------------===//
+++ /dev/null
-//===- 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<DialectDecodeAttributesInterface> {
-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_
/// (tensor-type | vector-type)
/// | `sparse` `<` attribute-value `,` attribute-value `>`
/// `:` (tensor-type | vector-type)
-/// | `opaque` `<` dialect-namespace `,` hex-string-literal
-/// `>` `:` (tensor-type | vector-type)
/// | extended-attribute
///
Attribute Parser::parseAttribute(Type type) {
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);
case Token::kw_dense_resource:
case Token::kw_false:
case Token::kw_loc:
- case Token::kw_opaque:
case Token::kw_sparse:
case Token::kw_true:
case Token::kw_unit:
return DenseResourceElementsAttr::get(shapedType, *handle);
}
-/// 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<OpaqueElementsAttr>(loc, builder.getStringAttr(name), type,
- data);
-}
-
/// Shaped type for elements attribute.
///
/// elements-literal-type ::= vector-type | ranked-tensor-type
/// 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);
TOK_KEYWORD(mod)
TOK_KEYWORD(none)
TOK_KEYWORD(offset)
-TOK_KEYWORD(opaque)
TOK_KEYWORD(size)
TOK_KEYWORD(sparse)
TOK_KEYWORD(step)
}
//===----------------------------------------------------------------------===//
-// Opaque elements attribute.
-//===----------------------------------------------------------------------===//
-
-bool mlirAttributeIsAOpaqueElements(MlirAttribute attr) {
- return unwrap(attr).isa<OpaqueElementsAttr>();
-}
-
-//===----------------------------------------------------------------------===//
// Sparse elements attribute.
//===----------------------------------------------------------------------===//
// 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.
+// We choose to use a dense resource ElementsAttr literal with conspicuous
+// content to hopefully alert readers to the fact that this has been elided.
static void printElidedElementsAttr(raw_ostream &os) {
- os << R"(opaque<"elided_large_const", "0xDEADBEEF">)";
+ os << R"(dense_resource<__elided__>)";
}
LogicalResult AsmPrinter::Impl::printAlias(Attribute attr) {
printSymbolReference(nestedRef.getValue(), os);
}
- } else if (auto opaqueAttr = attr.dyn_cast<OpaqueElementsAttr>()) {
- if (printerFlags.shouldElideElementsAttr(opaqueAttr)) {
- printElidedElementsAttr(os);
- } else {
- os << "opaque<" << opaqueAttr.getDialect() << ", ";
- printHexString(opaqueAttr.getValue());
- os << ">";
- }
-
} else if (auto intOrFpEltAttr = attr.dyn_cast<DenseIntOrFPElementsAttr>()) {
if (printerFlags.shouldElideElementsAttr(intOrFpEltAttr)) {
printElidedElementsAttr(os);
#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"
} // namespace mlir
//===----------------------------------------------------------------------===//
-// OpaqueElementsAttr
-//===----------------------------------------------------------------------===//
-
-bool OpaqueElementsAttr::decode(ElementsAttr &result) {
- Dialect *dialect = getContext()->getLoadedDialect(getDialect());
- if (!dialect)
- return true;
- auto *interface = llvm::dyn_cast<DialectDecodeAttributesInterface>(dialect);
- if (!interface)
- return true;
- return failed(interface->decode(*this, result));
-}
-
-LogicalResult
-OpaqueElementsAttr::verify(function_ref<InFlightDiagnostic()> emitError,
- StringAttr dialect, StringRef value,
- ShapedType type) {
- if (!Dialect::isValidNamespace(dialect.strref()))
- return emitError() << "invalid dialect namespace '" << dialect << "'";
- return success();
-}
-
-//===----------------------------------------------------------------------===//
// SparseElementsAttr
//===----------------------------------------------------------------------===//
/// Signal a completion for an attribute.
void completeAttribute(const llvm::StringMap<Attribute> &aliases) override {
appendSimpleCompletions({"affine_set", "affine_map", "dense",
- "dense_resource", "false", "loc", "opaque",
- "sparse", "true", "unit"},
+ "dense_resource", "false", "loc", "sparse", "true",
+ "unit"},
lsp::CompletionItemKind::Field,
/*sortText=*/"1");
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_resource<__elided__> : tensor<4xi32>, value = 0 : index} : () -> index loc(unknown)
// clang-format on
mlirOpPrintingFlagsDestroy(flags);
} : () -> ()
return
}
-
-// -----
-
-// expected-error @+1 {{invalid dialect namespace '"string with space"'}}
-#invalid_dialect = opaque<"string with space", "0xDEADBEEF"> : tensor<100xi32>
-
// 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`: }}
// -----
-func.func @elementsattr_malformed_opaque() -> () {
- "foo"(){bar = opaque<10, "0xQZz123"> : tensor<1xi8>} : () -> () // expected-error {{expected dialect namespace}}
-}
-
-// -----
-
-func.func @elementsattr_malformed_opaque1() -> () {
- "foo"(){bar = opaque<"_", "0xQZz123"> : tensor<1xi8>} : () -> () // expected-error {{expected string containing hex digits starting with `0x`}}
-}
-
-// -----
-
-func.func @elementsattr_malformed_opaque2() -> () {
- "foo"(){bar = opaque<"_", "00abc"> : tensor<1xi8>} : () -> () // expected-error {{expected string containing hex digits starting with `0x`}}
-}
-
-// -----
-
func.func @mi() {
// expected-error @+1 {{expected element literal of primitive type}}
"fooi64"(){bar = sparse<vector<1xi64>,[,[,1]
// 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_resource<__elided__> : 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: dense_resource<__elided__> : 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>} : () -> ()
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_resource<__elided__> : tensor<4xi32>
# CHECK: "func.return"(%arg0) : (i32) -> () -:4:7
module.operation.print(
large_elements_limit=2,
'UnitAttr',
'DenseStringElementsAttr',
'DenseIntOrFPElementsAttr',
- 'OpaqueElementsAttr',
'SparseElementsAttr',
# mlir/IR/BuiltinTypes.h
'ComplexType',