[Mlir-commits] [llvm] [mlir] [mlir][vector]: Rename VectorOps.cpp convertIntegerAttr to convertNumericAttr and handle float attributes (PR #159627)

Jhalak Patel llvmlistbot at llvm.org
Thu Sep 18 12:04:52 PDT 2025


https://github.com/jhalakpatel created https://github.com/llvm/llvm-project/pull/159627

Issue: https://github.com/llvm/llvm-project/issues/159613

>From 407837f098ac307160b5fe101909d14ed363ad56 Mon Sep 17 00:00:00 2001
From: Jhalak Patel <jhalakp at nvidia.com>
Date: Thu, 18 Sep 2025 12:03:26 -0700
Subject: [PATCH] [mlir][vector]: Rename VectorOps.cpp convertIntegerAttr to
 convertNumericAttr and handle float attributes

---
 float_attr.md                              | 27 +++++++++++++
 mlir/lib/Dialect/Vector/IR/VectorOps.cpp   | 44 ++++++++++++++++------
 mlir/test/Dialect/Vector/canonicalize.mlir | 22 +++++++++++
 3 files changed, 81 insertions(+), 12 deletions(-)
 create mode 100644 float_attr.md

diff --git a/float_attr.md b/float_attr.md
new file mode 100644
index 0000000000000..13b80fc25f1bc
--- /dev/null
+++ b/float_attr.md
@@ -0,0 +1,27 @@
+
+
+Looks like integer to float is not possible for i8 -> float8
+
+# | /home/jhalakp/dev/llvm-project/mlir/test/Dialect/Vector/float_attr.mlir:5:10: error: 'llvm.mlir.constant' op result #0 must be LLVM dialect-compatible type, but got 'f8E4M3FN'
+# |   %cst = llvm.mlir.constant(42 : i8) : f8E4M3FN
+# |          ^
+# | /home/jhalakp/dev/llvm-project/mlir/test/Dialect/Vector/float_attr.mlir:5:10: note: see current operation: %0 = "llvm.mlir.constant"() <{value = 42 : i8}> : () -> f8E4M3FN
+
+
+Even i8 -> f32 is not supported
+
+# .---command stderr------------
+# | /home/jhalakp/dev/llvm-project/mlir/test/Dialect/Vector/float_attr.mlir:5:10: error: 'llvm.mlir.constant' op expected integer type
+# |   %cst = llvm.mlir.constant(42 : i8) : f32
+# |          ^
+# | /home/jhalakp/dev/llvm-project/mlir/test/Dialect/Vector/float_attr.mlir:5:10: note: see current operation: %0 = "llvm.mlir.constant"() <{value = 42 : i8}> : () -> f32
+# `-----------------------------
+
+
+Even f16 -> bf16 is not supported
+# | /home/jhalakp/dev/llvm-project/mlir/test/Dialect/Vector/float_attr.mlir:5:10: error: 'llvm.mlir.constant' op attribute and type have different float semantics
+# |   %cst = llvm.mlir.constant(1.5 : f16) : bf16
+# |          ^
+# | /home/jhalakp/dev/llvm-project/mlir/test/Dialect/Vector/float_attr.mlir:5:10: note: see current operation: %0 = "llvm.mlir.constant"() <{value = 1.500000e+00 : f16}> : () -> bf16
+
+
diff --git a/mlir/lib/Dialect/Vector/IR/VectorOps.cpp b/mlir/lib/Dialect/Vector/IR/VectorOps.cpp
index 8d6e263934fb4..a9aebff75243f 100644
--- a/mlir/lib/Dialect/Vector/IR/VectorOps.cpp
+++ b/mlir/lib/Dialect/Vector/IR/VectorOps.cpp
@@ -396,15 +396,35 @@ std::optional<int64_t> vector::getConstantVscaleMultiplier(Value value) {
   return {};
 }
 
-/// Converts an IntegerAttr to have the specified type if needed.
-/// This handles cases where constant attributes have a different type than the
-/// target element type. If the input attribute is not an IntegerAttr or already
-/// has the correct type, returns it unchanged.
-static Attribute convertIntegerAttr(Attribute attr, Type expectedType) {
-  if (auto intAttr = mlir::dyn_cast<IntegerAttr>(attr)) {
-    if (intAttr.getType() != expectedType)
-      return IntegerAttr::get(expectedType, intAttr.getInt());
+/// Converts numeric attributes to the expected type. Supports integer-to-integer
+/// and float-to-integer conversions. Returns the original attribute if no
+/// conversion is needed or supported.
+static Attribute convertNumericAttr(Attribute attr, Type expectedType) {
+  // Integer-to-integer conversion
+  if (auto intAttr = dyn_cast<IntegerAttr>(attr)) {
+    if (auto intType = dyn_cast<IntegerType>(expectedType)) {
+      if (intAttr.getType() != expectedType)
+        return IntegerAttr::get(expectedType, intAttr.getInt());
+    }
+    return attr;
+  }
+
+  // Float-to-integer conversion  
+  if (auto floatAttr = dyn_cast<FloatAttr>(attr)) {
+    auto intType = dyn_cast<IntegerType>(expectedType);
+    if (!intType)
+      return attr;
+      
+    APFloat floatVal = floatAttr.getValue();
+    APSInt intVal(intType.getWidth(), intType.isUnsigned());
+    bool isExact = false;
+    [[maybe_unused]] APFloat::opStatus status =
+        floatVal.convertToInteger(intVal, APFloat::rmTowardZero, &isExact);
+    assert(status == APFloat::opOK && "float-to-integer conversion failed");
+    assert(isExact && "float-to-integer conversion must be exact");
+    return IntegerAttr::get(expectedType, intVal);
   }
+
   return attr;
 }
 
@@ -2475,7 +2495,7 @@ static OpFoldResult foldFromElementsToConstant(FromElementsOp fromElementsOp,
   // Constant attributes might have a different type than the return type.
   // Convert them before creating the dense elements attribute.
   auto convertedElements = llvm::map_to_vector(elements, [&](Attribute attr) {
-    return convertIntegerAttr(attr, destEltType);
+    return convertNumericAttr(attr, destEltType);
   });
 
   return DenseElementsAttr::get(destVecType, convertedElements);
@@ -3497,13 +3517,13 @@ foldDenseElementsAttrDestInsertOp(InsertOp insertOp, Attribute srcAttr,
   SmallVector<Attribute> insertedValues;
   Type destEltType = destTy.getElementType();
 
-  /// Converts the expected type to an IntegerAttr if there's
+  /// Converts the expected type to a numeric attribute if there's
   /// a mismatch.
   if (auto denseSource = llvm::dyn_cast<DenseElementsAttr>(srcAttr)) {
     for (auto value : denseSource.getValues<Attribute>())
-      insertedValues.push_back(convertIntegerAttr(value, destEltType));
+      insertedValues.push_back(convertNumericAttr(value, destEltType));
   } else {
-    insertedValues.push_back(convertIntegerAttr(srcAttr, destEltType));
+    insertedValues.push_back(convertNumericAttr(srcAttr, destEltType));
   }
 
   auto allValues = llvm::to_vector(denseDst.getValues<Attribute>());
diff --git a/mlir/test/Dialect/Vector/canonicalize.mlir b/mlir/test/Dialect/Vector/canonicalize.mlir
index 05c88b8abfbb0..dcab7088c631a 100644
--- a/mlir/test/Dialect/Vector/canonicalize.mlir
+++ b/mlir/test/Dialect/Vector/canonicalize.mlir
@@ -3375,6 +3375,28 @@ func.func @negative_from_elements_to_constant() -> vector<1x!llvm.ptr> {
   return %b : vector<1x!llvm.ptr>
 }
 
+// -----
+
+// CHECK-LABEL: func @from_elements_float8_to_i8_conversion(
+// CHECK-NEXT:    %[[CST:.*]] = arith.constant dense<0> : vector<1xi8>
+// CHECK-NEXT:    return %[[CST]] : vector<1xi8>
+func.func @from_elements_float8_to_i8_conversion() -> vector<1xi8> {
+  %cst = llvm.mlir.constant(0.0 : f8E4M3FN) : i8
+  %v = vector.from_elements %cst : vector<1xi8>
+  return %v : vector<1xi8>
+}
+
+// -----
+
+// CHECK-LABEL: func @from_elements_i1_to_i8_conversion(
+// CHECK-NEXT:    %[[CST:.*]] = arith.constant dense<0> : vector<1xi8>
+// CHECK-NEXT:    return %[[CST]] : vector<1xi8>
+func.func @from_elements_i1_to_i8_conversion() -> vector<1xi8> {
+  %cst = llvm.mlir.constant(0: i1) : i8
+  %v = vector.from_elements %cst : vector<1xi8>
+  return %v : vector<1xi8>
+}
+
 // +---------------------------------------------------------------------------
 // End of  Tests for foldFromElementsToConstant
 // +---------------------------------------------------------------------------



More information about the Mlir-commits mailing list