diff --git a/src/Conversion/ONNXToTOSA/ConvertONNXToTOSA.cpp b/src/Conversion/ONNXToTOSA/ConvertONNXToTOSA.cpp index 84e72a79d30..d884e8b2292 100644 --- a/src/Conversion/ONNXToTOSA/ConvertONNXToTOSA.cpp +++ b/src/Conversion/ONNXToTOSA/ConvertONNXToTOSA.cpp @@ -5,7 +5,7 @@ //====------ ConvertONNXToTOSA.cpp - ONNX dialects to TOSA lowering -------===// // // Copyright (c) 2022 Arm Limited. -// Copyright (c) 2022-2025 Advanced Micro Devices, Inc. +// Copyright (c) 2022-2026 Advanced Micro Devices, Inc. // // ============================================================================= // @@ -174,11 +174,11 @@ void FrontendToTosaLoweringPass::runOnOperation() { // We use the type converter to legalize types before any conversion patterns // are executed. This ensures that we do not need to trigger separate - // conversion failures. Quantized types are not supported right now. + // conversion failures. Only per-tensor quantization is supported right now. TypeConverter typeConverter; typeConverter.addConversion([](Type type) -> std::optional { if (isTOSAInt(type) || isa(type) || isa(type) || - isTOSABool(type)) + isTOSABool(type) || isTOSAQuantizedInt(type)) return type; return std::nullopt; }); diff --git a/src/Conversion/ONNXToTOSA/Math/Elementwise.cpp b/src/Conversion/ONNXToTOSA/Math/Elementwise.cpp index 842a845d2b6..ba901e8941a 100644 --- a/src/Conversion/ONNXToTOSA/Math/Elementwise.cpp +++ b/src/Conversion/ONNXToTOSA/Math/Elementwise.cpp @@ -4,7 +4,7 @@ //===---------------- Elementwise.cpp - Elementwise Op --------------------===// // -// Copyright (c) 2022 Advanced Micro Devices, Inc. +// Copyright (c) 2022-2026 Advanced Micro Devices, Inc. // // ============================================================================= // @@ -31,6 +31,18 @@ struct TOSADialectOp { using Op = mlir::tosa::NegateOp; }; +struct IsIntOrFloatOrQuantizedInt { + static LogicalResult checkType( + ConversionPatternRewriter &rewriter, Type scalarType, Operation *op) { + if (!isa(scalarType) && !isTOSAInt(scalarType) && + !isTOSAQuantizedInt(scalarType)) { + return rewriter.notifyMatchFailure(op, + "this operation only supports int, float, or quantized int types"); + } + return success(); + } +}; + struct IsIntOrFloat { static LogicalResult checkType( ConversionPatternRewriter &rewriter, Type scalarType, Operation *op) { @@ -724,7 +736,7 @@ static void populateLoweringONNXElementwiseUnaryTemplateOpToTOSAPattern( ONNXElementwiseUnaryOpLoweringToTOSA, ONNXElementwiseUnaryOpLoweringToTOSA, + IsIntOrFloatOrQuantizedInt, IsIntOrFloatOrQuantizedInt>, ONNXElementwiseUnaryOpLoweringToTOSA, ONNXElementwiseUnaryOpLoweringToTOSA(type); + return quantizedType && isTOSAInt(quantizedType.getStorageType()); +} + //===----------------------------------------------------------------------===// // This is to get a TOSA operation of a given type for a specific operation. //===----------------------------------------------------------------------===// diff --git a/test/mlir/conversion/onnx_to_tosa/Math/Elementwise.mlir b/test/mlir/conversion/onnx_to_tosa/Math/Elementwise.mlir index cf8c7209716..433860fa82a 100644 --- a/test/mlir/conversion/onnx_to_tosa/Math/Elementwise.mlir +++ b/test/mlir/conversion/onnx_to_tosa/Math/Elementwise.mlir @@ -1,3 +1,5 @@ +// Copyright (c) 2026 Advanced Micro Devices, Inc. + // RUN: onnx-mlir-opt --shape-inference --convert-onnx-to-tosa -cse %s -split-input-file | FileCheck %s // ----- @@ -786,6 +788,29 @@ func.func @test_abs_f64(%arg0: tensor<3xf64>) -> tensor<3xf64> { // CHECK: return {{.*}}: tensor<3xf64> } +func.func @test_abs_qi8(%arg0: tensor<3x!quant.uniform>) -> tensor<3x!quant.uniform> { + %0 = "onnx.Abs"(%arg0) : (tensor<3x!quant.uniform>) -> tensor<3x!quant.uniform> + return %0 : tensor<3x!quant.uniform> +// CHECK-LABEL: func @test_abs_qi8 +// CHECK-NEXT: [[VAR_0_:%.+]] = tosa.abs [[PARAM_0_]] : (tensor<3x!quant.uniform>) -> tensor<3x!quant.uniform> +// CHECK-NEXT: return [[VAR_0_]] : tensor<3x!quant.uniform> +// CHECK-NEXT: } +} + +// Per-channel quantized types use quant.uniform, +// which is not currently handled by the ONNX-to-TOSA elementwise conversion. +// Only per-tensor uniform quantized types are supported. +// This test checks that the conversion does not fail but keeps the original op. + +func.func @test_abs_qi8_channel(%arg0: tensor<3x4x!quant.uniform>) -> tensor<3x4x!quant.uniform> { + %0 = "onnx.Abs"(%arg0) : (tensor<3x4x!quant.uniform>) -> tensor<3x4x!quant.uniform> + return %0 : tensor<3x4x!quant.uniform> + +// CHECK-LABEL: func @test_abs_qi8_channel +// CHECK: "onnx.Abs" +// CHECK: return +} + // ----- func.func @test_erf_f32(%arg0: tensor<3xf32>) -> tensor<3xf32> {