From 569cc3611bedc18a50d24af504f4b4c68a5dd023 Mon Sep 17 00:00:00 2001 From: Matthias Gehre Date: Tue, 14 Mar 2023 17:10:00 +0100 Subject: [PATCH 1/6] TOSA: Allow all signless integers and all unsigned integers --- mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td b/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td index 0b4bd7d27badc..8ad2eef978323 100644 --- a/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td +++ b/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td @@ -38,8 +38,6 @@ class Tosa_QuantizedType params, bit signed> // Used to express accumulator results or compare results. //===----------------------------------------------------------------------===// -def Tosa_UInt8 : UI<8>; - def Tosa_Int8 : I<8>; def Tosa_Int16 : I<16>; def Tosa_Int32 : I<32>; @@ -54,9 +52,11 @@ def Tosa_SignedInt : AnyTypeOf<[Tosa_Int8, def Tosa_Bool : I<1>; -// No unsigned unquantized int types. def Tosa_Int : AnyTypeOf<[Tosa_Bool, - Tosa_UInt8, + AnyUnsignedInteger, + AnySignlessInteger, +// TODO: For backwards compatibility, keep Tosa_SignedInt, which is actually +// a set of signless types. Tosa_SignedInt]>; def Tosa_Int32Or64 : AnyTypeOf<[Tosa_Int32, From 10ac1de1786dc8e6c59bb3a7a97e6ddb354fb491 Mon Sep 17 00:00:00 2001 From: Matthias Gehre Date: Tue, 14 Mar 2023 17:10:29 +0100 Subject: [PATCH 2/6] Implement lowering of tosa.cast to unsigned integer --- .../lib/Conversion/TosaToLinalg/TosaToLinalg.cpp | 7 +++++++ .../TosaToLinalg/tosa-to-linalg-ui3.mlir | 16 ++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-ui3.mlir diff --git a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp index 251be563a0c8f..1c3f6a2a68468 100644 --- a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp +++ b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp @@ -484,6 +484,13 @@ createLinalgBodyCalculationForElementwiseOp(Operation *op, ValueRange args, auto clamped = clampFloatHelper(loc, rounded, intMin, intMax, rewriter); + if (dstTy.isUnsignedInteger()) { + auto cast = rewriter.create( + loc, rewriter.getIntegerType(dstTy.getIntOrFloatBitWidth()), clamped); + return rewriter.create( + loc, dstTy, cast->getResult(0)).getResult(0); + } + return rewriter.create(loc, dstTy, clamped); } diff --git a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-ui3.mlir b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-ui3.mlir new file mode 100644 index 0000000000000..078fea65e6ab2 --- /dev/null +++ b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-ui3.mlir @@ -0,0 +1,16 @@ +// RUN: mlir-opt --split-input-file -pass-pipeline="builtin.module(func.func(tosa-to-linalg))" %s | FileCheck %s + +func.func @test_cast(%arg0: tensor<1xf32>) -> tensor<1xui3> { + // CHECK: linalg.generic + // CHECK: arith.constant -4.000000e+00 + // CHECK: arith.constant 3.000000e+00 + // CHECK: math.roundeven + // CHECK: arith.minf + // CHECK: arith.maxf + // CHECK: arith.fptoui + // CHECK: builtin.unrealized_conversion_cast + %1 = "tosa.cast"(%arg0) : (tensor<1xf32>) -> tensor<1xui3> + + return %1 : tensor<1xui3> +} + \ No newline at end of file From c653caf5d0fa3c68bc37bcb23aa8fc7e2e888882 Mon Sep 17 00:00:00 2001 From: Matthias Gehre Date: Tue, 21 Mar 2023 18:01:46 +0100 Subject: [PATCH 3/6] Test tosa.matmul and tosa.cast with i2 --- .../TosaToLinalg/tosa-to-linalg-i2.mlir | 20 +++++++++++++++++++ .../TosaToLinalg/tosa-to-linalg-named-i2.mlir | 13 ++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-i2.mlir create mode 100644 mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-named-i2.mlir diff --git a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-i2.mlir b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-i2.mlir new file mode 100644 index 0000000000000..b9001d807194a --- /dev/null +++ b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-i2.mlir @@ -0,0 +1,20 @@ +// RUN: mlir-opt --split-input-file -pass-pipeline="builtin.module(func.func(tosa-to-linalg))" %s -verify-diagnostics -o -| FileCheck %s + +func.func @test_cast(%arg0: tensor<1xf32>) -> tensor<1xf32> { + // CHECK: linalg.generic + // CHECK: arith.constant -2.000000e+00 + // CHECK: arith.constant 1.000000e+00 + // CHECK: math.roundeven + // CHECK: arith.minf + // CHECK: arith.maxf + // CHECK: arith.fptosi + %1 = "tosa.cast"(%arg0) : (tensor<1xf32>) -> tensor<1xi2> + + // CHECK: linalg.generic + // CHECK: arith.sitofp + %2 = "tosa.cast"(%1) : (tensor<1xi2>) -> tensor<1xf32> + + return %2 : tensor<1xf32> +} + +// ----- diff --git a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-named-i2.mlir b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-named-i2.mlir new file mode 100644 index 0000000000000..b22c32263a69e --- /dev/null +++ b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-named-i2.mlir @@ -0,0 +1,13 @@ +// RUN: mlir-opt --split-input-file -pass-pipeline="builtin.module(func.func(tosa-to-linalg-named))" %s -verify-diagnostics -o -| FileCheck %s + +// CHECK-LABEL: @matmul +func.func @matmul(%arg0: tensor<1x5x3xi2>, %arg1: tensor<1x3x6xi2>) -> (tensor<1x5x6xi2>) { + // CHECK: [[C0:%.+]] = arith.constant 0 : i2 + // CHECK: [[INIT:%.+]] = tensor.empty() + // CHECK: [[FILLED:%.+]] = linalg.fill ins([[C0]] : i2) outs([[INIT]] : tensor<1x5x6xi2>) -> tensor<1x5x6xi2> + // CHECK: linalg.batch_matmul ins(%arg0, %arg1 : tensor<1x5x3xi2>, tensor<1x3x6xi2>) outs([[FILLED]] : tensor<1x5x6xi2>) -> tensor<1x5x6xi2> + %0 = "tosa.matmul"(%arg0, %arg1) : (tensor<1x5x3xi2>, tensor<1x3x6xi2>) -> (tensor<1x5x6xi2>) + return %0 : tensor<1x5x6xi2> +} + +// ----- From f99141d166ebf5e4993db007185ac53e551e1df2 Mon Sep 17 00:00:00 2001 From: Matthias Gehre Date: Wed, 22 Mar 2023 10:01:34 +0100 Subject: [PATCH 4/6] mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-named-i2.mlir: Add test case with different accumulator type --- .../TosaToLinalg/tosa-to-linalg-named-i2.mlir | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-named-i2.mlir b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-named-i2.mlir index b22c32263a69e..c42ede8f16a77 100644 --- a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-named-i2.mlir +++ b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-named-i2.mlir @@ -11,3 +11,15 @@ func.func @matmul(%arg0: tensor<1x5x3xi2>, %arg1: tensor<1x3x6xi2>) -> (tensor<1 } // ----- + +// CHECK-LABEL: @matmul +func.func @matmul(%arg0: tensor<1x5x3xi2>, %arg1: tensor<1x3x6xi2>) -> (tensor<1x5x6xi4>) { + // CHECK: [[C0:%.+]] = arith.constant 0 : i4 + // CHECK: [[INIT:%.+]] = tensor.empty() + // CHECK: [[FILLED:%.+]] = linalg.fill ins([[C0]] : i4) outs([[INIT]] : tensor<1x5x6xi4>) -> tensor<1x5x6xi4> + // CHECK: linalg.batch_matmul ins(%arg0, %arg1 : tensor<1x5x3xi2>, tensor<1x3x6xi2>) outs([[FILLED]] : tensor<1x5x6xi4>) -> tensor<1x5x6xi2> + %0 = "tosa.matmul"(%arg0, %arg1) : (tensor<1x5x3xi2>, tensor<1x3x6xi2>) -> (tensor<1x5x6xi4>) + return %0 : tensor<1x5x6xi4> +} + +// ----- From 2d89023b8856332d7e51a880e6ae1a5078ea788b Mon Sep 17 00:00:00 2001 From: Matthias Gehre Date: Wed, 22 Mar 2023 10:33:08 +0100 Subject: [PATCH 5/6] mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-named-i2.mlir: Fix broken test --- mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-named-i2.mlir | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-named-i2.mlir b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-named-i2.mlir index c42ede8f16a77..0d0686dc45fa2 100644 --- a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-named-i2.mlir +++ b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-named-i2.mlir @@ -17,7 +17,7 @@ func.func @matmul(%arg0: tensor<1x5x3xi2>, %arg1: tensor<1x3x6xi2>) -> (tensor<1 // CHECK: [[C0:%.+]] = arith.constant 0 : i4 // CHECK: [[INIT:%.+]] = tensor.empty() // CHECK: [[FILLED:%.+]] = linalg.fill ins([[C0]] : i4) outs([[INIT]] : tensor<1x5x6xi4>) -> tensor<1x5x6xi4> - // CHECK: linalg.batch_matmul ins(%arg0, %arg1 : tensor<1x5x3xi2>, tensor<1x3x6xi2>) outs([[FILLED]] : tensor<1x5x6xi4>) -> tensor<1x5x6xi2> + // CHECK: linalg.batch_matmul ins(%arg0, %arg1 : tensor<1x5x3xi2>, tensor<1x3x6xi2>) outs([[FILLED]] : tensor<1x5x6xi4>) -> tensor<1x5x6xi4> %0 = "tosa.matmul"(%arg0, %arg1) : (tensor<1x5x3xi2>, tensor<1x3x6xi2>) -> (tensor<1x5x6xi4>) return %0 : tensor<1x5x6xi4> } From a0c9b58f76f0309e9a353072ef0a3d914069af3c Mon Sep 17 00:00:00 2001 From: Matthias Gehre Date: Wed, 22 Mar 2023 10:33:52 +0100 Subject: [PATCH 6/6] TosaToLinalg: Fixed tosa.cast for small unsigned integers --- .../Conversion/TosaToLinalg/TosaToLinalg.cpp | 34 ++++++++++++++----- .../TosaToLinalg/tosa-to-linalg-ui3.mlir | 6 ++-- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp index 1c3f6a2a68468..75f82e737798a 100644 --- a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp +++ b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp @@ -469,7 +469,8 @@ createLinalgBodyCalculationForElementwiseOp(Operation *op, ValueRange args, args.front(), zero); } - if (arith::FPToSIOp::areCastCompatible(srcTy, dstTy)) { + if (dstTy.isSignlessInteger() && + arith::FPToSIOp::areCastCompatible(srcTy, dstTy)) { auto intMin = rewriter.create( loc, rewriter.getF32FloatAttr( APInt::getSignedMinValue(dstTy.getIntOrFloatBitWidth()) @@ -484,16 +485,33 @@ createLinalgBodyCalculationForElementwiseOp(Operation *op, ValueRange args, auto clamped = clampFloatHelper(loc, rounded, intMin, intMax, rewriter); - if (dstTy.isUnsignedInteger()) { - auto cast = rewriter.create( - loc, rewriter.getIntegerType(dstTy.getIntOrFloatBitWidth()), clamped); - return rewriter.create( - loc, dstTy, cast->getResult(0)).getResult(0); - } - return rewriter.create(loc, dstTy, clamped); } + if (dstTy.isUnsignedInteger() && + arith::FPToUIOp::areCastCompatible(srcTy, dstTy)) { + auto intMin = rewriter.create( + loc, rewriter.getF32FloatAttr( + APInt::getMinValue(dstTy.getIntOrFloatBitWidth()) + .getZExtValue())); + + auto intMax = rewriter.create( + loc, rewriter.getF32FloatAttr( + APInt::getMaxValue(dstTy.getIntOrFloatBitWidth()) + .getZExtValue())); + + auto rounded = rewriter.create(loc, args[0]); + + auto clamped = clampFloatHelper(loc, rounded, intMin, intMax, rewriter); + + auto cast = rewriter.create( + loc, rewriter.getIntegerType(dstTy.getIntOrFloatBitWidth()), clamped); + // arith is signless, so temporarily cast back to being unsigned. + return rewriter + .create(loc, dstTy, cast->getResult(0)) + .getResult(0); + } + // Casting to boolean, integers need to only be checked as not-equal to // zero. if (srcTy.isa() && dstTy.isInteger(1)) { diff --git a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-ui3.mlir b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-ui3.mlir index 078fea65e6ab2..051a4fb5a1092 100644 --- a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-ui3.mlir +++ b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg-ui3.mlir @@ -2,12 +2,12 @@ func.func @test_cast(%arg0: tensor<1xf32>) -> tensor<1xui3> { // CHECK: linalg.generic - // CHECK: arith.constant -4.000000e+00 - // CHECK: arith.constant 3.000000e+00 + // CHECK: arith.constant 0.000000e+00 + // CHECK: arith.constant 7.000000e+00 // CHECK: math.roundeven // CHECK: arith.minf // CHECK: arith.maxf - // CHECK: arith.fptoui + // CHECK: arith.fptoui {{.*}} : f32 to i3 // CHECK: builtin.unrealized_conversion_cast %1 = "tosa.cast"(%arg0) : (tensor<1xf32>) -> tensor<1xui3>