[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