This is an automated email from the ASF dual-hosted git repository.

tlopex pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git


The following commit(s) were added to refs/heads/main by this push:
     new 0b0afd8dd3 [Relax][Frontend][TFLite] Add CUMSUM operator mapping 
(#19434)
0b0afd8dd3 is described below

commit 0b0afd8dd3e3cc1e17512a9a8e11d7db55285b2c
Author: Peruere1828 <[email protected]>
AuthorDate: Sat Apr 25 04:54:18 2026 +0800

    [Relax][Frontend][TFLite] Add CUMSUM operator mapping (#19434)
    
    This commit adds frontend support for the TFLite `CUMSUM` operator by
    lowering it to `relax.op.cumsum`.
    
    Specifically, it handles:
    - Extracting the `axis` parameter from a constant tensor and converting
    it to an integer.
    - Parsing the `exclusive` flag from `CumsumOptions` via FlatBuffers.
    - Deriving the target `dtype` from the output tensor.
    - Raising a `NotImplementedError` for the `reverse` flag as it is not
    yet supported by the Relax op.
    
    Tracked in apache#19412.
---
 .../tvm/relax/frontend/tflite/tflite_frontend.py   | 44 ++++++++++++++++++++++
 tests/python/relax/test_frontend_tflite.py         | 35 +++++++++++++++++
 2 files changed, 79 insertions(+)

diff --git a/python/tvm/relax/frontend/tflite/tflite_frontend.py 
b/python/tvm/relax/frontend/tflite/tflite_frontend.py
index 334021b903..d773d8d7ce 100644
--- a/python/tvm/relax/frontend/tflite/tflite_frontend.py
+++ b/python/tvm/relax/frontend/tflite/tflite_frontend.py
@@ -129,6 +129,7 @@ class OperatorConverter:
             "CONCATENATION": self.convert_concatenation,
             "CONV_2D": functools.partial(self.convert_conv, 
conv_type="conv2d"),
             "COS": functools.partial(self._convert_unary_elemwise, 
relax_op=_op.cos),
+            "CUMSUM": self.convert_cumsum,
             "DENSIFY": self.convert_densify,
             "DEPTH_TO_SPACE": self.convert_depth_to_space,
             "DEPTHWISE_CONV_2D": functools.partial(self.convert_conv, 
conv_type="depthwise"),
@@ -1426,6 +1427,49 @@ class OperatorConverter:
             rhs_expr = self.get_tensor_expr(rhs_tensor)
             lhs_expr = relax.op.add(lhs_expr, rhs_expr)
         return lhs_expr
+    
+    def convert_cumsum(self, op):
+        """Convert TFLite CUMSUM"""
+        if self.is_quantized(op):
+            raise tvm.error.OpNotImplemented(
+                "The TFLite to Relax converter does not support quantized 
CUMSUM operator yet."
+            )
+
+        from tflite.BuiltinOptions import BuiltinOptions
+        from tflite.CumsumOptions import CumsumOptions
+
+        input_tensors = self.get_input_tensors(op)
+        assert len(input_tensors) == 2, "input tensors length should be 2"
+        
+        input_expr = self.get_tensor_expr(input_tensors[0])
+
+        if self.has_expr(input_tensors[1].tensor_idx):
+            raise tvm.error.OpNotImplemented(
+                "The TFLite to Relax converter does not support dynamic axis 
for CUMSUM yet."
+            )
+        axis = self.get_tensor_value(input_tensors[1])
+        if isinstance(axis, np.ndarray):
+            assert axis.size == 1, "only one value is expected."
+            axis = int(axis.flat[0])
+
+        assert op.BuiltinOptionsType() == BuiltinOptions.CumsumOptions
+        op_options = op.BuiltinOptions()
+        cumsum_options = CumsumOptions()
+        cumsum_options.Init(op_options.Bytes, op_options.Pos)
+        exclusive = cumsum_options.Exclusive()
+        if cumsum_options.Reverse():
+            raise tvm.error.OpNotImplemented(
+                "The TFLite to Relax converter does not support reverse CUMSUM 
operator yet."
+            )
+        
+        output_tensors = self.get_output_tensors(op)
+        assert len(output_tensors) == 1, "output tensors length should be 1"
+
+        out_dtype = self.get_tensor_type_str(output_tensors[0].tensor.Type())
+
+        out = relax.op.cumsum(input_expr, axis, out_dtype, exclusive)
+
+        return out
 
     def convert_squared_difference(self, op):
         """Convert TFLite SQUARED DIFFERENCE"""
diff --git a/tests/python/relax/test_frontend_tflite.py 
b/tests/python/relax/test_frontend_tflite.py
index 92080634e2..15ca1cacf1 100644
--- a/tests/python/relax/test_frontend_tflite.py
+++ b/tests/python/relax/test_frontend_tflite.py
@@ -142,6 +142,41 @@ def test_add_n():
     verify(AddN, Expected)
 
 
+def test_cumsum():
+    class Cumsum(tf.Module):
+        @tf.function(
+            input_signature=[
+                tf.TensorSpec(shape=(3, 4), dtype=tf.float32),
+                tf.TensorSpec(shape=(5, 6), dtype=tf.int32)
+            ]
+        )
+        def func(self, x, y):
+            out1 = tf.math.cumsum(x, axis=0)
+            out2 = tf.math.cumsum(y, axis=1, exclusive=True)
+            return out1, out2
+
+    @I.ir_module
+    class Expected:
+        @R.function
+        def main(
+            x: R.Tensor((3, 4), dtype="float32"),
+            y: R.Tensor((5, 6), dtype="int32"),
+        ) -> R.Tuple(R.Tensor((3, 4), dtype="float32"), R.Tensor((5, 6), 
dtype="int32")):
+            R.func_attr({"num_input": 2})
+            with R.dataflow():
+                gv1: R.Tensor((3, 4), dtype="float32") = R.cumsum(
+                    x, axis=0, dtype="float32", exclusive=False
+                )
+                gv2: R.Tensor((5, 6), dtype="int32") = R.cumsum(
+                    y, axis=1, dtype="int32", exclusive=True
+                )
+                gv = (gv1, gv2)
+                R.output(gv)
+            return gv
+
+    verify(Cumsum, Expected)
+
+
 def test_split():
     class Split(tf.Module):
         @tf.function(input_signature=[tf.TensorSpec(shape=(1, 30), 
dtype=tf.float32)])

Reply via email to