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 ca6fcc25b5 [BugFix][Relax] Preserve take mode in 
ReorderTakeAfterMatmul (#20206)
ca6fcc25b5 is described below

commit ca6fcc25b5655a92c25794515c9b13447ac9b91b
Author: Midst <[email protected]>
AuthorDate: Fri Aug 28 15:05:29 2026 +0800

    [BugFix][Relax] Preserve take mode in ReorderTakeAfterMatmul (#20206)
    
    `ReorderTakeAfterMatmul` rebuilds `relax.take` calls without forwarding
    the original `mode`, so `mode="clip"` silently becomes the default
    `mode="fast"`. This changes the defined behavior for out-of-bounds
    indices.
    
    This change forwards `TakeAttrs::mode` in both the simple and batched
    weight rewrite paths, and adds structural regression tests for both
    paths.
    
    Testing:
    - `git diff --check`
    - C++ syntax checks with TVM-generated compiler flags
    - `python -m py_compile
    tests/python/relax/test_transform_reorder_take_after_matmul.py`
    
    Full pytest was not run because the current Windows host does not have
    MSVC. The available MinGW build stops in TVM-FFI's Windows platform code
    before compiling this transform.
    
    Fixes #20201
---
 src/relax/transform/reorder_take_after_matmul.cc   |  4 +-
 .../test_transform_reorder_take_after_matmul.py    | 66 ++++++++++++++++++++++
 2 files changed, 68 insertions(+), 2 deletions(-)

diff --git a/src/relax/transform/reorder_take_after_matmul.cc 
b/src/relax/transform/reorder_take_after_matmul.cc
index f693d0278b..19e30f8c68 100644
--- a/src/relax/transform/reorder_take_after_matmul.cc
+++ b/src/relax/transform/reorder_take_after_matmul.cc
@@ -94,7 +94,7 @@ std::tuple<DFPattern, ffi::TypedFunction<Expr(Expr, 
ffi::Map<DFPattern, Expr>)>>
       // out_table.shape = [*batch, table_size]
       auto out_table = matmul(lhs, weights, std::nullopt);
       // new_output.shape = [*batch, outfeatures]
-      auto new_output = take(out_table, indices, matmul_ty->ndim - 1);
+      auto new_output = take(out_table, indices, matmul_ty->ndim - 1, 
attrs->mode);
 
       return new_output;
     } else if (lhs_ty->ndim == 3 && weights_ty->ndim == 3 && indices_ty->ndim 
== 1 && axis == 0 &&
@@ -130,7 +130,7 @@ std::tuple<DFPattern, ffi::TypedFunction<Expr(Expr, 
ffi::Map<DFPattern, Expr>)>>
       // operations.
 
       // duplicated_output.shape = [batch1, batch2, batch1, outfeatures]
-      auto duplicated_output = take(indexed_output, indices, 2);
+      auto duplicated_output = take(indexed_output, indices, 2, attrs->mode);
       // new_output.shape = [batch1, batch2, outfeatures]
       auto new_output = einsum(Tuple({duplicated_output}), "ijik->ijk");
 
diff --git a/tests/python/relax/test_transform_reorder_take_after_matmul.py 
b/tests/python/relax/test_transform_reorder_take_after_matmul.py
index 8e7243d02e..3d2de09907 100644
--- a/tests/python/relax/test_transform_reorder_take_after_matmul.py
+++ b/tests/python/relax/test_transform_reorder_take_after_matmul.py
@@ -185,5 +185,71 @@ class TestDynamicBatchedActivationsAndWeights(Base):
             return out
 
 
+class TestPreserveTakeMode(Base):
+    @I.ir_module
+    class Before:
+        @R.function
+        def main(
+            x: R.Tensor([1, 16], "float32"),
+            weight_table: R.Tensor([16, 64], "float32"),
+            routing_table: R.Tensor([32], "int64"),
+        ) -> R.Tensor([1, 32], "float32"):
+            with R.dataflow():
+                weight = R.take(weight_table, routing_table, axis=1, 
mode="clip")
+                out = R.matmul(x, weight)
+                R.output(out)
+            return out
+
+    @I.ir_module
+    class Expected:
+        @R.function
+        def main(
+            x: R.Tensor([1, 16], "float32"),
+            weight_table: R.Tensor([16, 64], "float32"),
+            routing_table: R.Tensor([32], "int64"),
+        ) -> R.Tensor([1, 32], "float32"):
+            with R.dataflow():
+                out_table = R.matmul(x, weight_table)
+                out = R.take(out_table, routing_table, axis=1, mode="clip")
+                R.output(out)
+            return out
+
+
+class TestPreserveTakeModeForBatchedWeights(Base):
+    @I.ir_module
+    class Before:
+        @R.function
+        def main(
+            x: R.Tensor([128, 1, 16], "float32"),
+            weight_table: R.Tensor([64, 16, 32], "float32"),
+            routing_table: R.Tensor([128], "int64"),
+        ) -> R.Tensor([128, 1, 32], "float32"):
+            with R.dataflow():
+                weight = R.take(weight_table, routing_table, axis=0, 
mode="clip")
+                out = R.matmul(x, weight)
+                R.output(out)
+            return out
+
+    @I.ir_module
+    class Expected:
+        @R.function
+        def main(
+            x: R.Tensor([128, 1, 16], "float32"),
+            weight_table: R.Tensor([64, 16, 32], "float32"),
+            routing_table: R.Tensor([128], "int64"),
+        ) -> R.Tensor([128, 1, 32], "float32"):
+            with R.dataflow():
+                reordered_weight = R.permute_dims(weight_table, [1, 0, 2])
+                fused_weight = R.reshape(reordered_weight, [16, 2048])
+                fused_output = R.matmul(x, fused_weight)
+                reordered_output = R.reshape(fused_output, [128, 1, 64, 32])
+                tabular_output = R.take(
+                    reordered_output, routing_table, axis=2, mode="clip"
+                )
+                out = R.einsum([tabular_output], "ijik->ijk")
+                R.output(out)
+            return out
+
+
 if __name__ == "__main__":
     tvm.testing.main()

Reply via email to