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 9f1e1980c1 [Tests][Frontend] Remove redundant PyTorch frontend tests 
(#20021)
9f1e1980c1 is described below

commit 9f1e1980c1442652df69d64f506c5e5e70efdebe
Author: Shushi Hong <[email protected]>
AuthorDate: Thu Jul 16 23:06:12 2026 -0400

    [Tests][Frontend] Remove redundant PyTorch frontend tests (#20021)
    
    This PR:
    - Removes duplicate module/functional, alias, positional-argument, and
    no-op cases from the PyTorch ExportedProgram tests.
    - Consolidates the four GRU configurations into a table-driven loop
    without removing any configurations.
    - Removes duplicated FX cases already covered through the same shared
    converters.
    - Restores FX scalar tensor constant coverage and TFLite
    constant-parameter Gather and static broadcast/MUL coverage.
---
 .../relax/test_frontend_from_exported_program.py   | 715 ++-------------------
 tests/python/relax/test_frontend_from_fx.py        | 468 +-------------
 tests/python/relax/test_frontend_tflite.py         |  69 ++
 3 files changed, 147 insertions(+), 1105 deletions(-)

diff --git a/tests/python/relax/test_frontend_from_exported_program.py 
b/tests/python/relax/test_frontend_from_exported_program.py
index 1f78e941e4..3799b8ed95 100644
--- a/tests/python/relax/test_frontend_from_exported_program.py
+++ b/tests/python/relax/test_frontend_from_exported_program.py
@@ -14,7 +14,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-# ruff: noqa: E501, F401, F841
+# ruff: noqa: F401, F841
 import operator
 
 import numpy as np
@@ -222,15 +222,7 @@ def test_extended_unary_ops():
     example_args = (torch.randn(1, 3, 10, 10, dtype=torch.float32),)
 
     # celu
-    class Celu1(Module):
-        def __init__(self):
-            super().__init__()
-            self.celu = torch.nn.CELU()
-
-        def forward(self, input):
-            return self.celu(input)
-
-    class Celu2(Module):
+    class Celu(Module):
         def forward(self, input):
             return torch.nn.functional.celu(input)
 
@@ -254,8 +246,7 @@ def test_extended_unary_ops():
                 R.output(gv)
             return gv
 
-    verify_model(Celu1(), example_args, {}, expected_celu)
-    verify_model(Celu2(), example_args, {}, expected_celu)
+    verify_model(Celu(), example_args, {}, expected_celu)
 
     # clamp
     class Clamp(Module):
@@ -330,15 +321,7 @@ def test_extended_unary_ops():
 
     # dropout
 
-    class Dropout1(Module):
-        def __init__(self):
-            super().__init__()
-            self.dropout = torch.nn.Dropout(0.5)
-
-        def forward(self, input):
-            return self.dropout(input)
-
-    class Dropout2(Module):
+    class Dropout(Module):
         def forward(self, input):
             return torch.dropout(input, 0.5, train=True)
 
@@ -377,20 +360,11 @@ def test_extended_unary_ops():
                 R.output(gv)
             return gv
 
-    verify_model(Dropout1(), example_args, {}, expected_dropout_for_1_2)
-    verify_model(Dropout2(), example_args, {}, expected_dropout_for_1_2)
+    verify_model(Dropout(), example_args, {}, expected_dropout_for_1_2)
     verify_model(Dropout3(), example_args, {}, expected_dropout_for_3)
 
     # elu
     class Elu(Module):
-        def __init__(self):
-            super().__init__()
-            self.elu = torch.nn.ELU()
-
-        def forward(self, input):
-            return self.elu(input)
-
-    class Elu2(Module):
         def forward(self, input):
             return torch.nn.functional.elu(input)
 
@@ -416,18 +390,9 @@ def test_extended_unary_ops():
             return gv
 
     verify_model(Elu(), example_args, {}, expected_elu)
-    verify_model(Elu2(), example_args, {}, expected_elu)
 
     # hardsigmoid
     class Hardsigmoid(torch.nn.Module):
-        def __init__(self):
-            super().__init__()
-            self.hs = torch.nn.Hardsigmoid()
-
-        def forward(self, input):
-            return self.hs(input)
-
-    class Hardsigmoid2(torch.nn.Module):
         def forward(self, input):
             return torch.nn.functional.hardsigmoid(input)
 
@@ -455,18 +420,9 @@ def test_extended_unary_ops():
             return gv
 
     verify_model(Hardsigmoid(), example_args, {}, expected_hardsigmoid)
-    verify_model(Hardsigmoid2(), example_args, {}, expected_hardsigmoid)
 
     # hardwish
     class Hardswish(torch.nn.Module):
-        def __init__(self):
-            super().__init__()
-            self.hs = torch.nn.Hardswish()
-
-        def forward(self, input):
-            return self.hs(input)
-
-    class Hardswish2(torch.nn.Module):
         def forward(self, input):
             return torch.nn.functional.hardswish(input)
 
@@ -523,7 +479,6 @@ def test_extended_unary_ops():
             return gv
 
     verify_model(Hardswish(), example_args, {}, expected_hardswish_for_1_2)
-    verify_model(Hardswish2(), example_args, {}, expected_hardswish_for_1_2)
     verify_model(Hardswish3(), example_args, {}, expected_hardswish_for_3)
 
     # isfinite
@@ -846,14 +801,6 @@ def test_extended_unary_ops():
 
 def test_hardtanh():
     class Hardtanh(torch.nn.Module):
-        def __init__(self):
-            super().__init__()
-            self.ht = torch.nn.Hardtanh()
-
-        def forward(self, input):
-            return self.ht(input)
-
-    class Hardtanh2(torch.nn.Module):
         def forward(self, input):
             return torch.nn.functional.hardtanh(input)
 
@@ -877,26 +824,12 @@ def test_hardtanh():
 
     example_args = (torch.randn(1, 3, 10, 10, dtype=torch.float32),)
     verify_model(Hardtanh(), example_args, {}, expected_for_1_2)
-    verify_model(Hardtanh2(), example_args, {}, expected_for_1_2)
     # In-place hardtanh_ yields the same program; mutation outputs are dropped.
     verify_model(Hardtanh3(), example_args, {}, expected_for_1_2)
 
 
 def test_softplus():
-    import torch
-    from torch.nn import Module
-
-    torch.set_grad_enabled(False)
-
-    class Softplus0(torch.nn.Module):
-        def __init__(self):
-            super().__init__()
-            self.softplus = torch.nn.Softplus(1.0, 20.0)
-
-        def forward(self, x):
-            return self.softplus(x)
-
-    class Softplus1(Module):
+    class Softplus(Module):
         def forward(self, input):
             return torch.nn.functional.softplus(input, 1.0, 20.0)
 
@@ -925,25 +858,11 @@ def test_softplus():
             return gv
 
     example_args = (torch.randn(1, 3, 10, 10, dtype=torch.float32),)
-    verify_model(Softplus0(), example_args, {}, expected)
-    verify_model(Softplus1(), example_args, {}, expected)
+    verify_model(Softplus(), example_args, {}, expected)
 
 
 def test_leakyrelu():
-    import torch
-    from torch.nn import Module
-
-    torch.set_grad_enabled(False)
-
-    class LeakyReLU0(Module):
-        def __init__(self):
-            super().__init__()
-            self.leakyrelu = torch.nn.LeakyReLU(0.02)
-
-        def forward(self, input):
-            return self.leakyrelu(input)
-
-    class LeakyReLU1(Module):
+    class LeakyReLU(Module):
         def forward(self, input):
             return torch.nn.functional.leaky_relu(input, 0.02)
 
@@ -965,8 +884,7 @@ def test_leakyrelu():
             return gv
 
     example_args = (torch.randn(1, 3, 10, 10, dtype=torch.float32),)
-    verify_model(LeakyReLU0(), example_args, {}, expected_for_1_2)
-    verify_model(LeakyReLU1(), example_args, {}, expected_for_1_2)
+    verify_model(LeakyReLU(), example_args, {}, expected_for_1_2)
     # In-place leaky_relu_ yields the same program; mutation outputs are 
dropped.
     verify_model(LeakyReLU2(), example_args, {}, expected_for_1_2)
 
@@ -1173,14 +1091,6 @@ def test_pow_integer():
 
 def test_logsoftmax():
     class LogSoftmax(Module):
-        def __init__(self):
-            super().__init__()
-            self.lsm = torch.nn.LogSoftmax(dim=1)
-
-        def forward(self, input):
-            return self.lsm(input)
-
-    class LogSoftmax2(Module):
         def forward(self, input):
             return torch.nn.functional.log_softmax(input, dim=1)
 
@@ -1199,19 +1109,10 @@ def test_logsoftmax():
 
     example_args = (torch.randn(1, 3, 10, 10, dtype=torch.float32),)
     verify_model(LogSoftmax(), example_args, {}, expected1)
-    verify_model(LogSoftmax2(), example_args, {}, expected1)
 
 
 def test_prelu():
-    class Prelu1(Module):
-        def __init__(self, num_parameters=1, alpha=0.25):
-            super().__init__()
-            self.prelu = torch.nn.PReLU(num_parameters=num_parameters, 
init=alpha)
-
-        def forward(self, x):
-            return self.prelu(x)
-
-    class Prelu2(torch.nn.Module):
+    class Prelu(torch.nn.Module):
         def __init__(self):
             super().__init__()
             self.alpha = torch.nn.Parameter(torch.tensor([0.25]))
@@ -1237,20 +1138,11 @@ def test_prelu():
             return gv
 
     example_args = (torch.randn(1, 3, 10, 10, dtype=torch.float32),)
-    verify_model(Prelu1(), example_args, {}, expected)
-    verify_model(Prelu2(), example_args, {}, expected)
+    verify_model(Prelu(), example_args, {}, expected)
 
 
 def test_softmax():
     class Softmax(Module):
-        def __init__(self):
-            super().__init__()
-            self.sm = torch.nn.Softmax(dim=1)
-
-        def forward(self, input):
-            return self.sm(input)
-
-    class Softmax2(Module):
         def forward(self, input):
             return torch.nn.functional.softmax(input, dim=1)
 
@@ -1269,19 +1161,10 @@ def test_softmax():
 
     example_args = (torch.randn(1, 3, 10, 10, dtype=torch.float32),)
     verify_model(Softmax(), example_args, {}, expected1)
-    verify_model(Softmax2(), example_args, {}, expected1)
 
 
 def test_softsign():
     class Softsign(Module):
-        def __init__(self):
-            super().__init__()
-            self.ss = torch.nn.Softsign()
-
-        def forward(self, input):
-            return self.ss(input)
-
-    class Softsign2(Module):
         def forward(self, input):
             return torch.nn.functional.softsign(input)
 
@@ -1301,19 +1184,10 @@ def test_softsign():
 
     example_args = (torch.randn(1, 3, 10, 10, dtype=torch.float32),)
     verify_model(Softsign(), example_args, {}, expected_softsign)
-    verify_model(Softsign2(), example_args, {}, expected_softsign)
 
 
 def test_softshrink():
     class Softshrink(Module):
-        def __init__(self):
-            super().__init__()
-            self.softshrink = torch.nn.Softshrink(lambd=0.5)
-
-        def forward(self, input):
-            return self.softshrink(input)
-
-    class Softshrink2(Module):
         def forward(self, input):
             return torch.nn.functional.softshrink(input, lambd=0.5)
 
@@ -1341,7 +1215,6 @@ def test_softshrink():
 
     example_args = (torch.randn(1, 3, 10, 10, dtype=torch.float32),)
     verify_model(Softshrink(), example_args, {}, expected_softshrink)
-    verify_model(Softshrink2(), example_args, {}, expected_softshrink)
 
 
 def test_tril_triu():
@@ -1411,7 +1284,6 @@ def test_tril_triu():
 operator_binary_1 = [
     (operator.add, R.add),
     (torch.ops.aten.add_, R.add),
-    (torch.ops.aten.bitwise_or, R.bitwise_or),
     (torch.ops.aten.bitwise_or_, R.bitwise_or),
     (operator.sub, R.subtract),
     (operator.mul, R.multiply),
@@ -1996,15 +1868,7 @@ def test_batchnorm2d():
 
 
 def test_adaptive_avgpool1d():
-    class AdaptiveAvgPool1d0(torch.nn.Module):
-        def __init__(self):
-            super().__init__()
-            self.pool = torch.nn.AdaptiveAvgPool1d(output_size=5)
-
-        def forward(self, input):
-            return self.pool(input)
-
-    class AdaptiveAvgPool1d1(torch.nn.Module):
+    class AdaptiveAvgPool1d(torch.nn.Module):
         def forward(self, input):
             return torch.nn.functional.adaptive_avg_pool1d(input, 
output_size=5)
 
@@ -2025,20 +1889,11 @@ def test_adaptive_avgpool1d():
             return gv
 
     example_args = (torch.randn(1, 3, 10, dtype=torch.float32),)
-    verify_model(AdaptiveAvgPool1d0(), example_args, {}, expected1)
-    verify_model(AdaptiveAvgPool1d1(), example_args, {}, expected1)
+    verify_model(AdaptiveAvgPool1d(), example_args, {}, expected1)
 
 
 def test_adaptive_avgpool2d():
-    class AdaptiveAvgPool2d0(Module):
-        def __init__(self):
-            super().__init__()
-            self.pool = torch.nn.AdaptiveAvgPool2d([10, 10])
-
-        def forward(self, input):
-            return self.pool(input)
-
-    class AdaptiveAvgPool2d1(Module):
+    class AdaptiveAvgPool2d(Module):
         def forward(self, input):
             return torch.nn.functional.adaptive_avg_pool2d(input, [10, 10])
 
@@ -2058,20 +1913,11 @@ def test_adaptive_avgpool2d():
             return gv
 
     example_args = (torch.randn(1, 3, 10, 10, dtype=torch.float32),)
-    verify_model(AdaptiveAvgPool2d0(), example_args, {}, expected1)
-    verify_model(AdaptiveAvgPool2d1(), example_args, {}, expected1)
+    verify_model(AdaptiveAvgPool2d(), example_args, {}, expected1)
 
 
 def test_adaptive_avgpool3d():
-    class AdaptiveAvgPool3d0(torch.nn.Module):
-        def __init__(self):
-            super().__init__()
-            self.pool = torch.nn.AdaptiveAvgPool3d([4, 4, 4])
-
-        def forward(self, input):
-            return self.pool(input)
-
-    class AdaptiveAvgPool3d1(torch.nn.Module):
+    class AdaptiveAvgPool3d(torch.nn.Module):
         def forward(self, input):
             return torch.nn.functional.adaptive_avg_pool3d(input, [4, 4, 4])
 
@@ -2090,8 +1936,7 @@ def test_adaptive_avgpool3d():
             return gv
 
     example_args = (torch.randn(1, 3, 8, 8, 8, dtype=torch.float32),)
-    verify_model(AdaptiveAvgPool3d0(), example_args, {}, expected1)
-    verify_model(AdaptiveAvgPool3d1(), example_args, {}, expected1)
+    verify_model(AdaptiveAvgPool3d(), example_args, {}, expected1)
 
 
 def test_addmm():
@@ -2244,14 +2089,6 @@ def test_avg_pool1d():
             return gv
 
     class AvgPool1d2(Module):
-        def __init__(self):
-            super().__init__()
-            self.pool = torch.nn.AvgPool1d(kernel_size=3, stride=2, padding=1, 
ceil_mode=True)
-
-        def forward(self, input):
-            return self.pool(input)
-
-    class AvgPool1d3(Module):
         def forward(self, input):
             return torch.nn.functional.avg_pool1d(
                 input, kernel_size=3, stride=2, padding=1, ceil_mode=True
@@ -2312,7 +2149,6 @@ def test_avg_pool1d():
     example_args = (torch.randn(1, 3, 10, dtype=torch.float32),)
     verify_model(AvgPool1d1(), example_args, {}, expected1)
     verify_model(AvgPool1d2(), example_args, {}, expected2)
-    verify_model(AvgPool1d3(), example_args, {}, expected2)
     verify_model(AvgPool1d4(), example_args, {}, expected3)
 
 
@@ -2348,14 +2184,6 @@ def test_avg_pool2d():
             return gv
 
     class AvgPool2d2(Module):
-        def __init__(self):
-            super().__init__()
-            self.pool = torch.nn.AvgPool2d(kernel_size=[4, 4], stride=2, 
padding=2, ceil_mode=True)
-
-        def forward(self, input):
-            return self.pool(input)
-
-    class AvgPool2d3(Module):
         def forward(self, input):
             return torch.nn.functional.avg_pool2d(
                 input, kernel_size=[4, 4], stride=2, padding=2, ceil_mode=True
@@ -2434,7 +2262,6 @@ def test_avg_pool2d():
     example_args = (torch.randn(1, 3, 10, 10, dtype=torch.float32),)
     verify_model(AvgPool2d1(), example_args, {}, expected1)
     verify_model(AvgPool2d2(), example_args, {}, expected2)
-    verify_model(AvgPool2d3(), example_args, {}, expected2)
     verify_model(AvgPool2d4(), example_args, {}, expected4)
     verify_model(AvgPool2d5(), example_args, {}, expected5)
 
@@ -2471,14 +2298,6 @@ def test_avg_pool3d():
             return gv
 
     class AvgPool3d2(Module):
-        def __init__(self):
-            super().__init__()
-            self.pool = torch.nn.AvgPool3d(kernel_size=3, stride=2, padding=1, 
ceil_mode=True)
-
-        def forward(self, input):
-            return self.pool(input)
-
-    class AvgPool3d3(Module):
         def forward(self, input):
             return torch.nn.functional.avg_pool3d(
                 input, kernel_size=3, stride=2, padding=1, ceil_mode=True
@@ -2531,7 +2350,6 @@ def test_avg_pool3d():
     example_args = (torch.randn(1, 3, 8, 8, 8, dtype=torch.float32),)
     verify_model(AvgPool3d1(), example_args, {}, expected1)
     verify_model(AvgPool3d2(), example_args, {}, expected2)
-    verify_model(AvgPool3d3(), example_args, {}, expected2)
     verify_model(AvgPool3d4(), example_args, {}, expected3)
 
 
@@ -3429,15 +3247,7 @@ def test_pad():
 
 
 def test_pixel_shuffle():
-    class PixelShuffle1(torch.nn.Module):
-        def __init__(self, upscale_factor=2):
-            super().__init__()
-            self.pixel_shuffle = torch.nn.PixelShuffle(upscale_factor)
-
-        def forward(self, x):
-            return self.pixel_shuffle(x)
-
-    class PixelShuffle2(torch.nn.Module):
+    class PixelShuffle(torch.nn.Module):
         def __init__(self, upscale_factor=2):
             super().__init__()
             self.upscale_factor = upscale_factor
@@ -3466,8 +3276,7 @@ def test_pixel_shuffle():
             return gv
 
     example_args = (torch.randn(1, 8, 10, 15, dtype=torch.float32),)
-    verify_model(PixelShuffle1(upscale_factor=2), example_args, {}, expected)
-    verify_model(PixelShuffle2(upscale_factor=2), example_args, {}, expected)
+    verify_model(PixelShuffle(upscale_factor=2), example_args, {}, expected)
 
 
 def test_einsum():
@@ -3574,12 +3383,6 @@ def test_embedding():
 
 
 def test_groupnorm():
-    import torch
-    from torch.nn import Module
-
-    torch.set_grad_enabled(False)
-    torch.random.manual_seed(0)
-
     class GroupNorm(Module):
         def __init__(self):
             super().__init__()
@@ -3623,9 +3426,6 @@ def test_groupnorm():
 
 
 def test_instancenorm2d():
-    torch.set_grad_enabled(False)
-    torch.random.manual_seed(0)
-
     class InstanceNorm2d(Module):
         def __init__(self):
             super().__init__()
@@ -3792,14 +3592,6 @@ def test_linear():
 
 def test_maxpool1d():
     class MaxPool1d(Module):
-        def __init__(self):
-            super().__init__()
-            self.pool = torch.nn.MaxPool1d(kernel_size=2)
-
-        def forward(self, input):
-            return self.pool(input)
-
-    class MaxPool1d_functional(Module):
         def __init__(self):
             super().__init__()
 
@@ -3842,34 +3634,6 @@ def test_maxpool1d():
                 R.output(gv)
             return gv
 
-    @tvm.script.ir_module
-    class expected2:
-        @R.function
-        def main(input_1: R.Tensor((1, 3, 8), dtype="float32")) -> R.Tuple(
-            R.Tensor((1, 3, 4), dtype="float32")
-        ):
-            with R.dataflow():
-                lv: R.Tensor((1, 3, 1, 8), dtype="float32") = 
R.expand_dims(input_1, axis=[-2])
-                lv1: R.Tensor((1, 3, 1, 4), dtype="float32") = R.nn.max_pool2d(
-                    lv,
-                    pool_size=[1, 2],
-                    strides=[1, 2],
-                    dilation=[1, 1],
-                    padding=[0, 0, 0, 0],
-                    layout="NCHW",
-                    out_layout="NCHW",
-                )
-                lv2: R.Tensor((1, 3, 1, 4), dtype="float32") = 
R.zeros_like(lv1)
-                lv3: R.Tuple(
-                    R.Tensor((1, 3, 1, 4), dtype="float32"),
-                    R.Tensor((1, 3, 1, 4), dtype="float32"),
-                ) = (lv1, lv2)
-                lv4: R.Tensor((1, 3, 1, 4), dtype="float32") = lv3[0]
-                lv5: R.Tensor((1, 3, 4), dtype="float32") = R.squeeze(lv4, 
axis=[-2])
-                gv: R.Tuple(R.Tensor((1, 3, 4), dtype="float32")) = (lv5,)
-                R.output(gv)
-            return gv
-
     @tvm.script.ir_module
     class expected3:
         @R.function
@@ -3900,12 +3664,10 @@ def test_maxpool1d():
 
     # Example inputs
     example_args1 = (torch.randn(1, 3, 8, dtype=torch.float32),)
-    example_args2 = (torch.randn(1, 3, 8, dtype=torch.float32),)
     example_args3 = (torch.randn(1, 3, 10, dtype=torch.float32),)
 
     # Verify the models
     verify_model(MaxPool1d(), example_args1, {}, expected1)
-    verify_model(MaxPool1d_functional(), example_args2, {}, expected2)
     verify_model(MaxPool1d2(), example_args3, {}, expected3)
 
 
@@ -5195,7 +4957,7 @@ def test_argmax_argmin():
     verify_model(Argmin2(), example_args, {}, expected_argmin2)
 
 
-def test_cat_concat():
+def test_cat():
     class Cat0(Module):
         def forward(self, x, y):
             return torch.cat((x, y))
@@ -5204,14 +4966,6 @@ def test_cat_concat():
         def forward(self, x, y):
             return torch.cat((x, y), dim=1)
 
-    class Cat2(Module):
-        def forward(self, x, y):
-            return torch.cat((x, y), 1)
-
-    class Cat3(Module):
-        def forward(self, x, y):
-            return torch.concat((x, y), dim=0)
-
     @I.ir_module
     class Expected1:
         @R.function
@@ -5241,8 +4995,6 @@ def test_cat_concat():
     example_args = (torch.randn(2, 3, dtype=torch.float32), torch.randn(2, 3, 
dtype=torch.float32))
     verify_model(Cat0(), example_args, {}, Expected1)
     verify_model(Cat1(), example_args, {}, Expected2)
-    verify_model(Cat2(), example_args, {}, Expected2)
-    verify_model(Cat3(), example_args, {}, Expected1)
 
 
 def test_cumsum():
@@ -5376,10 +5128,6 @@ def test_permute():
         def forward(self, x):
             return x.permute(0, 3, 2, 1)
 
-    class Permute2(Module):
-        def forward(self, x):
-            return torch.permute(x, (0, 3, 2, 1))
-
     @tvm.script.ir_module
     class expected1:
         @R.function
@@ -5395,7 +5143,6 @@ def test_permute():
 
     example_args = (torch.randn(1, 2, 3, 4, dtype=torch.float32),)
     verify_model(Permute1(), example_args, {}, expected1)
-    verify_model(Permute2(), example_args, {}, expected1)
 
 
 def test_repeat():
@@ -5437,9 +5184,6 @@ def test_repeat():
     example_args = (torch.randn(1, 3, dtype=torch.float32),)
     verify_model(Tile2(), example_args, {}, expected2)
 
-    example_args = (torch.randn(1, 3, dtype=torch.float32),)
-    verify_model(Tile2(), example_args, {}, expected2)
-
 
 def test_reshape():
     class Reshape(Module):
@@ -5776,7 +5520,6 @@ def test_split():
             R.Tensor((1, 1, 10, 10), dtype="float32"),
             R.Tensor((1, 1, 10, 10), dtype="float32"),
         ):
-            # block 0
             with R.dataflow():
                 lv: R.Tuple(
                     R.Tensor((1, 1, 10, 10), dtype="float32"),
@@ -5794,111 +5537,9 @@ def test_split():
                 R.output(gv)
             return gv
 
-    class Unbind1(Module):
-        def forward(self, data):
-            return torch.unbind(data)
-
-    @tvm.script.ir_module
-    class expected1:
-        @R.function
-        def main(data: R.Tensor((3, 3, 10, 10), dtype="float32")) -> R.Tuple(
-            R.Tensor((3, 10, 10), dtype="float32"),
-            R.Tensor((3, 10, 10), dtype="float32"),
-            R.Tensor((3, 10, 10), dtype="float32"),
-        ):
-            # block 0
-            with R.dataflow():
-                lv: R.Tensor((1, 3, 10, 10), dtype="float32") = 
R.strided_slice(
-                    data,
-                    (R.prim_value(0),),
-                    (R.prim_value(0),),
-                    (R.prim_value(1),),
-                    (R.prim_value(1),),
-                    assume_inbound=False,
-                )
-                lv1: R.Tensor((1, 3, 10, 10), dtype="float32") = 
R.strided_slice(
-                    data,
-                    (R.prim_value(0),),
-                    (R.prim_value(1),),
-                    (R.prim_value(2),),
-                    (R.prim_value(1),),
-                    assume_inbound=False,
-                )
-                lv2: R.Tensor((1, 3, 10, 10), dtype="float32") = 
R.strided_slice(
-                    data,
-                    (R.prim_value(0),),
-                    (R.prim_value(2),),
-                    (R.prim_value(3),),
-                    (R.prim_value(1),),
-                    assume_inbound=False,
-                )
-                lv3: R.Tensor((3, 10, 10), dtype="float32") = R.squeeze(lv, 
axis=[0])
-                lv4: R.Tensor((3, 10, 10), dtype="float32") = R.squeeze(lv1, 
axis=[0])
-                lv5: R.Tensor((3, 10, 10), dtype="float32") = R.squeeze(lv2, 
axis=[0])
-                gv: R.Tuple(
-                    R.Tensor((3, 10, 10), dtype="float32"),
-                    R.Tensor((3, 10, 10), dtype="float32"),
-                    R.Tensor((3, 10, 10), dtype="float32"),
-                ) = (lv3, lv4, lv5)
-                R.output(gv)
-            return gv
-
-    class Unbind2(Module):
-        def forward(self, data):
-            return torch.unbind(data, dim=1)
-
-    @tvm.script.ir_module
-    class expected2:
-        @R.function
-        def main(data: R.Tensor((3, 3, 10, 10), dtype="float32")) -> R.Tuple(
-            R.Tensor((3, 10, 10), dtype="float32"),
-            R.Tensor((3, 10, 10), dtype="float32"),
-            R.Tensor((3, 10, 10), dtype="float32"),
-        ):
-            # block 0
-            with R.dataflow():
-                lv: R.Tensor((3, 1, 10, 10), dtype="float32") = 
R.strided_slice(
-                    data,
-                    (R.prim_value(1),),
-                    (R.prim_value(0),),
-                    (R.prim_value(1),),
-                    (R.prim_value(1),),
-                    assume_inbound=False,
-                )
-                lv1: R.Tensor((3, 1, 10, 10), dtype="float32") = 
R.strided_slice(
-                    data,
-                    (R.prim_value(1),),
-                    (R.prim_value(1),),
-                    (R.prim_value(2),),
-                    (R.prim_value(1),),
-                    assume_inbound=False,
-                )
-                lv2: R.Tensor((3, 1, 10, 10), dtype="float32") = 
R.strided_slice(
-                    data,
-                    (R.prim_value(1),),
-                    (R.prim_value(2),),
-                    (R.prim_value(3),),
-                    (R.prim_value(1),),
-                    assume_inbound=False,
-                )
-                lv3: R.Tensor((3, 10, 10), dtype="float32") = R.squeeze(lv, 
axis=[1])
-                lv4: R.Tensor((3, 10, 10), dtype="float32") = R.squeeze(lv1, 
axis=[1])
-                lv5: R.Tensor((3, 10, 10), dtype="float32") = R.squeeze(lv2, 
axis=[1])
-                gv: R.Tuple(
-                    R.Tensor((3, 10, 10), dtype="float32"),
-                    R.Tensor((3, 10, 10), dtype="float32"),
-                    R.Tensor((3, 10, 10), dtype="float32"),
-                ) = (lv3, lv4, lv5)
-                R.output(gv)
-            return gv
-
     example_args = (torch.randn(1, 3, 10, 10, dtype=torch.float32),)
     verify_model(Chunk(), example_args, {}, Expected)
 
-    example_args = (torch.randn(3, 3, 10, 10, dtype=torch.float32),)
-    verify_model(Unbind1(), example_args, {}, expected1)
-    verify_model(Unbind2(), example_args, {}, expected2)
-
 
 def test_squeeze():
     class Squeeze1(Module):
@@ -5965,10 +5606,6 @@ def test_stack():
         def forward(self, x, y):
             return torch.stack((x, y), dim=1)
 
-    class Stack2(Module):
-        def forward(self, x, y):
-            return torch.stack((x, y), 1)  # positional dim
-
     class Stack3(Module):
         def forward(self, x, y):
             return torch.stack((x, y), dim=-1)  # negative dim
@@ -6020,7 +5657,6 @@ def test_stack():
 
     verify_model(Stack0(), example_args, {}, Expected0)
     verify_model(Stack1(), example_args, {}, Expected1)
-    verify_model(Stack2(), example_args, {}, Expected1)
     verify_model(Stack3(), example_args, {}, Expected3)
 
 
@@ -6033,10 +5669,6 @@ def test_tile():
         def forward(self, x):
             return x.tile(4, 2)
 
-    class Tile3(Module):
-        def forward(self, x):
-            return torch.tile(x, (4, 2))
-
     @tvm.script.ir_module
     class expected1:
         @R.function
@@ -6066,7 +5698,6 @@ def test_tile():
     example_args = (torch.randn(1, 3, dtype=torch.float32),)
     verify_model(Tile1(), example_args, {}, expected1)
     verify_model(Tile2(), example_args, {}, expected2)
-    verify_model(Tile3(), example_args, {}, expected2)
 
 
 def test_transpose():
@@ -6240,26 +5871,6 @@ def test_hamming_window():
     verify_model(HammingWindow(), example_args, {}, Expected)
 
 
-def test_contiguous():
-    class Contiguous(Module):
-        def forward(self, input):
-            return input.contiguous()
-
-    @tvm.script.ir_module
-    class Expected:
-        @R.function
-        def main(
-            input: R.Tensor((10, 10), dtype="float32"),
-        ) -> R.Tuple(R.Tensor((10, 10), dtype="float32")):
-            with R.dataflow():
-                gv: R.Tuple(R.Tensor((10, 10), dtype="float32")) = (input,)
-                R.output(gv)
-            return gv
-
-    example_args = (torch.randn(10, 10, dtype=torch.float32),)
-    verify_model(Contiguous(), example_args, {}, Expected)
-
-
 def test_clone():
     class Clone(Module):
         def forward(self, input):
@@ -6538,95 +6149,24 @@ def test_copy():
 
 
 def test_to_copy():
-    # float
-    class ToFloat(Module):
-        def forward(self, x):
-            return x.float()
-
-    @tvm.script.ir_module
-    class expected_float:
-        @R.function
-        def main(x: R.Tensor((1, 2, 3, 4), dtype="float32")) -> R.Tuple(
-            R.Tensor((1, 2, 3, 4), dtype="float32")
-        ):
-            # block 0
-            with R.dataflow():
-                gv: R.Tuple(R.Tensor((1, 2, 3, 4), dtype="float32")) = (x,)
-                R.output(gv)
-            return gv
-
-    # half
     class ToHalf(Module):
         def forward(self, x):
             return x.half()
 
     @tvm.script.ir_module
-    class expected_half:
+    class Expected:
         @R.function
         def main(x: R.Tensor((1, 2, 3, 4), dtype="float32")) -> R.Tuple(
             R.Tensor((1, 2, 3, 4), dtype="float16")
         ):
-            # block 0
             with R.dataflow():
                 lv: R.Tensor((1, 2, 3, 4), dtype="float16") = R.astype(x, 
dtype="float16")
                 gv: R.Tuple(R.Tensor((1, 2, 3, 4), dtype="float16")) = (lv,)
                 R.output(gv)
             return gv
 
-    # type
-    class Type(Module):
-        def forward(self, x):
-            return x.type(torch.float32)
-
-    @tvm.script.ir_module
-    class expected_type:
-        @R.function
-        def main(x: R.Tensor((1, 2, 3, 4), dtype="float32")) -> R.Tuple(
-            R.Tensor((1, 2, 3, 4), dtype="float32")
-        ):
-            # block 0
-            with R.dataflow():
-                gv: R.Tuple(R.Tensor((1, 2, 3, 4), dtype="float32")) = (x,)
-                R.output(gv)
-            return gv
-
-    class To1(Module):
-        def forward(self, input):
-            return input.to(torch.float16)
-
-    @I.ir_module
-    class expected_to1:
-        @R.function
-        def main(input: R.Tensor((1, 2, 3, 4), dtype="float32")) -> R.Tuple(
-            R.Tensor((1, 2, 3, 4), dtype="float16")
-        ):
-            with R.dataflow():
-                lv: R.Tensor((1, 2, 3, 4), dtype="float16") = R.astype(input, 
dtype="float16")
-                gv: R.Tuple(R.Tensor((1, 2, 3, 4), dtype="float16")) = (lv,)
-                R.output(gv)
-            return gv
-
-    class To2(Module):
-        def forward(self, input):
-            return input.to("cpu")
-
-    @I.ir_module
-    class expected_to2:
-        @R.function
-        def main(input: R.Tensor((1, 2, 3, 4), dtype="float32")) -> R.Tuple(
-            R.Tensor((1, 2, 3, 4), dtype="float32")
-        ):
-            with R.dataflow():
-                gv: R.Tuple(R.Tensor((1, 2, 3, 4), dtype="float32")) = (input,)
-                R.output(gv)
-            return gv
-
     example_args = (torch.randn(1, 2, 3, 4, dtype=torch.float32),)
-    verify_model(ToFloat(), example_args, {}, expected_float)
-    verify_model(ToHalf(), example_args, {}, expected_half)
-    verify_model(Type(), example_args, {}, expected_type)
-    verify_model(To1(), example_args, {}, expected_to1)
-    verify_model(To2(), example_args, {}, expected_to2)
+    verify_model(ToHalf(), example_args, {}, Expected)
 
 
 def test_keep_params():
@@ -8431,160 +7971,36 @@ def test_tensor_none_tuple():
 
 
 def test_gru():
-    class BasicGRU(nn.Module):
-        def __init__(self):
-            super().__init__()
-            self.gru = nn.GRU(
-                input_size=4,
-                hidden_size=8,
-                num_layers=1,
-                batch_first=True,
-                bidirectional=False,
-            )
-
-        def forward(self, x):
-            y, _ = self.gru(x)
-            return y
-
-    torch.manual_seed(42)
-    x = torch.randn(2, 3, 4, dtype=torch.float32)
-    model = BasicGRU()
-    with torch.no_grad():
-        pytorch_output = model(x)
-    exported_program = export(model, args=(x,))
-    mod = from_exported_program(exported_program)
-    target = tvm.target.Target("llvm")
-    ex = relax.build(mod, target)
-    vm = relax.VirtualMachine(ex, tvm.cpu())
-    x_tvm = tvm.runtime.tensor(x.numpy())
-    tvm_output = vm["main"](x_tvm)
-    if hasattr(tvm_output, "numpy"):
-        tvm_output_np = tvm_output.numpy()
-    else:
-        tvm_output_np = tvm_output[0].numpy()
-    assert pytorch_output.shape == tvm_output_np.shape, (
-        f"Shape mismatch: PyTorch {pytorch_output.shape} vs TVM 
{tvm_output_np.shape}"
-    )
-    tvm.testing.assert_allclose(pytorch_output.numpy(), tvm_output_np, 
rtol=1e-4, atol=1e-5)
-
-    class SeqFirstGRU(nn.Module):
-        def __init__(self):
-            super().__init__()
-            self.gru = nn.GRU(
-                input_size=3,
-                hidden_size=6,
-                num_layers=1,
-                batch_first=False,
-                bidirectional=False,
-            )
-
-        def forward(self, x):
-            y, _ = self.gru(x)
-            return y
-
-    torch.manual_seed(43)
-    x2 = torch.randn(4, 2, 3, dtype=torch.float32)
-    model2 = SeqFirstGRU()
-    with torch.no_grad():
-        pytorch_output2 = model2(x2)
-    exported_program2 = export(model2, args=(x2,))
-    mod2 = from_exported_program(exported_program2)
-    ex2 = relax.build(mod2, target)
-    vm2 = relax.VirtualMachine(ex2, tvm.cpu())
-    x2_tvm = tvm.runtime.tensor(x2.numpy())
-    tvm_output2 = vm2["main"](x2_tvm)
-    if hasattr(tvm_output2, "numpy"):
-        tvm_output2_np = tvm_output2.numpy()
-    else:
-        tvm_output2_np = tvm_output2[0].numpy()
-    assert pytorch_output2.shape == tvm_output2_np.shape
-    tvm.testing.assert_allclose(pytorch_output2.numpy(), tvm_output2_np, 
rtol=1e-4, atol=1e-5)
-
-    # Test bidirectional GRU with batch_first=True
-    class BidirectionalGRU(nn.Module):
-        def __init__(self):
-            super().__init__()
-            self.gru = nn.GRU(
-                input_size=4,
-                hidden_size=5,
-                num_layers=1,
-                batch_first=True,
-                bidirectional=True,
-            )
-
-        def forward(self, x):
-            y, _ = self.gru(x)
-            return y
-
-    torch.manual_seed(44)
-    x3 = torch.randn(2, 3, 4, dtype=torch.float32)
-    model3 = BidirectionalGRU()
-    with torch.no_grad():
-        pytorch_output3 = model3(x3)
-
-    # Verify output shape is correct (hidden_size * 2 due to bidirectional)
-    assert pytorch_output3.shape == (
-        2,
-        3,
-        10,
-    ), f"Expected shape (2, 3, 10), got {pytorch_output3.shape}"
-
-    exported_program3 = export(model3, args=(x3,))
-    mod3 = from_exported_program(exported_program3)
-    ex3 = relax.build(mod3, target)
-    vm3 = relax.VirtualMachine(ex3, tvm.cpu())
-    x3_tvm = tvm.runtime.tensor(x3.numpy())
-    tvm_output3 = vm3["main"](x3_tvm)
-    if hasattr(tvm_output3, "numpy"):
-        tvm_output3_np = tvm_output3.numpy()
-    else:
-        tvm_output3_np = tvm_output3[0].numpy()
-    assert pytorch_output3.shape == tvm_output3_np.shape, (
-        f"Shape mismatch: PyTorch {pytorch_output3.shape} vs TVM 
{tvm_output3_np.shape}"
-    )
-    tvm.testing.assert_allclose(pytorch_output3.numpy(), tvm_output3_np, 
rtol=1e-4, atol=1e-5)
-
-    # Test bidirectional GRU with batch_first=False
-    class SeqFirstBidirectionalGRU(nn.Module):
-        def __init__(self):
+    class GRU(nn.Module):
+        def __init__(self, input_size, hidden_size, batch_first, 
bidirectional):
             super().__init__()
             self.gru = nn.GRU(
-                input_size=3,
-                hidden_size=4,
+                input_size=input_size,
+                hidden_size=hidden_size,
                 num_layers=1,
-                batch_first=False,
-                bidirectional=True,
+                batch_first=batch_first,
+                bidirectional=bidirectional,
             )
 
         def forward(self, x):
             y, _ = self.gru(x)
             return y
 
-    torch.manual_seed(45)
-    x4 = torch.randn(4, 2, 3, dtype=torch.float32)  # (seq_len, batch, 
input_size)
-    model4 = SeqFirstBidirectionalGRU()
-    with torch.no_grad():
-        pytorch_output4 = model4(x4)
-
-    # Verify output shape (seq_len, batch, hidden_size * 2)
-    assert pytorch_output4.shape == (
-        4,
-        2,
-        8,
-    ), f"Expected shape (4, 2, 8), got {pytorch_output4.shape}"
-
-    exported_program4 = export(model4, args=(x4,))
-    mod4 = from_exported_program(exported_program4)
-    ex4 = relax.build(mod4, target)
-    vm4 = relax.VirtualMachine(ex4, tvm.cpu())
-    x4_tvm = tvm.runtime.tensor(x4.numpy())
-    tvm_output4 = vm4["main"](x4_tvm)
-    if hasattr(tvm_output4, "numpy"):
-        tvm_output4_np = tvm_output4.numpy()
-    else:
-        tvm_output4_np = tvm_output4[0].numpy()
-    assert pytorch_output4.shape == tvm_output4_np.shape
-    tvm.testing.assert_allclose(pytorch_output4.numpy(), tvm_output4_np, 
rtol=1e-4, atol=1e-5)
+    cases = [
+        (42, (2, 3, 4), 4, 8, True, False),
+        (43, (4, 2, 3), 3, 6, False, False),
+        (44, (2, 3, 4), 4, 5, True, True),
+        (45, (4, 2, 3), 3, 4, False, True),
+    ]
+    for seed, shape, input_size, hidden_size, batch_first, bidirectional in 
cases:
+        torch.manual_seed(seed)
+        x = torch.randn(*shape, dtype=torch.float32)
+        verify_model_numerically(
+            GRU(input_size, hidden_size, batch_first, bidirectional),
+            (x,),
+            rtol=1e-4,
+            atol=1e-5,
+        )
 
 
 @pytest.mark.skipif(not env.has_llvm(), reason="need llvm")
@@ -8814,45 +8230,12 @@ def test_dynamic_shape_with_unbounded_constraints():
 
 def test_sym_size_int():
     class SymSizeInt(Module):
-        def __init__(self, dim):
-            super().__init__()
-            self.dim = dim
-
         def forward(self, x):
-            # TODO(@mshr-h): `torch.ops.aten.sym_size.int(x, self.dim)` would 
be ideal, but currently
-            # the ep frontend is not able to handle it.
-            return torch.add(x[0], torch.ops.aten.sym_size.int(x, self.dim))
-
-    @I.ir_module
-    class Expected1:
-        @R.function
-        def main(x: R.Tensor((1, 3, 4), dtype="float32")) -> R.Tuple(
-            R.Tensor((3, 4), dtype="float32")
-        ):
-            with R.dataflow():
-                lv: R.Tensor((3, 4), dtype="float32") = R.take(
-                    x, R.const(0, "int64"), axis=0, mode="fast"
-                )
-                lv1: R.Tensor((3, 4), dtype="float32") = R.add(lv, 
R.const(3.0, "float32"))
-                gv: R.Tuple(R.Tensor((3, 4), dtype="float32")) = (lv1,)
-                R.output(gv)
-            return gv
-
-    example_args_1 = (torch.randn(1, 3, 4),)
-    verify_model(SymSizeInt(dim=1), example_args_1, {}, Expected1)
-    verify_model(SymSizeInt(dim=-2), example_args_1, {}, Expected1)
-
-    class SymSizeIntDynamic(Module):
-        def __init__(self, dim):
-            super().__init__()
-            self.dim = dim
-
-        def forward(self, x):
-            shape_dim = torch.ops.aten.sym_size.int(x, self.dim)
+            shape_dim = torch.ops.aten.sym_size.int(x, 0)
             return x.reshape(shape_dim, -1)
 
     @I.ir_module
-    class Expected2:
+    class Expected:
         @R.function
         def main(x: R.Tensor(("s0", 3, 4), dtype="float32")) -> R.Tuple(
             R.Tensor(("s0", 12), dtype="float32")
@@ -8865,13 +8248,13 @@ def test_sym_size_int():
                 R.output(gv)
             return gv
 
-    example_args_2 = (torch.randn(2, 3, 4),)
+    example_args = (torch.randn(2, 3, 4),)
     dynamic_shapes = {"x": {0: torch.export.Dim("dim")}}
     verify_model(
-        SymSizeIntDynamic(dim=0),
-        example_args_2,
+        SymSizeInt(),
+        example_args,
         {},
-        Expected2,
+        Expected,
         dynamic_shapes=dynamic_shapes,
         map_free_vars=True,
     )
diff --git a/tests/python/relax/test_frontend_from_fx.py 
b/tests/python/relax/test_frontend_from_fx.py
index e68a4fa768..a489977958 100644
--- a/tests/python/relax/test_frontend_from_fx.py
+++ b/tests/python/relax/test_frontend_from_fx.py
@@ -14,8 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-# ruff: noqa: F841
-
 import math
 import operator
 
@@ -33,7 +31,6 @@ from tvm.relax.frontend.torch import from_fx
 from tvm.script import ir as I
 from tvm.script import relax as R
 from tvm.script import tirx as T
-from tvm.testing import env
 
 
 def verify_model(torch_model, input_info, binding, expected):
@@ -901,14 +898,7 @@ def test_outer():
     verify_model(Outer(), input_infos, {}, expected)
 
 
[email protected]
[email protected](not env.has_gpu(), reason="need gpu")
 def test_softplus():
-    import torch
-    from torch.nn import Module
-
-    torch.set_grad_enabled(False)
-
     class Softplus0(torch.nn.Module):
         def __init__(self):
             super().__init__()
@@ -939,14 +929,7 @@ def test_softplus():
     verify_model(Softplus1(), input_info, {}, expected)
 
 
[email protected]
[email protected](not env.has_gpu(), reason="need gpu")
 def test_leakyrelu():
-    import torch
-    from torch.nn import Module
-
-    torch.set_grad_enabled(False)
-
     class LeakyReLU0(Module):
         def __init__(self):
             super().__init__()
@@ -1835,10 +1818,6 @@ def test_stochastic_depth():
         def forward(self, x):
             return self.stochastic_depth(x)
 
-    class StochasticDepth2(Module):
-        def forward(self, x):
-            return torchvision.ops.stochastic_depth(x, 0.5, mode="row", 
training=False)
-
     @tvm.script.ir_module
     class expected1:
         @R.function
@@ -1851,8 +1830,9 @@ def test_stochastic_depth():
                 R.output(gv)
             return gv
 
+    # The PyTorch frontend imports models with inference semantics, so 
stochastic
+    # depth is lowered to an identity even when the traced module is in 
training mode.
     verify_model(StochasticDepth1(), input_info, {}, expected1)
-    verify_model(StochasticDepth2(), input_info, {}, expected1)
 
 
 def test_layernorm():
@@ -2131,12 +2111,6 @@ def test_functional_cross_entropy():
 
 
 def test_groupnorm():
-    import torch
-    from torch.nn import Module
-
-    torch.set_grad_enabled(False)
-    torch.random.manual_seed(0)
-
     input_info = [([1, 3, 10, 10], "float32")]
 
     class GroupNorm(Module):
@@ -2180,9 +2154,6 @@ def test_groupnorm():
 
 
 def test_instancenorm2d():
-    torch.set_grad_enabled(False)
-    torch.random.manual_seed(0)
-
     input_info = [([1, 3, 10, 10], "float32")]
 
     class InstanceNorm2d(Module):
@@ -2216,8 +2187,6 @@ def test_instancenorm2d():
                 R.output(gv)
             return gv
 
-    example_args = (torch.randn(1, 3, 10, 10, dtype=torch.float32),)
-
     model = InstanceNorm2d()
     binding = {
         "w1": torch.ones(3).detach().numpy(),
@@ -2724,7 +2693,6 @@ operator_basic_unary = [
     (torch.floor, R.floor),
     (torch.log, R.log),
     (torch.neg, R.negative),
-    (torch.round, R.round),
     (torch.rsqrt, R.rsqrt),
     (torch.sin, R.sin),
     (torch.sinh, R.sinh),
@@ -3116,15 +3084,6 @@ def test_extended_unary_ops():
     verify_model(Hardtanh(), input_info, {}, expected1)
     verify_model(Hardtanh2(), input_info, {}, expected1)
 
-    # leaky_relu
-    test_leakyrelu()
-
-    # softplus
-    test_softplus()
-
-    # prelu
-    test_prelu()
-
     # log2
     class Log2(Module):
         def forward(self, x):
@@ -3771,41 +3730,6 @@ def test_interpolate():
 
     input_info_5d = [([1, 3, 4, 10, 10], "float32")]
 
-    class Interpolate5(Module):
-        def forward(self, input):
-            return torch.nn.functional.interpolate(
-                input,
-                size=None,
-                scale_factor=(2.0, 2.0, 2.0),
-                mode="trilinear",
-                align_corners=False,
-            )
-
-    @tvm.script.ir_module
-    class expected5:
-        @R.function
-        def main(input_5: R.Tensor((1, 3, 4, 10, 10), dtype="float32")) -> 
R.Tensor(
-            (1, 3, 8, 20, 20), dtype="float32"
-        ):
-            with R.dataflow():
-                lv: R.Tensor((1, 3, 8, 20, 20), dtype="float32") = 
R.image.resize3d(
-                    input_5,
-                    (8, 20, 20),
-                    roi=[0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 
0.000000],
-                    layout="NCDHW",
-                    method="linear",
-                    coordinate_transformation_mode="half_pixel",
-                    rounding_method="",
-                    cubic_alpha=-0.75,
-                    cubic_exclude=0,
-                    extrapolation_value=0,
-                )
-                gv: R.Tensor((1, 3, 8, 20, 20), dtype="float32") = lv
-                R.output(gv)
-            return gv
-
-    verify_model(Interpolate5(), input_info_5d, {}, expected5)
-
     class Interpolate6(Module):
         def forward(self, input):
             return torch.nn.functional.interpolate(
@@ -3911,44 +3835,6 @@ def test_interpolate():
 
 
 def test_interpolate_nhwc_layout():
-    # First verify backward compatibility - default should still be NCHW
-    input_info_nchw = [([1, 3, 10, 10], "float32")]
-
-    class InterpolateDefault(Module):
-        def forward(self, input):
-            return torch.nn.functional.interpolate(input, (5, 5))
-
-    @tvm.script.ir_module
-    class expected_default_nchw:
-        @R.function
-        def main(input_1: R.Tensor((1, 3, 10, 10), dtype="float32")) -> 
R.Tensor(
-            (1, 3, 5, 5), dtype="float32"
-        ):
-            # block 0
-            with R.dataflow():
-                lv: R.Tensor((1, 3, 5, 5), dtype="float32") = R.image.resize2d(
-                    input_1,
-                    (5, 5),
-                    roi=[0.000000, 0.000000, 0.000000, 0.000000],
-                    layout="NCHW",
-                    method="nearest_neighbor",
-                    coordinate_transformation_mode="asymmetric",
-                    rounding_method="round",
-                    cubic_alpha=-0.75,
-                    cubic_exclude=0,
-                    extrapolation_value=0,
-                )
-                gv: R.Tensor((1, 3, 5, 5), dtype="float32") = lv
-                R.output(gv)
-            return gv
-
-    # Verify default behavior (no default_image_layout parameter) uses NCHW
-    graph_model_default = fx.symbolic_trace(InterpolateDefault())
-    with torch.no_grad():
-        mod_default = from_fx(graph_model_default, input_info_nchw)
-    tvm.ir.assert_structural_equal(mod_default, expected_default_nchw)
-
-    # Now test NHWC layout
     input_info = [([1, 10, 10, 3], "float32")]
 
     class InterpolateNHWC(Module):
@@ -4401,65 +4287,28 @@ def test_masked_fill_inplace():
     verify_model(Masked_Fill_Inplace(), input_info, {}, Expected)
 
 
-def test_arange():
-    import numpy as np
-
-    torch.set_grad_enabled(False)
-    torch.random.manual_seed(0)
-
-    class Arange(Module):
-        def forward(self, input):
-            return torch.arange(0, 20, dtype=torch.int32)
-
-    graph_model = fx.symbolic_trace(Arange())
-    mod = from_fx(graph_model, [([10, 10], "float32")])
-    assert len(mod["main"].body.blocks) == 1
-    assert len(mod["main"].body.blocks[0].bindings) == 1
-    assert isinstance(mod["main"].body.blocks[0].bindings[0].value, 
relax.Constant)
-    tvm.testing.assert_allclose(
-        mod["main"].body.blocks[0].bindings[0].value.data.numpy(),
-        np.arange(0, 20, dtype="int32"),
-    )
-
[email protected](
+    "torch_dtype, expected_dtype",
+    [(torch.float32, "float32"), (None, "int64")],
+    ids=["float32", "default-int64"],
+)
+def test_get_attr_scalar_tensor_constant(torch_dtype, expected_dtype):
+    """Import rank-0 tensor constants folded to get_attr by FX tracing."""
 
-def test_empty():
-    class Empty(Module):
+    class ScalarTensor(Module):
         def forward(self, input):
-            return torch.empty((10, 10), dtype=torch.float32)
+            if torch_dtype is None:
+                return torch.tensor(3)
+            return torch.tensor(3, dtype=torch_dtype)
 
-    graph_model = fx.symbolic_trace(Empty())
+    graph_model = fx.symbolic_trace(ScalarTensor())
     mod = from_fx(graph_model, [([10, 10], "float32")])
-    assert len(mod["main"].body.blocks) == 1
-    assert len(mod["main"].body.blocks[0].bindings) == 1
-    assert isinstance(mod["main"].body.blocks[0].bindings[0].value, 
relax.Constant)
-    assert mod["main"].body.blocks[0].bindings[0].value.data.shape == (10, 10)
-    assert mod["main"].body.blocks[0].bindings[0].value.data.dtype == "float32"
-
-
-def test_tensor():
-    class Empty1(Module):
-        def forward(self, input):
-            return torch.tensor(3, dtype=torch.float32)
-
-    class Empty2(Module):
-        def forward(self, input):
-            return torch.tensor(3)
-
-    graph_model1 = fx.symbolic_trace(Empty1())
-    mod1 = from_fx(graph_model1, [([10, 10], "float32")])
-    assert len(mod1["main"].body.blocks) == 1
-    assert len(mod1["main"].body.blocks[0].bindings) == 1
-    assert isinstance(mod1["main"].body.blocks[0].bindings[0].value, 
relax.Constant)
-    assert mod1["main"].body.blocks[0].bindings[0].value.data.shape == ()
-    assert mod1["main"].body.blocks[0].bindings[0].value.data.dtype == 
"float32"
-
-    graph_model2 = fx.symbolic_trace(Empty2())
-    mod2 = from_fx(graph_model2, [([10, 10], "float32")])
-    assert len(mod2["main"].body.blocks) == 1
-    assert len(mod2["main"].body.blocks[0].bindings) == 1
-    assert isinstance(mod2["main"].body.blocks[0].bindings[0].value, 
relax.Constant)
-    assert mod2["main"].body.blocks[0].bindings[0].value.data.shape == ()
-    assert mod2["main"].body.blocks[0].bindings[0].value.data.dtype == "int64"
+    bindings = mod["main"].body.blocks[0].bindings
+    assert len(bindings) == 1
+    value = bindings[0].value
+    assert isinstance(value, relax.Constant)
+    assert value.data.shape == ()
+    assert value.data.dtype == expected_dtype
 
 
 def test_new_ones():
@@ -4513,10 +4362,6 @@ def test_new_zeros():
 def test_expand():
     input_info = [([1, 2, 3, 4], "float32")]
 
-    class Expand1(Module):
-        def forward(self, x):
-            return x.expand(4, 2, 3, 4)
-
     class Expand2(Module):
         def forward(self, x):
             return x.expand(4, -1, -1, 4)
@@ -4534,7 +4379,6 @@ def test_expand():
                 R.output(gv)
             return gv
 
-    verify_model(Expand1(), input_info, {}, expected1)
     verify_model(Expand2(), input_info, {}, expected1)
 
 
@@ -4832,7 +4676,6 @@ def test_repeat():
 
     verify_model(Tile1(), [([3], "float32")], {}, expected1)
     verify_model(Tile2(), [([1, 3], "float32")], {}, expected2)
-    verify_model(Tile2(), [(torch.Size([1, 3]), "float32")], {}, expected2)
 
 
 def test_roll():
@@ -5696,18 +5539,6 @@ def test_gather():
         def forward(self, data, indices):
             return torch.gather(data, 0, indices)
 
-    class Gather1(Module):
-        def forward(self, data, indices):
-            return torch.gather(data, 1, indices)
-
-    class Gather2(Module):
-        def forward(self, data, indices):
-            return torch.gather(data, -1, indices)
-
-    class Gather3(Module):
-        def forward(self, data, indices):
-            return torch.gather(data, -2, indices)
-
     @tvm.script.ir_module
     class Expected0:
         @R.function
@@ -5721,220 +5552,32 @@ def test_gather():
                 R.output(gv)
             return gv
 
-    @tvm.script.ir_module
-    class Expected1:
-        @R.function
-        def main(
-            inp_0: R.Tensor((2, 3), dtype="float32"),
-            inp_1: R.Tensor((2, 3), dtype="int32"),
-        ) -> R.Tensor((2, 3), dtype="float32"):
-            with R.dataflow():
-                lv: R.Tensor((2, 3), dtype="float32") = 
R.gather_elements(inp_0, inp_1, axis=1)
-                gv: R.Tensor((2, 3), dtype="float32") = lv
-                R.output(gv)
-            return gv
-
-    @tvm.script.ir_module
-    class Expected2:
-        @R.function
-        def main(
-            inp_0: R.Tensor((2, 3), dtype="float32"),
-            inp_1: R.Tensor((2, 3), dtype="int32"),
-        ) -> R.Tensor((2, 3), dtype="float32"):
-            with R.dataflow():
-                lv: R.Tensor((2, 3), dtype="float32") = 
R.gather_elements(inp_0, inp_1, axis=-1)
-                gv: R.Tensor((2, 3), dtype="float32") = lv
-                R.output(gv)
-            return gv
-
-    @tvm.script.ir_module
-    class Expected3:
-        @R.function
-        def main(
-            inp_0: R.Tensor((2, 3), dtype="float32"),
-            inp_1: R.Tensor((2, 3), dtype="int32"),
-        ) -> R.Tensor((2, 3), dtype="float32"):
-            with R.dataflow():
-                lv: R.Tensor((2, 3), dtype="float32") = 
R.gather_elements(inp_0, inp_1, axis=-2)
-                gv: R.Tensor((2, 3), dtype="float32") = lv
-                R.output(gv)
-            return gv
-
     verify_model(Gather0(), [([2, 3], "float32"), ([2, 3], "int32")], {}, 
Expected0)
-    verify_model(Gather1(), [([2, 3], "float32"), ([2, 3], "int32")], {}, 
Expected1)
-    verify_model(Gather2(), [([2, 3], "float32"), ([2, 3], "int32")], {}, 
Expected2)
-    verify_model(Gather3(), [([2, 3], "float32"), ([2, 3], "int32")], {}, 
Expected3)
 
 
 def test_index_put():
-    # Test case 1: 1D input
-    class IndexPut1D(Module):
-        def forward(self, data, indices_0, values):
-            indices_tuple = (indices_0,)
-            return data.index_put_(indices_tuple, values, accumulate=False)
-
-    input_info_1d = [((64,), "float32"), ((128,), "int64"), ((128,), 
"float32")]
+    class IndexPut(Module):
+        def forward(self, data, indices, values):
+            return data.index_put_((indices,), values, accumulate=False)
 
     @I.ir_module
-    class Expected1D:
+    class Expected:
         @R.function
         def main(
             data: R.Tensor((64,), dtype="float32"),
-            indices_0: R.Tensor((128,), dtype="int64"),
+            indices: R.Tensor((128,), dtype="int64"),
             values: R.Tensor((128,), dtype="float32"),
         ) -> R.Tensor((64,), dtype="float32"):
             with R.dataflow():
                 lv: R.Tensor((64,), dtype="float32") = R.index_put(
-                    data, R.tuple(indices_0), values, accumulate=False
+                    data, R.tuple(indices), values, accumulate=False
                 )
                 gv: R.Tensor((64,), dtype="float32") = lv
                 R.output(gv)
             return gv
 
-    # Test case 2: 2D input
-    class IndexPut2D(Module):
-        def forward(self, data, indices_0, indices_1, values):
-            indices_tuple = (indices_0, indices_1)
-            return data.index_put_(indices_tuple, values, accumulate=False)
-
-    input_info_2d = [
-        ((32, 64), "float32"),
-        ((128,), "int64"),
-        ((128,), "int64"),
-        ((128,), "float32"),
-    ]
-
-    @I.ir_module
-    class Expected2D:
-        @R.function
-        def main(
-            data: R.Tensor((32, 64), dtype="float32"),
-            indices_0: R.Tensor((128,), dtype="int64"),
-            indices_1: R.Tensor((128,), dtype="int64"),
-            values: R.Tensor((128,), dtype="float32"),
-        ) -> R.Tensor((32, 64), dtype="float32"):
-            with R.dataflow():
-                lv: R.Tensor((32, 64), dtype="float32") = R.index_put(
-                    data, R.tuple(indices_0, indices_1), values, 
accumulate=False
-                )
-                gv: R.Tensor((32, 64), dtype="float32") = lv
-                R.output(gv)
-            return gv
-
-    # Test case 3: 3D input
-    class IndexPut3D(Module):
-        def forward(self, data, indices_0, indices_1, indices_2, values):
-            indices_tuple = (indices_0, indices_1, indices_2)
-            return data.index_put_(indices_tuple, values, accumulate=False)
-
-    input_info_3d = [
-        ((16, 32, 64), "float32"),
-        ((128,), "int64"),
-        ((128,), "int64"),
-        ((128,), "int64"),
-        ((128,), "float32"),
-    ]
-
-    @I.ir_module
-    class Expected3D:
-        @R.function
-        def main(
-            data: R.Tensor((16, 32, 64), dtype="float32"),
-            indices_0: R.Tensor((128,), dtype="int64"),
-            indices_1: R.Tensor((128,), dtype="int64"),
-            indices_2: R.Tensor((128,), dtype="int64"),
-            values: R.Tensor((128,), dtype="float32"),
-        ) -> R.Tensor((16, 32, 64), dtype="float32"):
-            with R.dataflow():
-                lv: R.Tensor((16, 32, 64), dtype="float32") = R.index_put(
-                    data, R.tuple(indices_0, indices_1, indices_2), values, 
accumulate=False
-                )
-                gv: R.Tensor((16, 32, 64), dtype="float32") = lv
-                R.output(gv)
-            return gv
-
-    # Test case 4: 4D input
-    class IndexPut4D(Module):
-        def forward(self, data, indices_0, indices_1, indices_2, indices_3, 
values):
-            indices_tuple = (indices_0, indices_1, indices_2, indices_3)
-            return data.index_put_(indices_tuple, values, accumulate=False)
-
-    input_info_4d = [
-        ((8, 16, 32, 64), "float32"),
-        ((128,), "int64"),
-        ((128,), "int64"),
-        ((128,), "int64"),
-        ((128,), "int64"),
-        ((128,), "float32"),
-    ]
-
-    @I.ir_module
-    class Expected4D:
-        @R.function
-        def main(
-            data: R.Tensor((8, 16, 32, 64), dtype="float32"),
-            indices_0: R.Tensor((128,), dtype="int64"),
-            indices_1: R.Tensor((128,), dtype="int64"),
-            indices_2: R.Tensor((128,), dtype="int64"),
-            indices_3: R.Tensor((128,), dtype="int64"),
-            values: R.Tensor((128,), dtype="float32"),
-        ) -> R.Tensor((8, 16, 32, 64), dtype="float32"):
-            with R.dataflow():
-                lv: R.Tensor((8, 16, 32, 64), dtype="float32") = R.index_put(
-                    data,
-                    R.tuple(indices_0, indices_1, indices_2, indices_3),
-                    values,
-                    accumulate=False,
-                )
-                gv: R.Tensor((8, 16, 32, 64), dtype="float32") = lv
-                R.output(gv)
-            return gv
-
-    # Test case 5: 5D input
-    class IndexPut5D(Module):
-        def forward(self, data, indices_0, indices_1, indices_2, indices_3, 
indices_4, values):
-            indices_tuple = (indices_0, indices_1, indices_2, indices_3, 
indices_4)
-            return data.index_put_(indices_tuple, values, accumulate=False)
-
-    input_info_5d = [
-        ((4, 8, 16, 32, 64), "float32"),
-        ((128,), "int64"),
-        ((128,), "int64"),
-        ((128,), "int64"),
-        ((128,), "int64"),
-        ((128,), "int64"),
-        ((128,), "float32"),
-    ]
-
-    @I.ir_module
-    class Expected5D:
-        @R.function
-        def main(
-            data: R.Tensor((4, 8, 16, 32, 64), dtype="float32"),
-            indices_0: R.Tensor((128,), dtype="int64"),
-            indices_1: R.Tensor((128,), dtype="int64"),
-            indices_2: R.Tensor((128,), dtype="int64"),
-            indices_3: R.Tensor((128,), dtype="int64"),
-            indices_4: R.Tensor((128,), dtype="int64"),
-            values: R.Tensor((128,), dtype="float32"),
-        ) -> R.Tensor((4, 8, 16, 32, 64), dtype="float32"):
-            with R.dataflow():
-                lv: R.Tensor((4, 8, 16, 32, 64), dtype="float32") = 
R.index_put(
-                    data,
-                    R.tuple(indices_0, indices_1, indices_2, indices_3, 
indices_4),
-                    values,
-                    accumulate=False,
-                )
-                gv: R.Tensor((4, 8, 16, 32, 64), dtype="float32") = lv
-                R.output(gv)
-            return gv
-
-    # Run verification for each case
-    verify_model(IndexPut1D(), input_info_1d, {}, Expected1D)
-    verify_model(IndexPut2D(), input_info_2d, {}, Expected2D)
-    verify_model(IndexPut3D(), input_info_3d, {}, Expected3D)
-    verify_model(IndexPut4D(), input_info_4d, {}, Expected4D)
-    verify_model(IndexPut5D(), input_info_5d, {}, Expected5D)
+    input_info = [((64,), "float32"), ((128,), "int64"), ((128,), "float32")]
+    verify_model(IndexPut(), input_info, {}, Expected)
 
 
 def test_flip():
@@ -5942,10 +5585,6 @@ def test_flip():
         def forward(self, data):
             return torch.flip(data, [0])
 
-    class Flip1(Module):
-        def forward(self, data):
-            return torch.flip(data, [1])
-
     @tvm.script.ir_module
     class Expected0:
         @R.function
@@ -5958,20 +5597,7 @@ def test_flip():
                 R.output(gv)
             return gv
 
-    @tvm.script.ir_module
-    class Expected1:
-        @R.function
-        def main(
-            inp_0: R.Tensor((2, 2), dtype="float32"),
-        ) -> R.Tensor((2, 2), dtype="float32"):
-            with R.dataflow():
-                lv: R.Tensor((2, 2), dtype="float32") = R.flip(inp_0, axis=1)
-                gv: R.Tensor((2, 2), dtype="float32") = lv
-                R.output(gv)
-            return gv
-
     verify_model(Flip0(), [([2, 2], "float32")], {}, Expected0)
-    verify_model(Flip1(), [([2, 2], "float32")], {}, Expected1)
 
 
 def test_flip_multi_axis():
@@ -6713,42 +6339,6 @@ def test_dtypes(torch_dtype, relax_dtype):
     verify_model(Model(), [([10, 10], torch_dtype), ([10, 10], torch_dtype)], 
{}, Expected)
 
 
-def test_eye():
-    import numpy as np
-
-    class Eye(Module):
-        def forward(self, input):
-            return torch.eye(3)
-
-    graph_model = fx.symbolic_trace(Eye())
-    mod = from_fx(graph_model, [([3, 3], "float32")])
-    assert len(mod["main"].body.blocks) == 1
-    assert len(mod["main"].body.blocks[0].bindings) == 1
-    assert isinstance(mod["main"].body.blocks[0].bindings[0].value, 
relax.Constant)
-    tvm.testing.assert_allclose(
-        mod["main"].body.blocks[0].bindings[0].value.data.numpy(),
-        np.eye(3, dtype="float32"),
-    )
-
-
-def test_linspace():
-    import numpy as np
-
-    class Linspace(Module):
-        def forward(self, input):
-            return torch.linspace(0, 1, steps=9)
-
-    graph_model = fx.symbolic_trace(Linspace())
-    mod = from_fx(graph_model, [([9, 9], "float32")])
-    assert len(mod["main"].body.blocks) == 1
-    assert len(mod["main"].body.blocks[0].bindings) == 1
-    assert isinstance(mod["main"].body.blocks[0].bindings[0].value, 
relax.Constant)
-    tvm.testing.assert_allclose(
-        mod["main"].body.blocks[0].bindings[0].value.data.numpy(),
-        np.linspace(0, 1, num=9, dtype="float32"),
-    )
-
-
 def test_round():
     input_info = [([3, 4], "float32")]
 
@@ -6806,7 +6396,7 @@ def test_round():
         ]
     )
 
-    for decimals in [0, 1, 2, 3]:
+    for decimals in [0, 2]:
         torch_model = Round(decimals)
         graph_model = fx.symbolic_trace(torch_model)
         with torch.no_grad():
diff --git a/tests/python/relax/test_frontend_tflite.py 
b/tests/python/relax/test_frontend_tflite.py
index e030f73b8a..1561826b17 100644
--- a/tests/python/relax/test_frontend_tflite.py
+++ b/tests/python/relax/test_frontend_tflite.py
@@ -1327,6 +1327,48 @@ def test_binary(tf_op, relax_op):
     verify(Binary, Expected)
 
 
+def test_static_broadcast_lowered_to_multiply():
+    """Static TensorFlow broadcasts become TFLite MUL with a constant 
operand."""
+
+    class RankExpansion(tf.Module):
+        @tf.function(input_signature=[tf.TensorSpec(shape=(2, 2), 
dtype=tf.float32)])
+        def func(self, x):
+            return tf.broadcast_to(x, [3, 2, 2])
+
+    @I.ir_module
+    class ExpectedRankExpansion:
+        @R.function
+        def main(x: R.Tensor((2, 2), dtype="float32")) -> R.Tensor((3, 2, 2), 
dtype="float32"):
+            R.func_attr({"num_input": 1})
+            with R.dataflow():
+                gv: R.Tensor((3, 2, 2), dtype="float32") = R.multiply(
+                    x, R.const(np.ones((3, 2, 2), dtype="float32"))
+                )
+                R.output(gv)
+            return gv
+
+    verify(RankExpansion, ExpectedRankExpansion)
+
+    class ScalarInt(tf.Module):
+        @tf.function(input_signature=[tf.TensorSpec(shape=(), dtype=tf.int32)])
+        def func(self, x):
+            return tf.broadcast_to(x, [4, 4])
+
+    @I.ir_module
+    class ExpectedScalarInt:
+        @R.function
+        def main(x: R.Tensor((), dtype="int32")) -> R.Tensor((4, 4), 
dtype="int32"):
+            R.func_attr({"num_input": 1})
+            with R.dataflow():
+                gv: R.Tensor((4, 4), dtype="int32") = R.multiply(
+                    x, R.const(np.ones((4, 4), dtype="int32"))
+                )
+                R.output(gv)
+            return gv
+
+    verify(ScalarInt, ExpectedScalarInt)
+
+
 def test_pow():
     class TfInput(tf.Module):
         @tf.function(input_signature=[tf.TensorSpec(shape=(1, 30), 
dtype=tf.float32)])
@@ -2056,6 +2098,33 @@ def test_gather():
 
     verify(Gather, Expected)
 
+    # TensorFlow lowers embedding lookup to TFLite GATHER.  Keep a case with
+    # constant params and multidimensional int32 indices, since the case above
+    # uses runtime params and one-dimensional int64 indices along axis 1.
+    class GatherConstantParams(tf.Module):
+        @tf.function(input_signature=[tf.TensorSpec(shape=(2, 3), 
dtype=tf.int32)])
+        def func(self, indices):
+            params = tf.constant([[1, 2], [3, 4], [5, 6], [7, 8]], 
dtype=tf.float32)
+            return tf.gather(params, indices, axis=0)
+
+    @I.ir_module
+    class ExpectedConstantParams:
+        @R.function
+        def main(indices: R.Tensor((2, 3), dtype="int32")) -> R.Tensor((2, 3, 
2), dtype="float32"):
+            R.func_attr({"num_input": 1})
+            with R.dataflow():
+                lv: R.Tensor((2, 3), dtype="int32") = R.astype(indices, 
dtype="int32")
+                gv: R.Tensor((2, 3, 2), dtype="float32") = R.take(
+                    R.const(np.array([[1, 2], [3, 4], [5, 6], [7, 8]], 
dtype=np.float32)),
+                    lv,
+                    axis=0,
+                    mode="fast",
+                )
+                R.output(gv)
+            return gv
+
+    verify(GatherConstantParams, ExpectedConstantParams)
+
 
 def test_gather_nd():
     class GatherND(tf.Module):

Reply via email to