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

tqchen 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 f7b0fe62a9 [REFACTOR][S-TIR] Remove test-only force index narrowing 
(#20685)
f7b0fe62a9 is described below

commit f7b0fe62a9b2685b002efdc4e69f0960b3e30ffa
Author: Tianqi Chen <[email protected]>
AuthorDate: Mon Oct 12 19:11:45 2026 -0400

    [REFACTOR][S-TIR] Remove test-only force index narrowing (#20685)
    
    Remove the test-only S-TIR ForceNarrowIndexToInt32 API and keep
    sort/scan integration on the i64 index path. Localize the remaining
    narrowing implementation in TIRx while preserving its public entrypoint
    and WebGPU use.
---
 include/tvm/s_tir/transform.h                      |  13 --
 include/tvm/tirx/transform.h                       |   3 +-
 python/tvm/s_tir/transform/transform.py            |  19 ---
 python/tvm/tirx/transform/transform.py             |   3 +-
 src/s_tir/transform/force_narrow_index_to_i32.cc   |  78 ---------
 src/tirx/transform/force_narrow_index_to_i32.cc    |  70 +++++++-
 src/tirx/transform/force_narrow_index_to_i32.h     | 113 -------------
 .../relax/test_backend_dispatch_sort_scan.py       |  22 +--
 ...st_s_tir_transform_force_narrow_index_to_i32.py | 177 ---------------------
 9 files changed, 72 insertions(+), 426 deletions(-)

diff --git a/include/tvm/s_tir/transform.h b/include/tvm/s_tir/transform.h
index 1513e12cab..1e5187a0e3 100644
--- a/include/tvm/s_tir/transform.h
+++ b/include/tvm/s_tir/transform.h
@@ -310,19 +310,6 @@ TVM_DLL Pass DecorateDeviceScope();
  */
 TVM_DLL Pass UseAssumeToReduceBranches();
 
-/*!
- * \brief Force to narrow down indexing expressions and integer tensors to 
int32 dtype in
- *        functions that may still contain S-TIR blocks.
- *
- * Unlike tirx::transform::ForceNarrowIndexToInt32, this pass also rewrites 
block iterators,
- * block access regions, and match tensor regions, so it can run on scheduled 
functions before
- * block lowering.
- *
- * \return The pass.
- * \note This pass should not be used in default cases.
- */
-TVM_DLL Pass ForceNarrowIndexToInt32();
-
 }  // namespace transform
 }  // namespace s_tir
 }  // namespace tvm
diff --git a/include/tvm/tirx/transform.h b/include/tvm/tirx/transform.h
index aaf1b1a31a..3b6ede5942 100644
--- a/include/tvm/tirx/transform.h
+++ b/include/tvm/tirx/transform.h
@@ -228,8 +228,7 @@ TVM_TIRX_DLL Pass NarrowDataType(int target_bits);
 /*!
  * \brief Force to narrow down indexing expressions and integer tensors to 
int32 dtype.
  *
- * The function must not contain S-TIR blocks. Use 
s_tir::transform::ForceNarrowIndexToInt32
- * before block lowering.
+ * The function must not contain S-TIR blocks.
  *
  * \return The pass.
  * \note This pass should not be used in default cases.
diff --git a/python/tvm/s_tir/transform/transform.py 
b/python/tvm/s_tir/transform/transform.py
index ec6c05e5dd..3be6850e6a 100644
--- a/python/tvm/s_tir/transform/transform.py
+++ b/python/tvm/s_tir/transform/transform.py
@@ -421,22 +421,3 @@ def UseAssumeToReduceBranches():
         The result pass
     """
     return _ffi_api.UseAssumeToReduceBranches()  # type: ignore
-
-
-def ForceNarrowIndexToInt32():
-    """Force narrow down indexing expressions and integer tensors to int32 
dtype.
-
-    Unlike :py:func:`tvm.tirx.transform.ForceNarrowIndexToInt32`, this pass 
also rewrites block
-    iterators, block access regions, and match tensor regions, so it can run 
on scheduled
-    functions before block lowering.
-
-    Returns
-    -------
-    fpass : tvm.transform.Pass
-        The result pass
-
-    Note
-    ----
-    This pass should not be used in default cases.
-    """
-    return _ffi_api.ForceNarrowIndexToInt32()  # type: ignore
diff --git a/python/tvm/tirx/transform/transform.py 
b/python/tvm/tirx/transform/transform.py
index 54af2ec41d..892d945bee 100644
--- a/python/tvm/tirx/transform/transform.py
+++ b/python/tvm/tirx/transform/transform.py
@@ -388,8 +388,7 @@ def NarrowDataType(target_bits: int):
 def ForceNarrowIndexToInt32():
     """Force narrow down indexing expressions and integer tensors to int32 
dtype.
 
-    The function must not contain S-TIR blocks. Use
-    :py:func:`tvm.s_tir.transform.ForceNarrowIndexToInt32` before block 
lowering.
+    The function must not contain S-TIR blocks.
 
     Returns
     -------
diff --git a/src/s_tir/transform/force_narrow_index_to_i32.cc 
b/src/s_tir/transform/force_narrow_index_to_i32.cc
deleted file mode 100644
index e234b62662..0000000000
--- a/src/s_tir/transform/force_narrow_index_to_i32.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/*!
- * \file force_narrow_index_to_i32.cc
- * \brief Force narrow down indexing expressions and integer tensors to int32 
dtype in functions
- *        that still contain S-TIR blocks.
- * \note This pass is not used in default cases.
- */
-
-#include "../../tirx/transform/force_narrow_index_to_i32.h"
-
-#include <tvm/ffi/reflection/registry.h>
-#include <tvm/s_tir/transform.h>
-#include <tvm/tirx/transform.h>
-
-#include "../ir/data_type_rewriter.h"
-
-namespace tvm {
-namespace s_tir {
-using namespace tvm::tirx;
-
-class Int32DTypeNarrower : public 
Int32DTypeNarrowerBase<IndexDataTypeNormalizer> {
- public:
-  using Int32DTypeNarrowerBase::Mutate;
-  using Int32DTypeNarrowerBase::Mutate_;
-  static Function RewriteDataType(Function func) {
-    CheckTensorParams(func);
-    auto narrower = ffi::make_object<Int32DTypeNarrower>(func);
-    return narrower->Rewrite(func);
-  }
-
-  explicit Int32DTypeNarrower(Function func) : 
Int32DTypeNarrowerBase(std::move(func)) {}
-
- private:
-  UnchangedOr<Stmt> Mutate_(const SBlockNode* op, InplaceMode inplace_mode) 
final {
-    auto result = IndexDataTypeNormalizer::Mutate_(op, inplace_mode);
-    auto block = 
std::move(result).ValueOrUnchanged(ffi::GetRef<Stmt>(op)).as_or_throw<SBlock>();
-    for (const TensorVar& tensor : block->alloc_tensors) {
-      CheckAllocatedTensor(tensor);
-    }
-    return block;
-  }
-};
-
-namespace transform {
-
-Pass ForceNarrowIndexToInt32() {
-  auto pass_func = [](Function f, IRModule m, PassContext ctx) {
-    return Int32DTypeNarrower::RewriteDataType(std::move(f));
-  };
-  return CreateFunctionPass(pass_func, 0, "s_tir.ForceNarrowIndexToInt32");
-}
-
-TVM_FFI_STATIC_INIT_BLOCK() {
-  namespace refl = tvm::ffi::reflection;
-  refl::GlobalDef().def("s_tir.transform.ForceNarrowIndexToInt32", 
ForceNarrowIndexToInt32);
-}
-
-}  // namespace transform
-}  // namespace s_tir
-}  // namespace tvm
diff --git a/src/tirx/transform/force_narrow_index_to_i32.cc 
b/src/tirx/transform/force_narrow_index_to_i32.cc
index 4e44c07862..daf7cd152e 100644
--- a/src/tirx/transform/force_narrow_index_to_i32.cc
+++ b/src/tirx/transform/force_narrow_index_to_i32.cc
@@ -23,25 +23,87 @@
  * \note This pass is not used in default cases.
  */
 
-#include "force_narrow_index_to_i32.h"
-
 #include <tvm/ffi/cast.h>
 #include <tvm/ffi/reflection/registry.h>
+#include <tvm/ir/prim/op.h>
+#include <tvm/tirx/op/memory.h>
 #include <tvm/tirx/stmt_functor.h>
 #include <tvm/tirx/transform.h>
 
+#include <utility>
+
+#include "../ir/data_type_rewriter.h"
+
 namespace tvm {
 namespace tirx {
 
-class Int32DTypeNarrower : public 
Int32DTypeNarrowerBase<IndexDataTypeNormalizer> {
+class Int32DTypeNarrower : public IndexDataTypeNormalizer {
  public:
+  using IndexDataTypeNormalizer::Mutate;
+  using IndexDataTypeNormalizer::Mutate_;
+
   static Function RewriteDataType(Function func) {
     CheckTensorParams(func);
     auto narrower = ffi::make_object<Int32DTypeNarrower>(func);
     return narrower->Rewrite(func);
   }
 
-  explicit Int32DTypeNarrower(Function func) : 
Int32DTypeNarrowerBase(std::move(func)) {}
+  explicit Int32DTypeNarrower(Function func)
+      : IndexDataTypeNormalizer(PrimType::Int(32)), func_(std::move(func)) {}
+
+ private:
+  /*! \brief Reject integer tensor parameters wider than int32. */
+  static void CheckTensorParams(const Function& func) {
+    for (const Var& param : func->params) {
+      if (auto tensor = param.as<TensorVar>();
+          tensor && tensor.value()->dtype.MatchesCode(DLDataTypeCode::kDLInt) 
&&
+          tensor.value()->dtype.bits() > 32) {
+        TVM_FFI_THROW(InternalError) << "The tensor parameter " << 
tensor.value() << " has dtype "
+                                     << tensor.value()->dtype << ". The 
function is " << func;
+      }
+    }
+  }
+
+  /*! \brief Reject allocated integer tensors wider than int32. */
+  void CheckAllocatedTensor(const TensorVar& buf) const {
+    // Scalar assignments in TVMScript use local scalar storage.  Keep its 
explicit
+    // dtype (e.g. an int64 opaque call result) and cast at narrowed index 
uses.
+    // IsScalar checks the scalar layout contract, not merely the allocation 
size.
+    bool is_local_scalar = buf.scope() == "local" && buf.IsScalar();
+    if (!is_local_scalar && buf->dtype.MatchesCode(DLDataTypeCode::kDLInt) &&
+        buf->dtype.bits() > 32) {
+      TVM_FFI_THROW(InternalError)
+          << "The tensor " << buf << " allocated in the function has dtype " 
<< buf->dtype
+          << ". The function is " << func_;
+    }
+  }
+
+  bool ShouldClampShiftAmounts() const final { return true; }
+
+  UnchangedOr<PrimExpr> Mutate_(const IntImmNode* op, InplaceMode 
inplace_mode) final {
+    // ignore the enabled condition and always rewrite i64
+    if (op->ty.as_or_throw<PrimType>() == PrimType::Int(64)) {
+      TVM_FFI_ICHECK_LE(op->value, 
prim::max_value(target_data_type_).as_or_throw<IntImm>()->value);
+      return IntImm::Int32(op->value);
+    }
+    return ffi::Unchanged();
+  }
+
+  UnchangedOr<Stmt> Mutate_(const BindNode* op, InplaceMode inplace_mode) 
final {
+    if (const auto* call = op->value.as<CallNode>();
+        call && call->op.same_as(tirx::alloc_tensor_op()))
+      return MutateAllocTensor(op, inplace_mode);
+    return IndexDataTypeNormalizer::Mutate_(op, inplace_mode);
+  }
+
+  UnchangedOr<Stmt> MutateAllocTensor(const BindNode* op, InplaceMode 
inplace_mode) {
+    auto result = IndexDataTypeNormalizer::Mutate_(op, inplace_mode);
+    auto alloc = 
std::move(result).ValueOrUnchanged(ffi::GetRef<Stmt>(op)).as_or_throw<Bind>();
+    CheckAllocatedTensor(alloc->var.as_or_throw<TensorVar>());
+    return alloc;
+  }
+
+  Function func_;
 };
 
 Function ForceNarrowIndexToInt32(Function func) {
diff --git a/src/tirx/transform/force_narrow_index_to_i32.h 
b/src/tirx/transform/force_narrow_index_to_i32.h
deleted file mode 100644
index d04cb781dd..0000000000
--- a/src/tirx/transform/force_narrow_index_to_i32.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/*!
- * \file force_narrow_index_to_i32.h
- * \brief Narrowing rules shared by the TIRX and S-TIR ForceNarrowIndexToInt32 
passes.
- */
-#ifndef TVM_TIR_TRANSFORM_FORCE_NARROW_INDEX_TO_I32_H_
-#define TVM_TIR_TRANSFORM_FORCE_NARROW_INDEX_TO_I32_H_
-
-#include <tvm/ir/prim/op.h>
-#include <tvm/tirx/op/memory.h>
-
-#include <utility>
-
-#include "../ir/data_type_rewriter.h"
-
-namespace tvm {
-namespace tirx {
-
-/*!
- * \brief Force index expressions and integer tensors to int32.
- * \tparam Normalizer The index normalizer that determines which statements 
are traversed:
- *         tirx::IndexDataTypeNormalizer for lowered TIR, 
s_tir::IndexDataTypeNormalizer for
- *         TIR that still contains S-TIR blocks.
- */
-template <typename Normalizer>
-class Int32DTypeNarrowerBase : public Normalizer {
- public:
-  using Normalizer::Mutate;
-  using Normalizer::Mutate_;
-
- protected:
-  explicit Int32DTypeNarrowerBase(Function func)
-      : Normalizer(PrimType::Int(32)), func_(std::move(func)) {}
-
-  /*! \brief Reject integer tensor parameters wider than int32. */
-  static void CheckTensorParams(const Function& func) {
-    for (const Var& param : func->params) {
-      if (auto tensor = param.as<TensorVar>();
-          tensor && tensor.value()->dtype.MatchesCode(DLDataTypeCode::kDLInt) 
&&
-          tensor.value()->dtype.bits() > 32) {
-        TVM_FFI_THROW(InternalError) << "The tensor parameter " << 
tensor.value() << " has dtype "
-                                     << tensor.value()->dtype << ". The 
function is " << func;
-      }
-    }
-  }
-
-  /*! \brief Reject allocated integer tensors wider than int32. */
-  void CheckAllocatedTensor(const TensorVar& buf) const {
-    // Scalar assignments in TVMScript use local scalar storage.  Keep its 
explicit
-    // dtype (e.g. an int64 opaque call result) and cast at narrowed index 
uses.
-    // IsScalar checks the scalar layout contract, not merely the allocation 
size.
-    bool is_local_scalar = buf.scope() == "local" && buf.IsScalar();
-    if (!is_local_scalar && buf->dtype.MatchesCode(DLDataTypeCode::kDLInt) &&
-        buf->dtype.bits() > 32) {
-      TVM_FFI_THROW(InternalError)
-          << "The tensor " << buf << " allocated in the function has dtype " 
<< buf->dtype
-          << ". The function is " << func_;
-    }
-  }
-
-  bool ShouldClampShiftAmounts() const final { return true; }
-
-  UnchangedOr<PrimExpr> Mutate_(const IntImmNode* op, InplaceMode 
inplace_mode) final {
-    // ignore the enabled condition and always rewrite i64
-    if (op->ty.as_or_throw<PrimType>() == PrimType::Int(64)) {
-      TVM_FFI_ICHECK_LE(
-          op->value,
-          prim::max_value(this->target_data_type_).template 
as_or_throw<IntImm>()->value);
-      return IntImm::Int32(op->value);
-    }
-    return ffi::Unchanged();
-  }
-
-  UnchangedOr<Stmt> Mutate_(const BindNode* op, InplaceMode inplace_mode) 
final {
-    if (const auto* call = op->value.as<CallNode>();
-        call && call->op.same_as(tirx::alloc_tensor_op()))
-      return MutateAllocTensor(op, inplace_mode);
-    return Normalizer::Mutate_(op, inplace_mode);
-  }
-
-  UnchangedOr<Stmt> MutateAllocTensor(const BindNode* op, InplaceMode 
inplace_mode) {
-    auto result = Normalizer::Mutate_(op, inplace_mode);
-    auto alloc =
-        std::move(result).ValueOrUnchanged(ffi::GetRef<Stmt>(op)).template 
as_or_throw<Bind>();
-    CheckAllocatedTensor(alloc->var.template as_or_throw<TensorVar>());
-    return alloc;
-  }
-
-  Function func_;
-};
-
-}  // namespace tirx
-}  // namespace tvm
-
-#endif  // TVM_TIR_TRANSFORM_FORCE_NARROW_INDEX_TO_I32_H_
diff --git a/tests/python/relax/test_backend_dispatch_sort_scan.py 
b/tests/python/relax/test_backend_dispatch_sort_scan.py
index 1a71a3c1c2..809dbe25e1 100644
--- a/tests/python/relax/test_backend_dispatch_sort_scan.py
+++ b/tests/python/relax/test_backend_dispatch_sort_scan.py
@@ -521,7 +521,7 @@ def test_dispatch_sort_webgpu_merge_grid(op, size):
         pytest.param({"kind": "vulkan", "supports_int64": True}, 
marks=pytest.mark.gpu),
     ],
 )
[email protected]("index_bits", [None, 32, 64])
[email protected]("index_bits", [None, 64])
 def test_dispatch_cumsum_gpu(target, index_bits):
     """Test cumsum kernel dispatch and numerical correctness"""
     if not tvm.testing.device_enabled(target):
@@ -544,8 +544,6 @@ def test_dispatch_cumsum_gpu(target, index_bits):
     np_cumsum = np.cumsum(np_data, axis=-1)
     with tvm.target.Target(target):
         mod = DispatchSortScan(index_bits=index_bits)(Module)
-        if index_bits == 32:
-            mod = tvm.s_tir.transform.ForceNarrowIndexToInt32()(mod)
         ex = tvm.compile(mod, target)
 
     def run_and_check():
@@ -558,8 +556,8 @@ def test_dispatch_cumsum_gpu(target, index_bits):
     tvm.testing.run_with_gpu_lock(run_and_check)
 
 
[email protected]("target_kind", ["metal", "webgpu", "cuda"])
[email protected]("index_bits", [None, 32, 64])
[email protected]("target_kind", ["metal", "cuda"])
[email protected]("index_bits", [None, 64])
 def test_dispatch_cumsum_index_width(target_kind, index_bits):
     """Respect the caller's index budget without restricting Metal's 
default."""
     from tvm.relax.backend.gpu_generic import gpu_2d_continuous_cumsum
@@ -575,22 +573,10 @@ def test_dispatch_cumsum_index_width(target_kind, 
index_bits):
             return gv
 
     with tvm.target.Target(target_kind, host="llvm"):
-        if target_kind == "webgpu" and index_bits == 64:
-            with pytest.raises(ValueError, match="WebGPU scan kernels require 
index_bits=32"):
-                DispatchSortScan(index_bits=index_bits)(Module)
-            return
         mod = DispatchSortScan(index_bits=index_bits)(Module)
 
-    expected_bits = (
-        index_bits if index_bits is not None else (32 if target_kind == 
"webgpu" else 64)
-    )
-    expected = gpu_2d_continuous_cumsum(
-        in_dtype="float32", out_dtype="float32", index_bits=expected_bits
-    )
+    expected = gpu_2d_continuous_cumsum(in_dtype="float32", 
out_dtype="float32", index_bits=64)
     assert_structural_equal(mod["gpu_2d_continuous_cumsum"], expected)
-    if expected_bits == 32:
-        # This previously failed on Metal with a 2**35 IntImm.
-        tvm.s_tir.transform.ForceNarrowIndexToInt32()(mod)
 
 
 @pytest.mark.parametrize("index_bits", [0, 16, 128])
diff --git 
a/tests/python/s_tir/transform/test_s_tir_transform_force_narrow_index_to_i32.py
 
b/tests/python/s_tir/transform/test_s_tir_transform_force_narrow_index_to_i32.py
deleted file mode 100644
index 9cbfba3a08..0000000000
--- 
a/tests/python/s_tir/transform/test_s_tir_transform_force_narrow_index_to_i32.py
+++ /dev/null
@@ -1,177 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-import pytest
-
-import tvm
-import tvm.testing
-from tvm.s_tir import dlight as dl
-from tvm.script import s_tir as Ts
-from tvm.script import tirx as T
-from tvm.testing import env
-
-
-def _narrow(func):
-    mod = tvm.IRModule.from_expr(func)
-    return tvm.s_tir.transform.ForceNarrowIndexToInt32()(mod)["main"]
-
-
-def test_block():
-    @Ts.function(private=True)
-    def before(A: T.Tensor((128,), "float32"), B: T.Tensor((128,), "float32")):
-        for i in T.serial(0, T.int64(16)):
-            for j in T.serial(0, T.int64(8)):
-                with Ts.sblock():
-                    vi = Ts.axis.spatial(T.int64(128), i * T.int64(8) + j)
-                    B[vi] = A[vi] + T.float32(1)
-
-    @Ts.function(private=True)
-    def expected(A: T.Tensor((128,), "float32"), B: T.Tensor((128,), 
"float32")):
-        for i in T.serial(0, T.int32(16)):
-            for j in T.serial(0, T.int32(8)):
-                with Ts.sblock():
-                    vi = Ts.axis.spatial(T.int32(128), i * T.int32(8) + j)
-                    B[vi] = A[vi] + T.float32(1)
-
-    tvm.ir.assert_structural_equal(_narrow(before), expected)
-
-
-def test_block_iters_used_only_in_regions():
-    """Blockized blocks use their iterators only in access and match_tensor 
regions."""
-
-    @Ts.function(private=True)
-    def before(
-        A: T.Tensor((T.int64(16), T.int64(16)), "float32"),
-        B: T.Tensor((T.int64(16), T.int64(16)), "float32"),
-    ):
-        for i_o, j_o in T.grid(T.int64(2), T.int64(2)):
-            with Ts.sblock("tile_o"):
-                vi_o, vj_o = Ts.axis.remap("SS", [i_o, j_o])
-                Ts.reads(
-                    A[
-                        vi_o * T.int64(8) : vi_o * T.int64(8) + T.int64(8),
-                        vj_o * T.int64(8) : vj_o * T.int64(8) + T.int64(8),
-                    ]
-                )
-                Ts.writes(
-                    B[
-                        vi_o * T.int64(8) : vi_o * T.int64(8) + T.int64(8),
-                        vj_o * T.int64(8) : vj_o * T.int64(8) + T.int64(8),
-                    ]
-                )
-                A_tile = Ts.match_tensor(
-                    A[
-                        vi_o * T.int64(8) : vi_o * T.int64(8) + T.int64(8),
-                        vj_o * T.int64(8) : vj_o * T.int64(8) + T.int64(8),
-                    ],
-                    (T.int64(8), T.int64(8)),
-                    offset_factor=1,
-                )
-                B_tile = Ts.match_tensor(
-                    B[
-                        vi_o * T.int64(8) : vi_o * T.int64(8) + T.int64(8),
-                        vj_o * T.int64(8) : vj_o * T.int64(8) + T.int64(8),
-                    ],
-                    (T.int64(8), T.int64(8)),
-                    offset_factor=1,
-                )
-                for i_i, j_i in T.grid(T.int64(8), T.int64(8)):
-                    with Ts.sblock("tile"):
-                        vi_i, vj_i = Ts.axis.remap("SS", [i_i, j_i])
-                        B_tile[vi_i, vj_i] = A_tile[vi_i, vj_i] + T.float32(1)
-
-    @Ts.function(private=True)
-    def expected(A: T.Tensor((16, 16), "float32"), B: T.Tensor((16, 16), 
"float32")):
-        for i_o, j_o in T.grid(2, 2):
-            with Ts.sblock("tile_o"):
-                vi_o, vj_o = Ts.axis.remap("SS", [i_o, j_o])
-                Ts.reads(A[vi_o * 8 : vi_o * 8 + 8, vj_o * 8 : vj_o * 8 + 8])
-                Ts.writes(B[vi_o * 8 : vi_o * 8 + 8, vj_o * 8 : vj_o * 8 + 8])
-                A_tile = Ts.match_tensor(
-                    A[vi_o * 8 : vi_o * 8 + 8, vj_o * 8 : vj_o * 8 + 8], (8, 
8), offset_factor=1
-                )
-                B_tile = Ts.match_tensor(
-                    B[vi_o * 8 : vi_o * 8 + 8, vj_o * 8 : vj_o * 8 + 8], (8, 
8), offset_factor=1
-                )
-                for i_i, j_i in T.grid(8, 8):
-                    with Ts.sblock("tile"):
-                        vi_i, vj_i = Ts.axis.remap("SS", [i_i, j_i])
-                        B_tile[vi_i, vj_i] = A_tile[vi_i, vj_i] + T.float32(1)
-
-    tvm.ir.assert_structural_equal(_narrow(before), expected)
-
-
-def test_fail_on_tensor_param():
-    @Ts.function(private=True)
-    def func(A: T.Tensor((128,), "int64"), B: T.Tensor((128,), "int64")):
-        for i in T.serial(0, 16):
-            for j in T.serial(0, 8):
-                with Ts.sblock():
-                    vi = Ts.axis.spatial(128, i * 8 + j)
-                    B[vi] = A[vi] + T.int64(1)
-
-    with pytest.raises(RuntimeError):
-        _narrow(func)
-
-
-def test_fail_on_block_alloc_tensor():
-    @Ts.function(private=True)
-    def func(A: T.Tensor((128,), "int32"), B: T.Tensor((128,), "int32")):
-        C = Ts.sblock_alloc_tensor((128,), "int64")
-        for i in T.serial(0, 16):
-            for j in T.serial(0, 8):
-                with Ts.sblock():
-                    vi = Ts.axis.spatial(128, i * 8 + j)
-                    C[vi] = T.cast(A[vi], "int64") + T.int64(1)
-        for i in T.serial(0, 16):
-            for j in T.serial(0, 8):
-                with Ts.sblock():
-                    vi = Ts.axis.spatial(128, i * 8 + j)
-                    B[vi] = T.cast(C[vi] + T.int64(1), "int32")
-
-    with pytest.raises(RuntimeError):
-        _narrow(func)
-
-
[email protected](not env.has_llvm(), reason="need llvm for the host module")
-def test_metal_simdgroup_matmul_builds():
-    """Narrowing a DLight-scheduled Metal matmul keeps its tensorized blocks 
consistent."""
-
-    n = T.dynamic("n")
-
-    @Ts.function
-    def main(
-        A: T.Tensor((T.int64(1), n, T.int64(256)), "float16"),
-        B: T.Tensor((T.int64(256), T.int64(256)), "float16"),
-        C: T.Tensor((T.int64(1), n, T.int64(256)), "float16"),
-    ):
-        for i0, i1, i2, k in T.grid(T.int64(1), n, T.int64(256), T.int64(256)):
-            with Ts.sblock("NT_matmul"):
-                v0, v1, v2, vk = Ts.axis.remap("SSSR", [i0, i1, i2, k])
-                with Ts.init():
-                    C[v0, v1, v2] = T.float16(0)
-                C[v0, v1, v2] = C[v0, v1, v2] + A[v0, v1, vk] * B[v2, vk]
-
-    target = tvm.target.Target("metal", host="llvm")
-    with target:
-        mod = dl.ApplyDefaultSchedule(dl.gpu.Matmul())(tvm.IRModule({"main": 
main}))
-    assert "metal.simdgroup" in mod.script()
-    mod = tvm.s_tir.transform.ForceNarrowIndexToInt32()(mod)
-    tvm.tirx.compile(mod, target=target).mod
-
-
-if __name__ == "__main__":
-    tvm.testing.main()

Reply via email to