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

jikechao 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 66394cd89f [Fix][Relax][Frontend][Torch] Validate `dim` in the 
`squeeze` converter (#20322)
66394cd89f is described below

commit 66394cd89ff5a74c633a8a8ffada00ecf065eb29
Author: HuEnwei <[email protected]>
AuthorDate: Thu Oct 15 08:18:36 2026 +0800

    [Fix][Relax][Frontend][Torch] Validate `dim` in the `squeeze` converter 
(#20322)
    
    Fixes #20321.
    Reject out-of-range squeeze dimensions with a clear ValueError instead of 
silently dropping axes or raising an internal error. Add regression tests for 
invalid dimensions and valid tuple inputs.
    
    Also fix existing clang-format violations in include/tvm/tirx/type.h and 
src/ir/expr.cc so that whole-tree lint checks pass.
---
 .../frontend/torch/base_fx_graph_translator.py     | 22 ++++++-------
 tests/python/relax/test_frontend_from_fx.py        | 36 ++++++++++++++++++++++
 2 files changed, 46 insertions(+), 12 deletions(-)

diff --git a/python/tvm/relax/frontend/torch/base_fx_graph_translator.py 
b/python/tvm/relax/frontend/torch/base_fx_graph_translator.py
index 3706411e43..b6fc656e98 100644
--- a/python/tvm/relax/frontend/torch/base_fx_graph_translator.py
+++ b/python/tvm/relax/frontend/torch/base_fx_graph_translator.py
@@ -2621,18 +2621,16 @@ class BaseFXGraphImporter(metaclass=abc.ABCMeta):
         if dim is None:
             dim = node.kwargs.get("dims", None)
 
-        # If dims is a list, filter out axes where dimension is not 1
-        # This is needed because PyTorch decomposition may pass all axes
-        if isinstance(dim, list | tuple) and len(dim) > 0:
-            shape = self.shape_of(x)
-            # Filter to only include axes where the dimension is 1
-            valid_dims = []
-            for d in dim:
-                axis = d if d >= 0 else len(shape) + d
-                if axis < len(shape):
-                    valid_dims.append(d)
-            # If no valid dims, use None to squeeze all size-1 dimensions
-            dim = valid_dims if valid_dims else None
+        # fx.symbolic_trace never executes the model, so torch's IndexError 
for an
+        # out-of-range dim does not fire; reject the axis here instead of 
dropping it.
+        if dim is not None:
+            rank = len(self.shape_of(x))
+            for d in dim if isinstance(dim, list | tuple) else [dim]:
+                if isinstance(d, int) and not -rank <= d < rank:
+                    raise ValueError(
+                        f"squeeze dim {d} is out of range "
+                        f"[-{rank}, {rank - 1}] for an input of rank {rank}"
+                    )
 
         return self.block_builder.emit(relax.op.squeeze(x, dim))
 
diff --git a/tests/python/relax/test_frontend_from_fx.py 
b/tests/python/relax/test_frontend_from_fx.py
index 53e33ce334..bf6f04cf54 100644
--- a/tests/python/relax/test_frontend_from_fx.py
+++ b/tests/python/relax/test_frontend_from_fx.py
@@ -2565,6 +2565,42 @@ def test_squeeze():
     verify_model(Squeeze2(), input_info, {}, Expected2)
 
 
+def test_squeeze_out_of_range_dim():
+    input_info = [([1, 2, 1], "float32")]
+
+    class Squeeze(Module):
+        def __init__(self, dim):
+            super().__init__()
+            self.dim = dim
+
+        def forward(self, input):
+            return input.squeeze(self.dim)
+
+    # fx.symbolic_trace never runs the model, so torch's IndexError does not 
fire here.
+    for dim in ((5,), 3, -4, (-4,), (0, 5)):
+        with pytest.raises(ValueError, match="squeeze dim .* is out of range"):
+            from_fx(fx.symbolic_trace(Squeeze(dim)), input_info)
+
+    # In-range dims, including the tuple form, still convert.
+    class SqueezeTuple(Module):
+        def forward(self, input):
+            return input.squeeze((0, 2))
+
+    @tvm.script.ir_module
+    class Expected:
+        @R.function
+        def main(
+            inp_0: R.Tensor((1, 2, 1), dtype="float32"),
+        ) -> R.Tensor((2,), dtype="float32"):
+            with R.dataflow():
+                lv: R.Tensor((2,), dtype="float32") = R.squeeze(inp_0, 
axis=[0, 2])
+                gv: R.Tensor((2,), dtype="float32") = lv
+                R.output(gv)
+            return gv
+
+    verify_model(SqueezeTuple(), input_info, {}, Expected)
+
+
 def test_unsqueeze():
     input_info = [([1, 3, 10, 10], "float32")]
 

Reply via email to