[Mlir-commits] [mlir] 4053765 - [mlir][tosa] Add support for dense_resource in tosa-narrow-* passes (#182032)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Thu Feb 19 01:28:38 PST 2026


Author: Thibaut Goetghebuer-Planchon
Date: 2026-02-19T09:28:33Z
New Revision: 4053765e4290266ec640c13dcd2920c3bab96f72

URL: https://github.com/llvm/llvm-project/commit/4053765e4290266ec640c13dcd2920c3bab96f72
DIFF: https://github.com/llvm/llvm-project/commit/4053765e4290266ec640c13dcd2920c3bab96f72.diff

LOG: [mlir][tosa] Add support for dense_resource in tosa-narrow-* passes (#182032)

Add support for `dense_resource` in `tosa-narrow-f64-to-f32` and
`tosa-narrow-i64-to-i32` passes.

Added: 
    

Modified: 
    mlir/include/mlir/Dialect/Tosa/Utils/ConversionUtils.h
    mlir/lib/Dialect/Tosa/Transforms/TosaFolders.cpp
    mlir/lib/Dialect/Tosa/Transforms/TosaNarrowTypes.cpp
    mlir/test/Dialect/Tosa/tosa-narrow-f64-to-f32-aggressive.mlir
    mlir/test/Dialect/Tosa/tosa-narrow-f64-to-f32.mlir
    mlir/test/Dialect/Tosa/tosa-narrow-i64-to-i32-aggressive.mlir
    mlir/test/Dialect/Tosa/tosa-narrow-i64-to-i32.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/Tosa/Utils/ConversionUtils.h b/mlir/include/mlir/Dialect/Tosa/Utils/ConversionUtils.h
index cdcd099ec7d22..3a48608e7fd94 100644
--- a/mlir/include/mlir/Dialect/Tosa/Utils/ConversionUtils.h
+++ b/mlir/include/mlir/Dialect/Tosa/Utils/ConversionUtils.h
@@ -17,6 +17,7 @@
 #include "mlir/Dialect/Tensor/IR/Tensor.h"
 #include "mlir/Dialect/Tosa/Utils/ShapeUtils.h"
 #include "mlir/Dialect/Utils/StructuredOpsUtils.h"
+#include "mlir/IR/DialectResourceBlobManager.h"
 #include "mlir/IR/ImplicitLocOpBuilder.h"
 #include "mlir/IR/PatternMatch.h"
 #include <optional>
@@ -248,6 +249,28 @@ SmallVector<int64_t> convertFromIntAttr(const DenseElementsAttr &attr,
 // per batch
 bool hasUniqueConstantScatterIndices(ShapedType indicesType,
                                      DenseIntElementsAttr indicesAttr);
+
+// Try to get the values of a DenseResourceElementsAttr construct
+template <typename T>
+std::optional<ArrayRef<T>> tryGetDenseResourceValues(ElementsAttr attr) {
+  if (auto denseResource = dyn_cast<DenseResourceElementsAttr>(attr)) {
+    // Check that the resource memory blob exists
+    AsmResourceBlob *blob = denseResource.getRawHandle().getBlob();
+    if (!blob)
+      return std::nullopt;
+
+    // Check that the data are in a valid form
+    if (!DenseElementsAttr::isValidRawBuffer(attr.getShapedType(),
+                                             blob->getData())) {
+      return std::nullopt;
+    }
+
+    return blob->template getDataAs<T>();
+  }
+
+  return std::nullopt;
+}
+
 } // namespace tosa
 } // namespace mlir
 

diff  --git a/mlir/lib/Dialect/Tosa/Transforms/TosaFolders.cpp b/mlir/lib/Dialect/Tosa/Transforms/TosaFolders.cpp
index f01a87afaa2aa..0a035bbd3df00 100644
--- a/mlir/lib/Dialect/Tosa/Transforms/TosaFolders.cpp
+++ b/mlir/lib/Dialect/Tosa/Transforms/TosaFolders.cpp
@@ -15,10 +15,10 @@
 
 #include "mlir/Dialect/Tosa/IR/TosaOps.h"
 #include "mlir/Dialect/Tosa/Transforms/Passes.h"
+#include "mlir/Dialect/Tosa/Utils/ConversionUtils.h"
 #include "mlir/Dialect/Utils/IndexingUtils.h"
 #include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/IR/BuiltinTypes.h"
-#include "mlir/IR/DialectResourceBlobManager.h"
 #include "mlir/IR/Matchers.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
@@ -175,27 +175,6 @@ DenseElementsAttr transposeType(const RangeType &data, ShapedType inputType,
                                 llvm::ArrayRef<ElementType>(outputValues));
 }
 
-// Try to get the values of a DenseResourceElementsAttr construct
-template <typename T>
-std::optional<ArrayRef<T>> tryGetDenseResourceValues(ElementsAttr attr) {
-  if (auto denseResource = dyn_cast<DenseResourceElementsAttr>(attr)) {
-    // Check that the resource memory blob exists
-    AsmResourceBlob *blob = denseResource.getRawHandle().getBlob();
-    if (!blob)
-      return std::nullopt;
-
-    // Check that the data are in a valid form
-    if (!DenseElementsAttr::isValidRawBuffer(attr.getShapedType(),
-                                             blob->getData())) {
-      return std::nullopt;
-    }
-
-    return blob->template getDataAs<T>();
-  }
-
-  return std::nullopt;
-}
-
 // A type specialized transposition of an ElementsAttr.
 // This implementation tries to operate on the underlying data in its raw
 // representation when possible to avoid allocating a large number of Attribute

diff  --git a/mlir/lib/Dialect/Tosa/Transforms/TosaNarrowTypes.cpp b/mlir/lib/Dialect/Tosa/Transforms/TosaNarrowTypes.cpp
index d9651f7321269..983472762e791 100644
--- a/mlir/lib/Dialect/Tosa/Transforms/TosaNarrowTypes.cpp
+++ b/mlir/lib/Dialect/Tosa/Transforms/TosaNarrowTypes.cpp
@@ -15,12 +15,16 @@
 
 #include "llvm/ADT/APFloat.h"
 
+#include <algorithm>
 #include <limits>
 #include <type_traits>
 
 #include "mlir/Dialect/Func/IR/FuncOps.h"
 #include "mlir/Dialect/Func/Transforms/FuncConversions.h"
 #include "mlir/Dialect/Tosa/IR/TosaOps.h"
+#include "mlir/Dialect/Tosa/Utils/ConversionUtils.h"
+#include "mlir/IR/BuiltinDialect.h"
+#include "mlir/IR/DialectResourceBlobManager.h"
 #include "mlir/IR/Verifier.h"
 #include "mlir/Pass/Pass.h"
 
@@ -238,6 +242,70 @@ convertDenseFPElementsAttr(ShapedType type, DenseFPElementsAttr attr,
   return convertedAttr;
 }
 
+template <TosaNarrowKind Kind>
+FailureOr<Attribute> convertDenseResourceElementsAttr(
+    ShapedType type, DenseResourceElementsAttr attr,
+    const TypeConverter &typeConverter, bool allowLossyConversion) {
+  static_assert(Kind == TosaNarrowKind::Int64ToInt32 ||
+                Kind == TosaNarrowKind::Float64ToFloat32);
+  using From =
+      std::conditional_t<Kind == TosaNarrowKind::Int64ToInt32, int64_t, double>;
+  using To =
+      std::conditional_t<Kind == TosaNarrowKind::Int64ToInt32, int32_t, float>;
+
+  if (Kind == TosaNarrowKind::Int64ToInt32 &&
+      !isa<DenseI64ResourceElementsAttr>(attr)) {
+    return attr;
+  }
+
+  if (Kind == TosaNarrowKind::Float64ToFloat32 &&
+      !isa<DenseF64ResourceElementsAttr>(attr)) {
+    return attr;
+  }
+
+  auto narrow = [](From value) {
+    if constexpr (Kind == TosaNarrowKind::Int64ToInt32) {
+      value = std::clamp<From>(value, std::numeric_limits<To>::min(),
+                               std::numeric_limits<To>::max());
+    }
+
+    return static_cast<To>(value);
+  };
+
+  const auto newType =
+      dyn_cast_or_null<ShapedType>(typeConverter.convertType(type));
+  if (!newType) {
+    return failure();
+  }
+
+  const std::optional<ArrayRef<From>> values =
+      tryGetDenseResourceValues<From>(attr);
+  if (!values) {
+    return failure();
+  }
+
+  SmallVector<To> newValues;
+  newValues.reserve(values->size());
+  for (From value : *values) {
+    const To convertedValue = narrow(value);
+    if (!allowLossyConversion && convertedValue != value) {
+      return failure();
+    }
+
+    newValues.push_back(convertedValue);
+  }
+
+  AsmResourceBlob blob = HeapAsmResourceBlob::allocateAndCopyInferAlign(
+      ArrayRef<To>(newValues.data(), newValues.size()));
+
+  auto resourceManager =
+      DenseResourceElementsHandle::getManagerInterface(attr.getContext());
+  resourceManager.getBlobManager().update(attr.getRawHandle().getKey(),
+                                          std::move(blob));
+
+  return DenseResourceElementsAttr::get(newType, attr.getRawHandle());
+}
+
 template <TosaNarrowKind Kind, typename AttrT>
 FailureOr<Attribute>
 convertAttributeWithTypeConverter(AttrT attr, Type type,
@@ -340,6 +408,20 @@ LogicalResult convertGenericOp(Operation *op, ValueRange operands,
       continue;
     }
 
+    if (const auto denseResourceElementsAttr =
+            dyn_cast<DenseResourceElementsAttr>(attribute)) {
+      FailureOr<Attribute> convertedAttr =
+          convertAttributeWithTypeConverter<Kind>(
+              denseResourceElementsAttr, denseResourceElementsAttr.getType(),
+              typeConverter);
+      if (failed(convertedAttr))
+        return rewriter.notifyMatchFailure(
+            op, "Failed to convert dense resource elements attribute without "
+                "precision loss; enable aggressive rewrite to override.");
+      state.addAttribute(namedAttribute.getName(), convertedAttr.value());
+      continue;
+    }
+
     state.addAttribute(namedAttribute.getName(), attribute);
   }
 
@@ -539,6 +621,18 @@ LogicalResult runTosaNarrowing(Operation *op, bool aggressiveRewrite,
   typeConverter.addSourceMaterialization(materializeCast);
   typeConverter.addTargetMaterialization(materializeCast);
 
+  typeConverter.addTypeAttributeConversion(
+      [&typeConverter, allowLossyConversion](ShapedType type,
+                                             DenseResourceElementsAttr attr)
+          -> TypeConverter::AttributeConversionResult {
+        FailureOr<Attribute> converted = convertDenseResourceElementsAttr<Kind>(
+            type, attr, typeConverter, allowLossyConversion);
+        if (failed(converted))
+          return TypeConverter::AttributeConversionResult::abort();
+        return TypeConverter::AttributeConversionResult::result(
+            converted.value());
+      });
+
   if constexpr (Kind == TosaNarrowKind::Int64ToInt32) {
     typeConverter.addTypeAttributeConversion(
         [allowLossyConversion](IntegerType /*type*/, IntegerAttr attribute)

diff  --git a/mlir/test/Dialect/Tosa/tosa-narrow-f64-to-f32-aggressive.mlir b/mlir/test/Dialect/Tosa/tosa-narrow-f64-to-f32-aggressive.mlir
index 69547194dee3f..191a337e88874 100644
--- a/mlir/test/Dialect/Tosa/tosa-narrow-f64-to-f32-aggressive.mlir
+++ b/mlir/test/Dialect/Tosa/tosa-narrow-f64-to-f32-aggressive.mlir
@@ -68,3 +68,23 @@ func.func @test_f64_const() -> tensor<2xf64> {
   // FUNCBOUND: return %[[CONST]] : tensor<2xf32>
   return %0 : tensor<2xf64>
 }
+
+// -----
+
+// CHECK-LABEL: test_dense_ressource_f64
+func.func @test_dense_ressource_f64() -> tensor<1x2xf64> {
+  // COMMON: %[[CONST:.*]] = "tosa.const"() <{values = dense_resource<resource> : tensor<1x2xf32>}> : () -> tensor<1x2xf32>
+  %0 = "tosa.const"() <{values = dense_resource<resource> : tensor<1x2xf64>}> : () -> tensor<1x2xf64>
+  // DEFAULT: %[[OUT_CAST:.*]] = tosa.cast %[[CONST]] : (tensor<1x2xf32>) -> tensor<1x2xf64>
+  // DEFAULT: return %[[OUT_CAST]] : tensor<1x2xf64>
+  // FUNCBOUND: return %[[CONST]] : tensor<1x2xf32>
+  return %0 : tensor<1x2xf64>
+}
+{-#
+  dialect_resources: {
+    builtin: {
+      // COMMON: resource: "0x04000000DB0F4940EAD6FCBD"
+      resource: "0x04000000182D4454FB21094059F64637DD9ABFBF"
+    }
+  }
+#-}

diff  --git a/mlir/test/Dialect/Tosa/tosa-narrow-f64-to-f32.mlir b/mlir/test/Dialect/Tosa/tosa-narrow-f64-to-f32.mlir
index 1034ee67f65e2..be596eb890aad 100644
--- a/mlir/test/Dialect/Tosa/tosa-narrow-f64-to-f32.mlir
+++ b/mlir/test/Dialect/Tosa/tosa-narrow-f64-to-f32.mlir
@@ -178,3 +178,23 @@ func.func @test_f64_add_diagnostic(%arg0: tensor<13x21x1xf64>, %arg1: tensor<13x
   return %0 : tensor<13x21x3xf64>
 }
 }
+
+// -----
+
+// CHECK-LABEL: test_dense_ressource_f64
+func.func @test_dense_ressource_f64() -> tensor<1x2xf64> {
+  // COMMON: %[[CONST:.*]] = "tosa.const"() <{values = dense_resource<resource> : tensor<1x2xf32>}> : () -> tensor<1x2xf32>
+  %0 = "tosa.const"() <{values = dense_resource<resource> : tensor<1x2xf64>}> : () -> tensor<1x2xf64>
+  // DEFAULT: %[[OUT_CAST:.*]] = tosa.cast %[[CONST]] : (tensor<1x2xf32>) -> tensor<1x2xf64>
+  // DEFAULT: return %[[OUT_CAST]] : tensor<1x2xf64>
+  // FUNCBOUND: return %[[CONST]] : tensor<1x2xf32>
+  return %0 : tensor<1x2xf64>
+}
+{-#
+  dialect_resources: {
+    builtin: {
+      // COMMON: resource: "0x040000000000803F000080BF"
+      resource: "0x04000000000000000000F03F000000000000F0BF"
+    }
+  }
+#-}

diff  --git a/mlir/test/Dialect/Tosa/tosa-narrow-i64-to-i32-aggressive.mlir b/mlir/test/Dialect/Tosa/tosa-narrow-i64-to-i32-aggressive.mlir
index 9848fe4abb345..f7ba9765be556 100644
--- a/mlir/test/Dialect/Tosa/tosa-narrow-i64-to-i32-aggressive.mlir
+++ b/mlir/test/Dialect/Tosa/tosa-narrow-i64-to-i32-aggressive.mlir
@@ -88,3 +88,23 @@ func.func @test_clamp_trunc(%arg0: tensor<100xi64>) -> tensor<100xi64> {
   %1 = tosa.clamp %arg0 {max_val = 3000000000 : i64, min_val = -2147483648 : i64} : (tensor<100xi64>) -> tensor<100xi64>
   return %1 : tensor<100xi64>
 }
+
+// -----
+
+// CHECK-LABEL: test_dense_ressource_i64
+func.func @test_dense_ressource_i64() -> tensor<1x2xi64> {
+  // COMMON: %[[CONST:.*]] = "tosa.const"() <{values = dense_resource<resource> : tensor<1x2xi32>}> : () -> tensor<1x2xi32>
+  %1 = "tosa.const"() <{values = dense_resource<resource> : tensor<1x2xi64>}> : () -> tensor<1x2xi64>
+  // DEFAULT: %[[OUT_CAST:.*]] = tosa.cast %[[CONST]] : (tensor<1x2xi32>) -> tensor<1x2xi64>
+  // DEFAULT: return %[[OUT_CAST]] : tensor<1x2xi64>
+  // FUNCBOUND: return %[[CONST]] : tensor<1x2xi32>
+  return %1 : tensor<1x2xi64>
+}
+{-#
+  dialect_resources: {
+    builtin: {
+      // COMMON: resource: "0x04000000FFFFFF7F00000080"
+      resource: "0x04000000000000000800000000000000F8FFFFFF"
+    }
+  }
+#-}

diff  --git a/mlir/test/Dialect/Tosa/tosa-narrow-i64-to-i32.mlir b/mlir/test/Dialect/Tosa/tosa-narrow-i64-to-i32.mlir
index 42e63346d8c33..6c01d80bdb38f 100644
--- a/mlir/test/Dialect/Tosa/tosa-narrow-i64-to-i32.mlir
+++ b/mlir/test/Dialect/Tosa/tosa-narrow-i64-to-i32.mlir
@@ -199,3 +199,23 @@ func.func @test_clamp_min_outside_i32_range(%arg0: tensor<100xi64>) -> tensor<10
   %1 = tosa.clamp %arg0 {max_val = 2147483647 : i64, min_val = -2147483649 : i64} : (tensor<100xi64>) -> tensor<100xi64>
   return %1 : tensor<100xi64>
 }
+
+// -----
+
+// CHECK-LABEL: test_dense_ressource_i64
+func.func @test_dense_ressource_i64() -> tensor<1x2xi64> {
+  // COMMON: %[[CONST:.*]] = "tosa.const"() <{values = dense_resource<resource> : tensor<1x2xi32>}> : () -> tensor<1x2xi32>
+  %1 = "tosa.const"() <{values = dense_resource<resource> : tensor<1x2xi64>}> : () -> tensor<1x2xi64>
+  // DEFAULT: %[[OUT_CAST:.*]] = tosa.cast %[[CONST]] : (tensor<1x2xi32>) -> tensor<1x2xi64>
+  // DEFAULT: return %[[OUT_CAST]] : tensor<1x2xi64>
+  // FUNCBOUND: return %[[CONST]] : tensor<1x2xi32>
+  return %1 : tensor<1x2xi64>
+}
+{-#
+  dialect_resources: {
+    builtin: {
+      // COMMON: resource: "0x04000000FEFFFF7F905AE75A"
+      resource: "0x04000000FEFFFF7F00000000905AE75A00000000"
+    }
+  }
+#-}


        


More information about the Mlir-commits mailing list