Revert "[mlir][IR] Generalize DenseElementsAttr to custom element types"#181692
Merged
matthias-springer merged 1 commit intoFeb 16, 2026
Conversation
Member
|
@llvm/pr-subscribers-mlir-ods @llvm/pr-subscribers-mlir Author: Matthias Springer (matthias-springer) ChangesReverts llvm/llvm-project#179122. This PR broke the Windows build: https://lab.llvm.org/buildbot/#/builders/207/builds/13576 Patch is 40.76 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/181692.diff 14 Files Affected:
diff --git a/mlir/include/mlir/IR/BuiltinAttributes.td b/mlir/include/mlir/IR/BuiltinAttributes.td
index dced379d1f979..798d3c84f9618 100644
--- a/mlir/include/mlir/IR/BuiltinAttributes.td
+++ b/mlir/include/mlir/IR/BuiltinAttributes.td
@@ -239,48 +239,29 @@ def Builtin_DenseIntOrFPElementsAttr : Builtin_Attr<
"DenseElementsAttr"
> {
let summary = "An Attribute containing a dense multi-dimensional array of "
- "values";
+ "integer or floating-point values";
let description = [{
- A dense elements attribute stores one or multiple elements of the same type.
- The term "dense" refers to the fact that elements are not stored as
- individual MLIR attributes, but in a raw buffer. The attribute provides a
- covenience API to access elements in the form of MLIR attributes, but users
- should avoid that API in performance-critical code and utilize APIs that
- operate on raw bytes instead.
-
- The number of elements is determined by the `type` shaped type. (Unranked
- shaped types are not supported.) The element type of the shaped type must
- implement the `DenseElementType` interface. This type interface defines the
- bitwidth of an element and provides a serializer/deserializer to/from MLIR
- attributes.
-
- Storage format: Given an element bitwidth "w", element "i" starts at byte
- offset "i * ceildiv(w, 8)". In other words, each element starts at a full
- byte offset.
-
- TODO: The name `DenseIntOrFPElements` is no longer accurate. The attribute
- will be renamed in the future.
+ Syntax:
+
+ ```
+ tensor-literal ::= integer-literal | float-literal | bool-literal | [] | [tensor-literal (, tensor-literal)* ]
+ dense-intorfloat-elements-attribute ::= `dense` `<` tensor-literal `>` `:`
+ ( tensor-type | vector-type )
+ ```
+
+ A dense int-or-float elements attribute is an elements attribute containing
+ a densely packed vector or tensor of integer or floating-point values. The
+ element type of this attribute is required to be either an `IntegerType` or
+ a `FloatType`.
Examples:
```
- // Literal-first syntax: A splat tensor of integer values.
+ // A splat tensor of integer values.
dense<10> : tensor<2xi32>
-
- // Literal-first syntax: A tensor of 2 float32 elements.
+ // A tensor of 2 float32 elements.
dense<[10.0, 11.0]> : tensor<2xf32>
-
- // Type-first syntax: A splat tensor of integer values.
- dense<tensor<2xi32> : 10 : i32>
-
- // Type-first syntax: A tensor of 2 float32 elements.
- dense<tensor<2xf32> : [10.0, 11.0]>
```
-
- Note: The literal-first syntax is supported only for complex, float, index,
- int element types. The parser/print have special casing for these types.
- Dense element attributes with other element types must use the type-first
- syntax.
}];
let parameters = (ins AttributeSelfTypeParameter<"", "ShapedType">:$type,
"ArrayRef<char>":$rawData);
diff --git a/mlir/include/mlir/IR/BuiltinTypeInterfaces.h b/mlir/include/mlir/IR/BuiltinTypeInterfaces.h
index 9425d554b427c..5f14517d8dd71 100644
--- a/mlir/include/mlir/IR/BuiltinTypeInterfaces.h
+++ b/mlir/include/mlir/IR/BuiltinTypeInterfaces.h
@@ -19,29 +19,6 @@ struct fltSemantics;
namespace mlir {
class FloatType;
class MLIRContext;
-
-namespace detail {
-/// Float type implementation of
-/// DenseElementTypeInterface::getDenseElementBitSize.
-size_t getFloatTypeDenseElementBitSize(Type type);
-
-/// Float type implementation of DenseElementTypeInterface::convertToAttribute.
-Attribute convertFloatTypeToAttribute(Type type, llvm::ArrayRef<char> rawData);
-
-/// Float type implementation of
-/// DenseElementTypeInterface::convertFromAttribute.
-LogicalResult
-convertFloatTypeFromAttribute(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 93c8c0694b467..9ef08b7020b99 100644
--- a/mlir/include/mlir/IR/BuiltinTypeInterfaces.td
+++ b/mlir/include/mlir/IR/BuiltinTypeInterfaces.td
@@ -41,70 +41,12 @@ 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.
- 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)
- >,
- 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)
- >,
- 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)
- >,
- ];
-}
-
//===----------------------------------------------------------------------===//
// FloatTypeInterface
//===----------------------------------------------------------------------===//
def FloatTypeInterface : TypeInterface<"FloatType",
- [DenseElementTypeInterface, VectorElementTypeInterface]> {
+ [VectorElementTypeInterface]> {
let cppNamespace = "::mlir";
let description = [{
This type interface should be implemented by all floating-point types. It
@@ -141,21 +83,6 @@ def FloatTypeInterface : TypeInterface<"FloatType",
/// The width includes the integer bit.
unsigned getFPMantissaWidth();
}];
-
- let extraTraitClassDeclaration = [{
- /// DenseElementTypeInterface implementations for float types.
- size_t getDenseElementBitSize() const {
- return ::mlir::detail::getFloatTypeDenseElementBitSize($_type);
- }
- ::mlir::Attribute convertToAttribute(::llvm::ArrayRef<char> rawData) const {
- return ::mlir::detail::convertFloatTypeToAttribute($_type, rawData);
- }
- ::llvm::LogicalResult
- convertFromAttribute(::mlir::Attribute attr,
- ::llvm::SmallVectorImpl<char> &result) const {
- return ::mlir::detail::convertFloatTypeFromAttribute($_type, attr, result);
- }
- }];
}
//===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/IR/BuiltinTypes.td b/mlir/include/mlir/IR/BuiltinTypes.td
index e7d0a03a85e7d..806064faeda00 100644
--- a/mlir/include/mlir/IR/BuiltinTypes.td
+++ b/mlir/include/mlir/IR/BuiltinTypes.td
@@ -45,10 +45,7 @@ def ValueSemantics : NativeTypeTrait<"ValueSemantics"> {
// ComplexType
//===----------------------------------------------------------------------===//
-def Builtin_Complex : Builtin_Type<"Complex", "complex",
- [DeclareTypeInterfaceMethods<DenseElementTypeInterface,
- ["getDenseElementBitSize", "convertToAttribute", "convertFromAttribute"]>
- ]> {
+def Builtin_Complex : Builtin_Type<"Complex", "complex"> {
let summary = "Complex number with a parameterized element type";
let description = [{
Syntax:
@@ -563,9 +560,7 @@ def Builtin_Graph : Builtin_FunctionLike<"Graph", "graph">;
//===----------------------------------------------------------------------===//
def Builtin_Index : Builtin_Type<"Index", "index",
- [DeclareTypeInterfaceMethods<DenseElementTypeInterface,
- ["getDenseElementBitSize", "convertToAttribute", "convertFromAttribute"]>,
- VectorElementTypeInterface]> {
+ [VectorElementTypeInterface]> {
let summary = "Integer-like type with unknown platform-dependent bit width";
let description = [{
Syntax:
@@ -596,10 +591,7 @@ def Builtin_Index : Builtin_Type<"Index", "index",
//===----------------------------------------------------------------------===//
def Builtin_Integer : Builtin_Type<"Integer", "integer",
- [VectorElementTypeInterface, QuantStorageTypeInterface,
- DeclareTypeInterfaceMethods<DenseElementTypeInterface, [
- "getDenseElementBitSize", "convertToAttribute",
- "convertFromAttribute"]>]> {
+ [VectorElementTypeInterface, QuantStorageTypeInterface]> {
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 dc9744a42b730..5978a11d06bc9 100644
--- a/mlir/lib/AsmParser/AttributeParser.cpp
+++ b/mlir/lib/AsmParser/AttributeParser.cpp
@@ -16,7 +16,6 @@
#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,119 +953,6 @@ 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) {
- // Skip l_paren because "parseType" would try to parse it as a tuple/function
- // type, but '(' starts a complex literal like in the literal-first syntax.
- if (p.getToken().is(Token::l_paren))
- return Attribute();
-
- // Parse type and valdiate that it's a shaped type.
- auto typeLoc = p.getToken().getLoc();
- Type type;
- OptionalParseResult typeResult = p.parseOptionalType(type);
- if (!typeResult.has_value())
- return Attribute(); // Not type-first syntax.
- if (failed(*typeResult))
- return failure(); // Type parse error.
-
- auto shapedType = dyn_cast<ShapedType>(type);
- if (!shapedType) {
- p.emitError(typeLoc, "expected a shaped type for dense elements");
- return failure();
- }
- if (!shapedType.hasStaticShape()) {
- p.emitError(typeLoc, "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(typeLoc,
- "element type must implement DenseElementTypeInterface "
- "for type-first dense syntax");
- return failure();
- }
-
- // Parse colon.
- if (p.parseToken(Token::colon, "expected ':' after type in dense attribute"))
- return failure();
-
- // Parse the element attributes and convert to raw bytes.
- SmallVector<char> rawData;
-
- // 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();
- };
-
- // Parse elements.
- if (!p.getToken().is(Token::l_square)) {
- // Single element - parse as splat.
- if (parseSingleElement())
- return failure();
- } else if (shapedType.getShape().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(shapedType.getShape()))
- 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();
@@ -1074,16 +960,7 @@ Attribute Parser::parseDenseElementsAttr(Type attrType) {
if (parseToken(Token::less, "expected '<' after 'dense'"))
return nullptr;
- // 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.
+ // Parse the literal data if necessary.
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 b3242f838fc1d..81455699421cc 100644
--- a/mlir/lib/IR/AsmPrinter.cpp
+++ b/mlir/lib/IR/AsmPrinter.cpp
@@ -507,18 +507,11 @@ class AsmPrinter::Impl {
/// Print a dense string elements attribute.
void printDenseStringElementsAttr(DenseStringElementsAttr attr);
- /// 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.
+ /// Print a dense elements attribute. 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);
@@ -2514,17 +2507,7 @@ void AsmPrinter::Impl::printAttributeImpl(Attribute attr,
printElidedElementsAttr(os);
} else {
os << "dense<";
- // 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;
- }
+ printDenseIntOrFPElementsAttr(intOrFpEltAttr, /*allowHex=*/true);
os << '>';
}
@@ -2722,27 +2705,6 @@ 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, static_cast<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 8505149afdd9c..1f268603cf37f 100644
--- a/mlir/lib/IR/AttributeDetail.h
+++ b/mlir/lib/IR/AttributeDetail.h
@@ -16,7 +16,6 @@
#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"
@@ -33,9 +32,12 @@ namespace detail {
/// Return the bit width which DenseElementsAttr should use for this type.
inline size_t getDenseElementBitWidth(Type eltType) {
- if (auto denseEltType = llvm::dyn_cast<DenseElementType>(eltType))
- return denseEltType.getDenseElementBitSize();
- llvm_unreachable("unsupported element type");
+ // 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;
+ return eltType.getIntOrFloatBitWidth();
}
/// An attribute representing a reference to a dense vector or tensor object.
diff --git a/mlir/lib/IR/Builtin...
[truncated]
|
Member
Author
|
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/143/builds/14385 Here is the relevant piece of the build log for the reference |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reverts #179122.
This PR broke the Windows build: https://lab.llvm.org/buildbot/#/builders/207/builds/13576