[Mlir-commits] [mlir] 139e2fb - [mlir][tosa]: Add Binary Shape Ops folders (#178877)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Tue Feb 3 03:32:49 PST 2026
Author: Udaya Ranga
Date: 2026-02-03T11:32:44Z
New Revision: 139e2fb60217a9cbdb68f9efad32da611b957c30
URL: https://github.com/llvm/llvm-project/commit/139e2fb60217a9cbdb68f9efad32da611b957c30
DIFF: https://github.com/llvm/llvm-project/commit/139e2fb60217a9cbdb68f9efad32da611b957c30.diff
LOG: [mlir][tosa]: Add Binary Shape Ops folders (#178877)
* SUB_SHAPE
* MUL_SHAPE
* DIV_CEIL_SHAPE
* DIV_FLOOR_SHAPE
* MOD_SHAPE
Change-Id: I12500bbc05c62730e0dc9cc8d3f20b02845d407e
Signed-off-by: Udaya Ranga <udaya.ranga at arm.com>
Added:
Modified:
mlir/include/mlir/Dialect/Tosa/IR/TosaShapeOps.td
mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp
mlir/test/Dialect/Tosa/constant_folding.mlir
Removed:
################################################################################
diff --git a/mlir/include/mlir/Dialect/Tosa/IR/TosaShapeOps.td b/mlir/include/mlir/Dialect/Tosa/IR/TosaShapeOps.td
index 57fd1d2d20aa8..104f2741e5678 100644
--- a/mlir/include/mlir/Dialect/Tosa/IR/TosaShapeOps.td
+++ b/mlir/include/mlir/Dialect/Tosa/IR/TosaShapeOps.td
@@ -159,6 +159,8 @@ def Tosa_DivCeilShapeOp : Tosa_ElementwiseShapeOp<"div_ceil_shape", [Pure]> {
);
let results = (outs Tosa_Shape:$output);
+
+ let hasFolder = 1;
}
//===----------------------------------------------------------------------===//
@@ -177,6 +179,8 @@ def Tosa_DivFloorShapeOp : Tosa_ElementwiseShapeOp<"div_floor_shape", [Pure]> {
);
let results = (outs Tosa_Shape:$output);
+
+ let hasFolder = 1;
}
//===----------------------------------------------------------------------===//
@@ -282,6 +286,8 @@ def Tosa_ModShapeOp : Tosa_ElementwiseShapeOp<"mod_shape", [Pure]> {
);
let results = (outs Tosa_Shape:$output);
+
+ let hasFolder = 1;
}
//===----------------------------------------------------------------------===//
@@ -300,6 +306,8 @@ def Tosa_MulShapeOp : Tosa_ElementwiseShapeOp<"mul_shape", [Pure]> {
);
let results = (outs Tosa_Shape:$output);
+
+ let hasFolder = 1;
}
//===----------------------------------------------------------------------===//
@@ -339,6 +347,8 @@ def Tosa_SubShapeOp : Tosa_ElementwiseShapeOp<"sub_shape", [Pure]> {
);
let results = (outs Tosa_Shape:$output);
+
+ let hasFolder = 1;
}
//===----------------------------------------------------------------------===//
diff --git a/mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp b/mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp
index 07a0b6742d48a..ed1584f93a367 100644
--- a/mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp
+++ b/mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp
@@ -986,7 +986,7 @@ binaryFolder(DenseElementsAttr lhs, DenseElementsAttr rhs, ShapedType returnTy,
return {};
}
-struct FoldAddAdaptor {
+struct AddFoldAdaptor {
static FailureOr<APInt> fold(const APInt &lhs, const APInt &rhs,
const bool isUnsigned) {
bool overflow;
@@ -1002,7 +1002,7 @@ struct FoldAddAdaptor {
}
};
-struct FoldSubAdaptor {
+struct SubFoldAdaptor {
static FailureOr<APInt> fold(const APInt &lhs, const APInt &rhs,
const bool isUnsigned) {
bool overflow;
@@ -1018,6 +1018,104 @@ struct FoldSubAdaptor {
}
};
+struct MulFoldAdaptor {
+ static FailureOr<APInt> fold(const APInt &lhs, const APInt &rhs,
+ const bool isUnsigned) {
+
+ const unsigned originalWidth = lhs.getBitWidth();
+
+ // Check same type
+ if (lhs.getBitWidth() != rhs.getBitWidth()) {
+ return failure();
+ }
+
+ // If either is `0`
+ if (lhs == 0 || rhs == 0)
+ return APInt::getZero(originalWidth);
+
+ bool overflow = false;
+ APInt const result =
+ isUnsigned ? lhs.umul_ov(rhs, overflow) : lhs.smul_ov(rhs, overflow);
+
+ if (overflow)
+ return failure();
+
+ return result.trunc(originalWidth);
+ }
+
+ static FailureOr<APFloat> fold(const APFloat &lhs, const APFloat &rhs) {
+ return lhs * rhs;
+ }
+};
+
+static bool signsDiffer(const APInt &a, const APInt &b) {
+ return a.isNegative() != b.isNegative();
+}
+
+template <bool Ceil>
+struct DivFoldAdaptor {
+ static FailureOr<APInt> fold(const APInt &lhs, const APInt &rhs,
+ bool isUnsigned) {
+ if (lhs.getBitWidth() != rhs.getBitWidth())
+ return failure();
+ if (rhs.isZero())
+ return failure();
+
+ if (isUnsigned) {
+ APInt q{};
+ APInt r{};
+ APInt::udivrem(lhs, rhs, q, r);
+ if (!r.isZero() && Ceil) {
+ return q + 1;
+ }
+ return q;
+ }
+
+ // Signed: start from trunc-toward-zero, then adjust to ceil.
+ bool overflow{false};
+ APInt const q = lhs.sdiv_ov(rhs, overflow);
+ if (overflow)
+ return failure();
+ APInt const r = lhs.srem(rhs);
+
+ if (Ceil && !r.isZero() && !signsDiffer(lhs, rhs)) {
+ // Same sign => exact quotient is positive; trunc is below ceil =>
+ // increment q.
+ return q + 1;
+ }
+ return q;
+ }
+
+ static FailureOr<APFloat> fold(const APFloat &lhs, const APFloat &rhs) {
+ return lhs / rhs;
+ }
+};
+
+struct ModFoldAdaptor {
+ static FailureOr<APInt> fold(const APInt &lhs, const APInt &rhs,
+ bool isUnsigned) {
+ if (lhs.getBitWidth() != rhs.getBitWidth())
+ return failure();
+ if (lhs.isNegative() || (!rhs.isStrictlyPositive()))
+ return failure();
+
+ if (isUnsigned) {
+ return lhs.urem(rhs);
+ }
+
+ return lhs.srem(rhs);
+ }
+
+ static FailureOr<APFloat> fold(const APFloat &lhs, const APFloat &rhs) {
+ auto t = lhs;
+ auto const r = t.mod(rhs);
+ if (llvm::APFloatBase::opStatus::opOK == r) {
+ return t;
+ }
+ return failure();
+ }
+};
+
struct FoldGreaterAdaptor {
static FailureOr<APInt> fold(const APInt &lhs, const APInt &rhs,
const bool isUnsigned) {
@@ -1097,7 +1195,7 @@ OpFoldResult AddOp::fold(FoldAdaptor adaptor) {
if (!lhsAttr || !rhsAttr)
return {};
- return binaryFolder<FoldAddAdaptor>(lhsAttr, rhsAttr, resultTy);
+ return binaryFolder<AddFoldAdaptor>(lhsAttr, rhsAttr, resultTy);
}
OpFoldResult ArgMaxOp::fold(FoldAdaptor adaptor) {
@@ -1149,8 +1247,11 @@ OpFoldResult IntDivOp::fold(FoldAdaptor adaptor) {
APInt l = lhsAttr.getSplatValue<APInt>();
APInt r = rhsAttr.getSplatValue<APInt>();
if (!r.isZero()) {
- APInt result = l.sdiv(r);
- return DenseElementsAttr::get(resultTy, result);
+ auto const result =
+ DivFoldAdaptor</*Ceil*/ false>::fold(l, r, /*isUnsigned*/ false);
+ if (failed(result))
+ return {};
+ return DenseElementsAttr::get(resultTy, result.value());
}
}
@@ -1162,7 +1263,11 @@ namespace {
// return nullopt if result is not in range of int32_t when shift > 0
std::optional<APInt> mulInt(APInt lhs, APInt rhs, int32_t shift,
unsigned bitwidth) {
- APInt result = lhs.sext(64) * rhs.sext(64);
+ bool overflow = false;
+ APInt result = lhs.sext(64).smul_ov(rhs.sext(64), overflow);
+
+ if (overflow)
+ return std::nullopt;
if (shift > 0) {
auto round = APInt(64, 1) << (shift - 1);
@@ -1278,7 +1383,7 @@ OpFoldResult SubOp::fold(FoldAdaptor adaptor) {
if (!lhsAttr || !rhsAttr)
return {};
- return binaryFolder<FoldSubAdaptor>(lhsAttr, rhsAttr, resultTy);
+ return binaryFolder<SubFoldAdaptor>(lhsAttr, rhsAttr, resultTy);
}
OpFoldResult GreaterOp::fold(FoldAdaptor adaptor) {
@@ -1750,18 +1855,19 @@ OpFoldResult tosa::ReciprocalOp::fold(FoldAdaptor adaptor) {
return {};
}
-OpFoldResult tosa::AddShapeOp::fold(FoldAdaptor adaptor) {
+template <typename Op, typename OpFoldAdaptor>
+OpFoldResult binaryFold(Op *op) {
auto input1ConstShape =
- dyn_cast<tosa::ConstShapeOp>(getInput1().getDefiningOp());
+ dyn_cast<tosa::ConstShapeOp>(op->getInput1().getDefiningOp());
auto input2ConstShape =
- dyn_cast<tosa::ConstShapeOp>(getInput2().getDefiningOp());
+ dyn_cast<tosa::ConstShapeOp>(op->getInput2().getDefiningOp());
if (!input1ConstShape || !input2ConstShape)
return {};
const auto input1Attr = cast<DenseElementsAttr>(input1ConstShape.getValues());
const auto input2Attr = cast<DenseElementsAttr>(input2ConstShape.getValues());
- return binaryFolder<FoldAddAdaptor>(
+ return binaryFolder<OpFoldAdaptor>(
input1Attr, input2Attr, input1Attr.getType(), /*foldDenseValues=*/true);
}
@@ -1779,3 +1885,27 @@ OpFoldResult tosa::DimOp::fold(FoldAdaptor adaptor) {
RankedTensorType::get(/*rank=*/1, builder.getIndexType());
return DenseElementsAttr::get(resultAttrTy, dimSize);
}
+
+OpFoldResult tosa::AddShapeOp::fold(FoldAdaptor adaptor) {
+ return binaryFold<AddShapeOp, AddFoldAdaptor>(this);
+}
+
+OpFoldResult tosa::SubShapeOp::fold(FoldAdaptor adaptor) {
+ return binaryFold<SubShapeOp, SubFoldAdaptor>(this);
+}
+
+OpFoldResult tosa::MulShapeOp::fold(FoldAdaptor adaptor) {
+ return binaryFold<MulShapeOp, MulFoldAdaptor>(this);
+}
+
+OpFoldResult tosa::DivCeilShapeOp::fold(FoldAdaptor adaptor) {
+ return binaryFold<DivCeilShapeOp, DivFoldAdaptor</*Ceil*/ true>>(this);
+}
+
+OpFoldResult tosa::DivFloorShapeOp::fold(FoldAdaptor adaptor) {
+ return binaryFold<DivFloorShapeOp, DivFoldAdaptor</*Ceil*/ false>>(this);
+}
+
+OpFoldResult tosa::ModShapeOp::fold(FoldAdaptor adaptor) {
+ return binaryFold<ModShapeOp, ModFoldAdaptor>(this);
+}
diff --git a/mlir/test/Dialect/Tosa/constant_folding.mlir b/mlir/test/Dialect/Tosa/constant_folding.mlir
index 4cb9a46e5d049..a8bcb9d52f000 100644
--- a/mlir/test/Dialect/Tosa/constant_folding.mlir
+++ b/mlir/test/Dialect/Tosa/constant_folding.mlir
@@ -695,6 +695,17 @@ func.func @test_fold_dim(%arg0: tensor<6xi32>) -> !tosa.shape<1> {
// -----
+// CHECK-LABEL: @test_fold_sub_shape
+// CHECK: tosa.const_shape {values = dense<[2, 4, 6, 8, 10, 12]> : tensor<6xindex>} : () -> !tosa.shape<6>
+func.func @test_fold_sub_shape() -> !tosa.shape<6> {
+ %a = tosa.const_shape {values = dense<[12, 22, 32, 42, 52, 62]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %b = tosa.const_shape {values = dense<[10, 18, 26, 34, 42, 50]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %c = tosa.sub_shape %a, %b : (!tosa.shape<6>, !tosa.shape<6>) -> !tosa.shape<6>
+ return %c : !tosa.shape<6>
+}
+
+// -----
+
// CHECK-LABEL: @test_no_fold_dim_unranked_input
// CHECK: tosa.dim
func.func @test_no_fold_dim_unranked_input(%arg0: tensor<*xi32>) -> !tosa.shape<1> {
@@ -704,9 +715,163 @@ func.func @test_no_fold_dim_unranked_input(%arg0: tensor<*xi32>) -> !tosa.shape<
// -----
+// CHECK-LABEL: @test_no_fold_sub_shape_positive_overflow
+// CHECK: tosa.sub_shape
+func.func @test_no_fold_sub_shape_positive_overflow() -> !tosa.shape<6> {
+ %a = tosa.const_shape {values = dense<[1, 2, 3, 4, 5, 9223372036854775807]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %b = tosa.const_shape {values = dense<[1, 2, 3, 4, 5, -1]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %c = tosa.sub_shape %a, %b : (!tosa.shape<6>, !tosa.shape<6>) -> !tosa.shape<6>
+ return %c : !tosa.shape<6>
+}
+
+// -----
+
// CHECK-LABEL: @test_no_fold_dim_dynamic
// CHECK: tosa.dim
func.func @test_no_fold_dim_dynamic(%arg0: tensor<4x?xi32>) -> !tosa.shape<1> {
%dim = tosa.dim %arg0 {axis = 1 : i32} : (tensor<4x?xi32>) -> !tosa.shape<1>
return %dim : !tosa.shape<1>
}
+
+// -----
+
+// CHECK-LABEL: @test_no_fold_sub_shape_negative_overflow
+// CHECK: tosa.sub_shape
+func.func @test_no_fold_sub_shape_negative_overflow() -> !tosa.shape<6> {
+ %a = tosa.const_shape {values = dense<[1, 2, 3, 4, 5, -9223372036854775808]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %b = tosa.const_shape {values = dense<[1, 2, 3, 4, 5, 1]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %c = tosa.sub_shape %a, %b : (!tosa.shape<6>, !tosa.shape<6>) -> !tosa.shape<6>
+ return %c : !tosa.shape<6>
+}
+
+// -----
+
+// CHECK-LABEL: @test_fold_mul_shape
+// CHECK: tosa.const_shape {values = dense<[2, 4, 6, 8, 10, 12]> : tensor<6xindex>} : () -> !tosa.shape<6>
+func.func @test_fold_mul_shape() -> !tosa.shape<6> {
+ %a = tosa.const_shape {values = dense<[2, 2, 3, 4, 2, 3]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %b = tosa.const_shape {values = dense<[1, 2, 2, 2, 5, 4]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %c = tosa.mul_shape %a, %b : (!tosa.shape<6>, !tosa.shape<6>) -> !tosa.shape<6>
+ return %c : !tosa.shape<6>
+}
+
+// -----
+
+// CHECK-LABEL: @test_no_fold_mul_shape_positive_overflow
+// CHECK: tosa.mul_shape
+func.func @test_no_fold_mul_shape_positive_overflow() -> !tosa.shape<6> {
+ %a = tosa.const_shape {values = dense<[1, 2, 3, 4, 5, 9223372036854775807]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %b = tosa.const_shape {values = dense<[1, 2, 3, 4, 5, 2]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %c = tosa.mul_shape %a, %b : (!tosa.shape<6>, !tosa.shape<6>) -> !tosa.shape<6>
+ return %c : !tosa.shape<6>
+}
+
+// -----
+
+// CHECK-LABEL: @test_no_fold_mul_shape_negative_overflow
+// CHECK: tosa.mul_shape
+func.func @test_no_fold_mul_shape_negative_overflow() -> !tosa.shape<6> {
+ %a = tosa.const_shape {values = dense<[1, 2, 3, 4, 5, -9223372036854775808]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %b = tosa.const_shape {values = dense<[1, 2, 3, 4, 5, 2]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %c = tosa.mul_shape %a, %b : (!tosa.shape<6>, !tosa.shape<6>) -> !tosa.shape<6>
+ return %c : !tosa.shape<6>
+}
+
+// -----
+
+// CHECK-LABEL: @test_fold_div_ceil_shape
+// CHECK: tosa.const_shape {values = dense<[2, 4, 6, 8, 10, 12]> : tensor<6xindex>} : () -> !tosa.shape<6>
+func.func @test_fold_div_ceil_shape() -> !tosa.shape<6> {
+ %a = tosa.const_shape {values = dense<[2, 7, 11, 22, 47, 46]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %b = tosa.const_shape {values = dense<[1, 2, 2, 3, 5, 4]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %c = tosa.div_ceil_shape %a, %b : (!tosa.shape<6>, !tosa.shape<6>) -> !tosa.shape<6>
+ return %c : !tosa.shape<6>
+}
+
+// -----
+
+// CHECK-LABEL: @test_no_fold_div_ceil_shape_positive_overflow
+// CHECK: tosa.div_ceil_shape
+func.func @test_no_fold_div_ceil_shape_positive_overflow() -> !tosa.shape<6> {
+ %a = tosa.const_shape {values = dense<[2, 7, 11, 22, 47, 9223372036854775807]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %b = tosa.const_shape {values = dense<[1, 2, 2, 3, 5, 0]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %c = tosa.div_ceil_shape %a, %b : (!tosa.shape<6>, !tosa.shape<6>) -> !tosa.shape<6>
+ return %c : !tosa.shape<6>
+}
+
+// -----
+
+// CHECK-LABEL: @test_no_fold_div_ceil_shape_negative_overflow
+// CHECK: tosa.div_ceil_shape
+func.func @test_no_fold_div_ceil_shape_negative_overflow() -> !tosa.shape<6> {
+ %a = tosa.const_shape {values = dense<[2, 7, 11, 22, 47, -9223372036854775808]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %b = tosa.const_shape {values = dense<[1, 2, 2, 3, 5, 0]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %c = tosa.div_ceil_shape %a, %b : (!tosa.shape<6>, !tosa.shape<6>) -> !tosa.shape<6>
+ return %c : !tosa.shape<6>
+}
+
+// -----
+
+// CHECK-LABEL: @test_fold_div_floor_shape
+// CHECK: tosa.const_shape {values = dense<[2, 3, 5, 7, 9, 11]> : tensor<6xindex>} : () -> !tosa.shape<6>
+func.func @test_fold_div_floor_shape() -> !tosa.shape<6> {
+ %a = tosa.const_shape {values = dense<[2, 7, 11, 22, 47, 46]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %b = tosa.const_shape {values = dense<[1, 2, 2, 3, 5, 4]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %c = tosa.div_floor_shape %a, %b : (!tosa.shape<6>, !tosa.shape<6>) -> !tosa.shape<6>
+ return %c : !tosa.shape<6>
+}
+
+// -----
+
+// CHECK-LABEL: @test_no_fold_div_floor_shape_positive_overflow
+// CHECK: tosa.div_floor_shape
+func.func @test_no_fold_div_floor_shape_positive_overflow() -> !tosa.shape<6> {
+ %a = tosa.const_shape {values = dense<[2, 7, 11, 22, 47, 9223372036854775807]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %b = tosa.const_shape {values = dense<[1, 2, 2, 3, 5, 0]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %c = tosa.div_floor_shape %a, %b : (!tosa.shape<6>, !tosa.shape<6>) -> !tosa.shape<6>
+ return %c : !tosa.shape<6>
+}
+
+// -----
+
+// CHECK-LABEL: @test_no_fold_div_floor_shape_negative_overflow
+// CHECK: tosa.div_floor_shape
+func.func @test_no_fold_div_floor_shape_negative_overflow() -> !tosa.shape<6> {
+ %a = tosa.const_shape {values = dense<[2, 7, 11, 22, 47, -9223372036854775808]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %b = tosa.const_shape {values = dense<[1, 2, 2, 3, 5, 0]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %c = tosa.div_floor_shape %a, %b : (!tosa.shape<6>, !tosa.shape<6>) -> !tosa.shape<6>
+ return %c : !tosa.shape<6>
+}
+
+// -----
+
+// CHECK-LABEL: @test_fold_mod_shape
+// CHECK: tosa.const_shape {values = dense<[2, 1, 5, 7, 9, 11]> : tensor<6xindex>} : () -> !tosa.shape<6>
+func.func @test_fold_mod_shape() -> !tosa.shape<6> {
+ %a = tosa.const_shape {values = dense<[24, 7, 65, 33, 39, 39]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %b = tosa.const_shape {values = dense<[11, 2, 12, 13, 15, 14]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %c = tosa.mod_shape %a, %b : (!tosa.shape<6>, !tosa.shape<6>) -> !tosa.shape<6>
+ return %c : !tosa.shape<6>
+}
+
+// -----
+
+// CHECK-LABEL: @test_no_fold_mod_shape_positive_overflow
+// CHECK: tosa.mod_shape
+func.func @test_no_fold_mod_shape_positive_overflow() -> !tosa.shape<6> {
+ %a = tosa.const_shape {values = dense<[24, 7, 65, 33, 39, 9223372036854775807]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %b = tosa.const_shape {values = dense<[11, 2, 12, 13, 15, 0]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %c = tosa.mod_shape %a, %b : (!tosa.shape<6>, !tosa.shape<6>) -> !tosa.shape<6>
+ return %c : !tosa.shape<6>
+}
+
+// -----
+
+// CHECK-LABEL: @test_no_fold_mod_shape_negative_overflow
+// CHECK: tosa.mod_shape
+func.func @test_no_fold_mod_shape_negative_overflow() -> !tosa.shape<6> {
+ %a = tosa.const_shape {values = dense<[24, 7, 65, 33, 39, -9223372036854775808]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %b = tosa.const_shape {values = dense<[11, 2, 12, 13, 15, 0]> : tensor<6xindex>} : () -> !tosa.shape<6>
+ %c = tosa.mod_shape %a, %b : (!tosa.shape<6>, !tosa.shape<6>) -> !tosa.shape<6>
+ return %c : !tosa.shape<6>
+}
More information about the Mlir-commits
mailing list