[Mlir-commits] [mlir] [mlir][IR] Generalize`DenseElementsAttr` to custom element types (PR #179122)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Thu Feb 5 07:15:11 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir

Author: Matthias Springer (matthias-springer)

<details>
<summary>Changes</summary>

`DenseElementsAttr` supports only a hard-coded list of element types: `int`, `index`, `float`, `complex`. This commit generalizes the `DenseElementsAttr` infrastructure: it now supports arbitrary element types, as long as they implement the new `DenseElementTypeInterface`.

The `DenseElementTypeInterface` has the following helper functions:
- `getDenseElementBitSize`: Query the size of an element in bits. (When storing an element in memory, each element is padded to a full byte. This is an existing limitation of the `DenseElementsAttr`; with an exception for `i1`.)
- `convertToAttribute`: Attribute factory / deserializer. Converts bytes into an MLIR attribute. The attribute provides the assembly format / printer for a single element.
- `convertFromAttribute`: Serializer. Converts an MLIR attribute into bytes.

Note: `convertToAttribute` / `convertFromAttribute` are mainly for writing test cases. For performance reasons, `DenseElementsAttr` users should work with raw bytes / elements and avoid any API that materializes MLIR attributes. However, MLIR attributes typically have human-readable parsers/printers, making them suitable for lit tests and debugging.

This PR introduces an additional assembly format for `DenseElementsAttrs`. There are now two formats. (The existing one is kept for compatibility reasons.)
- Literal-first (existing): `dense<[1, 2, 3]> : tensor<3xi32>`
- Type-first (new): `dense<tensor<3xi32> : [1 : i32, 2 : i32, 3 : i32]>`

The new syntax is needed because we have to know the number of elements that we are about to parse. (Note: We could avoid the new syntax if we could assume that the assembly format of an element attribute does not start with `[`.)

The existing `int`, `index`, `float`, `complex` types also implement the `DenseElementTypeInterface`. This allows us to implement `DenseElementsAttr::get` and `AttributeElementIterator::operator*` in a generic way.

RFC: https://discourse.llvm.org/t/rfc-allow-custom-element-types-in-denseelementattr/89656


---

Patch is 40.03 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/179122.diff


13 Files Affected:

- (modified) mlir/include/mlir/IR/BuiltinTypeInterfaces.h (+20) 
- (modified) mlir/include/mlir/IR/BuiltinTypeInterfaces.td (+72-1) 
- (modified) mlir/include/mlir/IR/BuiltinTypes.td (+10-3) 
- (modified) mlir/lib/AsmParser/AttributeParser.cpp (+146-1) 
- (modified) mlir/lib/IR/AsmPrinter.cpp (+41-3) 
- (modified) mlir/lib/IR/AttributeDetail.h (+7-5) 
- (modified) mlir/lib/IR/BuiltinAttributes.cpp (+38-92) 
- (modified) mlir/lib/IR/BuiltinTypeInterfaces.cpp (+50) 
- (modified) mlir/lib/IR/BuiltinTypes.cpp (+122) 
- (added) mlir/test/IR/dense-elements-type-interface.mlir (+37) 
- (modified) mlir/test/lib/Dialect/Test/TestTypeDefs.td (+12) 
- (modified) mlir/test/lib/Dialect/Test/TestTypes.cpp (+28) 
- (modified) mlir/test/lib/Dialect/Test/TestTypes.h (+1) 


``````````diff
diff --git a/mlir/include/mlir/IR/BuiltinTypeInterfaces.h b/mlir/include/mlir/IR/BuiltinTypeInterfaces.h
index 5f14517d8dd71..c6e6e86d64b9c 100644
--- a/mlir/include/mlir/IR/BuiltinTypeInterfaces.h
+++ b/mlir/include/mlir/IR/BuiltinTypeInterfaces.h
@@ -19,6 +19,26 @@ struct fltSemantics;
 namespace mlir {
 class FloatType;
 class MLIRContext;
+
+namespace detail {
+/// Default implementation of DenseElementTypeInterface::getDenseElementBitSize.
+size_t getDefaultDenseElementBitSize(Type type);
+
+/// Default implementation of DenseElementTypeInterface::convertToAttribute.
+Attribute defaultConvertToAttribute(Type type, llvm::ArrayRef<char> rawData);
+
+/// Default implementation of DenseElementTypeInterface::convertFromAttribute.
+LogicalResult defaultConvertFromAttribute(Type type, Attribute attr,
+                                          llvm::SmallVectorImpl<char> &result);
+
+/// Read `bitWidth` bits from byte-aligned position in `rawData` and return as
+/// an APInt. Handles endianness correctly.
+llvm::APInt readBits(const char *rawData, size_t bitPos, size_t bitWidth);
+
+/// Write `value` to byte-aligned position `bitPos` in `rawData`. Handles
+/// endianness correctly.
+void writeBits(char *rawData, size_t bitPos, llvm::APInt value);
+} // namespace detail
 } // namespace mlir
 
 #include "mlir/IR/BuiltinTypeInterfaces.h.inc"
diff --git a/mlir/include/mlir/IR/BuiltinTypeInterfaces.td b/mlir/include/mlir/IR/BuiltinTypeInterfaces.td
index 9ef08b7020b99..6463f62b1923b 100644
--- a/mlir/include/mlir/IR/BuiltinTypeInterfaces.td
+++ b/mlir/include/mlir/IR/BuiltinTypeInterfaces.td
@@ -41,12 +41,83 @@ def VectorElementTypeInterface : TypeInterface<"VectorElementTypeInterface"> {
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// DenseElementTypeInterface
+//===----------------------------------------------------------------------===//
+
+def DenseElementTypeInterface : TypeInterface<"DenseElementType"> {
+  let cppNamespace = "::mlir";
+  let description = [{
+    This interface allows custom types to be used as element types in
+    DenseElementsAttr. Types implementing this interface define:
+
+    1. The bit size for element storage. Only full byte sizes are supported
+       at the moment.
+    2. Helper methods for converting from/to Attribute. This assumes that there
+       is a corresponding attribute for each type that implements this
+       interface.
+
+    The helper methods for converting from/to Attribute are utilized when
+    parsing/printing IR or iterating over the elements via Attribute.
+  }];
+
+  let methods = [
+    InterfaceMethod<
+      /*desc=*/[{
+        Return the number of bits required to store one element in dense
+        storage.
+        
+        Note: The DenseElementsAttr infrastructure will automatically align
+        every element to a full byte in storage. This limitation could be lifted
+        in the future to support dense packing of non-byte-sized elements.
+      }],
+      /*retTy=*/"size_t",
+      /*methodName=*/"getDenseElementBitSize",
+      /*args=*/(ins),
+      /*methodBody=*/"",
+      /*defaultImplementation=*/[{
+        return ::mlir::detail::getDefaultDenseElementBitSize($_type);
+      }]
+    >,
+    InterfaceMethod<
+      /*desc=*/[{
+        Attribute deserialization / attribute factory: Convert raw storage bytes
+        into an MLIR attribute. The size of `rawData` is
+        "ceilDiv(getDenseElementBitSize(), 8)".
+      }],
+      /*retTy=*/"::mlir::Attribute",
+      /*methodName=*/"convertToAttribute",
+      /*args=*/(ins "::llvm::ArrayRef<char>":$rawData),
+      /*methodBody=*/"",
+      /*defaultImplementation=*/[{
+        return ::mlir::detail::defaultConvertToAttribute($_type, rawData);
+      }]
+    >,
+    InterfaceMethod<
+      /*desc=*/[{
+        Attribute serialization: Convert an MLIR attribute into raw bytes.
+        Implementations must append "getDenseElementBitSize() / 8" values to
+        `result`. Return "failure" if the attribute is incompatible with this
+        element type.
+      }],
+      /*retTy=*/"::llvm::LogicalResult",
+      /*methodName=*/"convertFromAttribute",
+      /*args=*/(ins "::mlir::Attribute":$attr,
+                    "::llvm::SmallVectorImpl<char>&":$result),
+      /*methodBody=*/"",
+      /*defaultImplementation=*/[{
+        return ::mlir::detail::defaultConvertFromAttribute($_type, attr, result);
+      }]
+    >,
+  ];
+}
+
 //===----------------------------------------------------------------------===//
 // FloatTypeInterface
 //===----------------------------------------------------------------------===//
 
 def FloatTypeInterface : TypeInterface<"FloatType",
-    [VectorElementTypeInterface]> {
+    [DenseElementTypeInterface, VectorElementTypeInterface]> {
   let cppNamespace = "::mlir";
   let description = [{
     This type interface should be implemented by all floating-point types. It
diff --git a/mlir/include/mlir/IR/BuiltinTypes.td b/mlir/include/mlir/IR/BuiltinTypes.td
index 08847dd11c685..e671f96f2d0f3 100644
--- a/mlir/include/mlir/IR/BuiltinTypes.td
+++ b/mlir/include/mlir/IR/BuiltinTypes.td
@@ -44,7 +44,10 @@ def ValueSemantics : NativeTypeTrait<"ValueSemantics"> {
 // ComplexType
 //===----------------------------------------------------------------------===//
 
-def Builtin_Complex : Builtin_Type<"Complex", "complex"> {
+def Builtin_Complex : Builtin_Type<"Complex", "complex",
+    [DeclareTypeInterfaceMethods<DenseElementTypeInterface,
+      ["getDenseElementBitSize", "convertToAttribute", "convertFromAttribute"]>
+    ]> {
   let summary = "Complex number with a parameterized element type";
   let description = [{
     Syntax:
@@ -470,7 +473,9 @@ def Builtin_Graph : Builtin_FunctionLike<"Graph", "graph">;
 //===----------------------------------------------------------------------===//
 
 def Builtin_Index : Builtin_Type<"Index", "index",
-    [VectorElementTypeInterface]> {
+    [DeclareTypeInterfaceMethods<DenseElementTypeInterface,
+      ["getDenseElementBitSize", "convertToAttribute", "convertFromAttribute"]>,
+     VectorElementTypeInterface]> {
   let summary = "Integer-like type with unknown platform-dependent bit width";
   let description = [{
     Syntax:
@@ -501,7 +506,9 @@ def Builtin_Index : Builtin_Type<"Index", "index",
 //===----------------------------------------------------------------------===//
 
 def Builtin_Integer : Builtin_Type<"Integer", "integer",
-    [VectorElementTypeInterface]> {
+    [DeclareTypeInterfaceMethods<DenseElementTypeInterface,
+      ["getDenseElementBitSize", "convertToAttribute", "convertFromAttribute"]>,
+     VectorElementTypeInterface]> {
   let summary = "Integer type with arbitrary precision up to a fixed limit";
   let description = [{
     Syntax:
diff --git a/mlir/lib/AsmParser/AttributeParser.cpp b/mlir/lib/AsmParser/AttributeParser.cpp
index 519609a38be6e..81cafb45abff2 100644
--- a/mlir/lib/AsmParser/AttributeParser.cpp
+++ b/mlir/lib/AsmParser/AttributeParser.cpp
@@ -16,6 +16,7 @@
 #include "mlir/IR/AffineMap.h"
 #include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/IR/BuiltinDialect.h"
+#include "mlir/IR/BuiltinTypeInterfaces.h"
 #include "mlir/IR/BuiltinTypes.h"
 #include "mlir/IR/DialectResourceBlobManager.h"
 #include "mlir/IR/IntegerSet.h"
@@ -954,6 +955,141 @@ Attribute Parser::parseDenseArrayAttr(Type attrType) {
   return eltParser.getAttr();
 }
 
+/// Try to parse a dense elements attribute with the type-first syntax.
+/// Syntax: dense<TYPE : [ATTR, ATTR, ...]>
+/// This syntax is used for types other than int, float, index and complex.
+///
+/// Returns:
+///   - "null" attribute if this is not the type-first syntax.
+///   - "failure" in case of a parse error.
+///   - A valid Attribute otherwise.
+static FailureOr<Attribute> parseDenseElementsAttrTyped(Parser &p, SMLoc loc) {
+  // Try to parse an optional type. Skip l_paren because parseOptionalType
+  // would try to parse it as a tuple/function type, but '(' starts a complex
+  // literal like (0, 1) in dense syntax.
+  Type type;
+  OptionalParseResult typeResult = p.getToken().is(Token::l_paren)
+                                       ? OptionalParseResult(std::nullopt)
+                                       : p.parseOptionalType(type);
+  if (!typeResult.has_value())
+    return Attribute(); // Not type-first syntax.
+
+  if (failed(*typeResult))
+    return failure(); // Type parse error.
+
+  // We parsed a type. Check for ':' to confirm type-first syntax.
+  if (!p.getToken().is(Token::colon)) {
+    p.emitError(loc, "expected ':' after type in dense attribute");
+    return failure();
+  }
+
+  // Validate the type.
+  auto shapedType = dyn_cast<ShapedType>(type);
+  if (!shapedType) {
+    p.emitError(loc, "expected a shaped type for dense elements");
+    return failure();
+  }
+
+  if (!shapedType.hasStaticShape()) {
+    p.emitError(loc, "dense elements type must have static shape");
+    return failure();
+  }
+
+  // Check that the element type implements DenseElementTypeInterface.
+  auto denseEltType = dyn_cast<DenseElementType>(shapedType.getElementType());
+  if (!denseEltType) {
+    p.emitError(loc, "element type must implement DenseElementTypeInterface "
+                     "for type-first dense syntax");
+    return failure();
+  }
+
+  // Consume the ':' that separates the type from the element list.
+  p.consumeToken(Token::colon);
+
+  ArrayRef<int64_t> shape = shapedType.getShape();
+
+  // Parse the element attributes and convert to raw bytes.
+  SmallVector<char> rawData;
+  // Storage is byte-aligned: align bit size up to next byte boundary. This
+  // limitation could be lifted in the future to support dense packing of
+  // non-byte-sized elements.
+  size_t bitSize = denseEltType.getDenseElementBitSize();
+  size_t byteSize = llvm::divideCeil(bitSize, static_cast<size_t>(CHAR_BIT));
+
+  // Helper to parse a single element.
+  auto parseSingleElement = [&]() -> ParseResult {
+    Attribute elemAttr = p.parseAttribute();
+    if (!elemAttr)
+      return failure();
+    if (failed(denseEltType.convertFromAttribute(elemAttr, rawData))) {
+      p.emitError("incompatible attribute for element type");
+      return failure();
+    }
+    return success();
+  };
+
+  // Recursively parse elements matching the expected shape.
+  std::function<ParseResult(ArrayRef<int64_t>)> parseElements;
+  parseElements = [&](ArrayRef<int64_t> remainingShape) -> ParseResult {
+    // Leaf: parse a single element.
+    if (remainingShape.empty())
+      return parseSingleElement();
+
+    // Non-leaf: expect a list with the correct number of elements.
+    int64_t expectedCount = remainingShape.front();
+    ArrayRef<int64_t> innerShape = remainingShape.drop_front();
+    int64_t actualCount = 0;
+
+    auto parseOne = [&]() -> ParseResult {
+      if (parseElements(innerShape))
+        return failure();
+      ++actualCount;
+      return success();
+    };
+
+    if (p.parseCommaSeparatedList(Parser::Delimiter::Square, parseOne))
+      return failure();
+
+    if (actualCount != expectedCount) {
+      p.emitError() << "expected " << expectedCount
+                    << " elements in dimension, got " << actualCount;
+      return failure();
+    }
+    return success();
+  };
+
+  // Check for splat (single element for the whole tensor).
+  bool isSplat = false;
+  if (!p.getToken().is(Token::l_square)) {
+    // Single element - parse as splat.
+    if (parseSingleElement())
+      return failure();
+    isSplat = shapedType.getNumElements() != 1;
+  } else if (shape.empty()) {
+    // Scalar type shouldn't have a list.
+    p.emitError(loc, "expected single element for scalar type, got list");
+    return failure();
+  } else {
+    // Parse structured literal matching the shape.
+    if (parseElements(shape))
+      return failure();
+  }
+
+  // Verify element count (should match unless it's a splat).
+  int64_t numElements = shapedType.getNumElements();
+  if (!isSplat && rawData.size() != byteSize * numElements) {
+    p.emitError(loc) << "parsed " << (rawData.size() / byteSize)
+                     << " elements, but type expects " << numElements;
+    return failure();
+  }
+
+  if (p.parseToken(Token::greater, "expected '>' to close dense attribute"))
+    return failure();
+
+  // Create the attribute from raw buffer.
+  return DenseElementsAttr::getFromRawBuffer(shapedType, rawData);
+}
+
 /// Parse a dense elements attribute.
 Attribute Parser::parseDenseElementsAttr(Type attrType) {
   auto attribLoc = getToken().getLoc();
@@ -961,7 +1097,16 @@ Attribute Parser::parseDenseElementsAttr(Type attrType) {
   if (parseToken(Token::less, "expected '<' after 'dense'"))
     return nullptr;
 
-  // Parse the literal data if necessary.
+  // Try to parse the type-first syntax: dense<TYPE : [ATTR, ...]>
+  FailureOr<Attribute> typedResult =
+      parseDenseElementsAttrTyped(*this, attribLoc);
+  if (failed(typedResult))
+    return nullptr;
+  if (*typedResult)
+    return *typedResult;
+
+  // Try to parse the literal-first syntax, which is the default format for
+  // int, float, index and complex element types.
   TensorLiteralParser literalParser(*this);
   if (!consumeIf(Token::greater)) {
     if (literalParser.parse(/*allowHex=*/true) ||
diff --git a/mlir/lib/IR/AsmPrinter.cpp b/mlir/lib/IR/AsmPrinter.cpp
index 81455699421cc..b4f5a2b0ff67b 100644
--- a/mlir/lib/IR/AsmPrinter.cpp
+++ b/mlir/lib/IR/AsmPrinter.cpp
@@ -507,11 +507,18 @@ class AsmPrinter::Impl {
   /// Print a dense string elements attribute.
   void printDenseStringElementsAttr(DenseStringElementsAttr attr);
 
-  /// Print a dense elements attribute. If 'allowHex' is true, a hex string is
-  /// used instead of individual elements when the elements attr is large.
+  /// Print a dense elements attribute in the literal-first syntax. If
+  /// 'allowHex' is true, a hex string is used instead of individual elements
+  /// when the elements attr is large.
   void printDenseIntOrFPElementsAttr(DenseIntOrFPElementsAttr attr,
                                      bool allowHex);
 
+  /// Print a dense elements attribute using the type-first syntax and the
+  /// DenseElementTypeInterface, which provides the attribute printer for each
+  /// element.
+  void printTypeFirstDenseElementsAttr(DenseElementsAttr attr,
+                                       DenseElementType denseEltType);
+
   /// Print a dense array attribute.
   void printDenseArrayAttr(DenseArrayAttr attr);
 
@@ -2507,7 +2514,17 @@ void AsmPrinter::Impl::printAttributeImpl(Attribute attr,
       printElidedElementsAttr(os);
     } else {
       os << "dense<";
-      printDenseIntOrFPElementsAttr(intOrFpEltAttr, /*allowHex=*/true);
+      // Check if the element type implements DenseElementTypeInterface and is
+      // not a built-in type. Built-in types (int, float, index, complex) use
+      // the existing printing format for backwards compatibility.
+      Type eltType = intOrFpEltAttr.getElementType();
+      if (isa<FloatType, IntegerType, IndexType, ComplexType>(eltType)) {
+        printDenseIntOrFPElementsAttr(intOrFpEltAttr, /*allowHex=*/true);
+      } else {
+        printTypeFirstDenseElementsAttr(intOrFpEltAttr,
+                                        cast<DenseElementType>(eltType));
+        typeElision = AttrTypeElision::Must;
+      }
       os << '>';
     }
 
@@ -2705,6 +2722,27 @@ void AsmPrinter::Impl::printDenseStringElementsAttr(
   printDenseElementsAttrImpl(attr.isSplat(), attr.getType(), os, printFn);
 }
 
+void AsmPrinter::Impl::printTypeFirstDenseElementsAttr(
+    DenseElementsAttr attr, DenseElementType denseEltType) {
+  // Print the type first: dense<TYPE : [ELEMENTS]>
+  printType(attr.getType());
+  os << " : ";
+
+  ArrayRef<char> rawData = attr.getRawData();
+  // Storage is byte-aligned: align bit size up to next byte boundary.
+  size_t bitSize = denseEltType.getDenseElementBitSize();
+  size_t byteSize = llvm::divideCeil(bitSize, (size_t)CHAR_BIT);
+
+  // Print elements: convert raw bytes to attribute, then print attribute.
+  printDenseElementsAttrImpl(
+      attr.isSplat(), attr.getType(), os, [&](unsigned index) {
+        size_t offset = attr.isSplat() ? 0 : index * byteSize;
+        ArrayRef<char> elemData = rawData.slice(offset, byteSize);
+        Attribute elemAttr = denseEltType.convertToAttribute(elemData);
+        printAttributeImpl(elemAttr);
+      });
+}
+
 void AsmPrinter::Impl::printDenseArrayAttr(DenseArrayAttr attr) {
   Type type = attr.getElementType();
   unsigned bitwidth = type.isInteger(1) ? 8 : type.getIntOrFloatBitWidth();
diff --git a/mlir/lib/IR/AttributeDetail.h b/mlir/lib/IR/AttributeDetail.h
index cb9d21bf3e611..b6b3a0551079d 100644
--- a/mlir/lib/IR/AttributeDetail.h
+++ b/mlir/lib/IR/AttributeDetail.h
@@ -16,6 +16,7 @@
 #include "mlir/IR/AffineMap.h"
 #include "mlir/IR/AttributeSupport.h"
 #include "mlir/IR/BuiltinAttributes.h"
+#include "mlir/IR/BuiltinTypeInterfaces.h"
 #include "mlir/IR/BuiltinTypes.h"
 #include "mlir/IR/IntegerSet.h"
 #include "mlir/IR/MLIRContext.h"
@@ -32,11 +33,12 @@ namespace detail {
 
 /// Return the bit width which DenseElementsAttr should use for this type.
 inline size_t getDenseElementBitWidth(Type eltType) {
-  // Align the width for complex to 8 to make storage and interpretation easier.
-  if (ComplexType comp = llvm::dyn_cast<ComplexType>(eltType))
-    return llvm::alignTo<8>(getDenseElementBitWidth(comp.getElementType())) * 2;
-  if (eltType.isIndex())
-    return IndexType::kInternalStorageBitWidth;
+  // i1 is stored as a single bit (bit-packed storage).
+  if (eltType.isInteger(1))
+    return 1;
+  // Check for DenseElementTypeInterface.
+  if (auto denseEltType = llvm::dyn_cast<DenseElementType>(eltType))
+    return denseEltType.getDenseElementBitSize();
   return eltType.getIntOrFloatBitWidth();
 }
 
diff --git a/mlir/lib/IR/BuiltinAttributes.cpp b/mlir/lib/IR/BuiltinAttributes.cpp
index 6f880f810d651..d9c5fd9acb811 100644
--- a/mlir/lib/IR/BuiltinAttributes.cpp
+++ b/mlir/lib/IR/BuiltinAttributes.cpp
@@ -10,6 +10,7 @@
 #include "AttributeDetail.h"
 #include "mlir/IR/AffineMap.h"
 #include "mlir/IR/BuiltinDialect.h"
+#include "mlir/IR/BuiltinTypeInterfaces.h"
 #include "mlir/IR/Dialect.h"
 #include "mlir/IR/DialectResourceBlobManager.h"
 #include "mlir/IR/IntegerSet.h"
@@ -543,7 +544,7 @@ static void copyArrayToAPIntForBEmachine(const char *inArray, size_t numBytes,
 }
 
 /// Writes value to the bit position `bitPos` in array `rawData`.
-static void writeBits(char *rawData, size_t bitPos, APInt value) {
+void mlir::detail::writeBits(char *rawData, size_t bitPos, APInt value) {
   size_t bitWidth = value.getBitWidth();
 
   // If the bitwidth is 1 we just toggle the specific bit.
@@ -569,7 +570,8 @@ static void writeBits(char *rawData, size_t bitPos, APInt value) {
 
 /// Reads the next `bitWidth` bits from the bit position `bitPos` in array
 /// `rawData`.
-static APInt readBits(const char *rawData, size_t bitPos, size_t bitWidth) {
+APInt mlir::detail::readBits(const char *rawData, size_t bitPos,
+                             size_t bitWidth) {
   // Handle a boolean bit position.
   if (bitWidth == 1)
     return APInt(1, getBit(rawData, bitPos) ? 1 : 0);
@@ -619,39 +621,27 @@ DenseElementsAttr::AttributeElementIterator::AttributeElementIterator(
 Attribute DenseElementsAttr::AttributeElementIterator::operator*() const {
   auto owner = llvm::cast<DenseElementsAttr>(getFromOpaquePointer(base));
   Type eltTy = owner.getElementType();
-  if (llvm::dyn_cast<IntegerType>(eltTy))
-    return IntegerAttr::get(eltTy, *IntElementIterator(owner, index));
-  if (llvm::isa<IndexType>(eltTy))
-    return IntegerAttr::get(eltTy, *IntElementIterator(owner, index));
-  if (auto floatEltTy = llvm::dyn_cast<FloatType>(eltTy)) {
-    IntElementIterator intIt(owner, index);
-    FloatElementIterator floatIt(floatEltTy.getFloatSemantics(), intIt);
-    return FloatAttr::get(eltTy, *floatIt);
-  }
-  if (auto complexTy = llvm::dyn_cast<ComplexType>(eltTy)) {
-    auto complexEltTy = complexTy.getElementType();
-    ComplexIntElementIterator complexIntIt(owner, index);
-    if (llvm::isa<IntegerType>(complexEltTy)) {
-      auto value = *complexIntIt;
-      auto real = IntegerAttr::get(complexEltTy, value.real());
-      auto imag = IntegerAttr::get(complexEltTy, value.imag());
-      return ArrayAttr::get(comp...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/179122


More information about the Mlir-commits mailing list