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 15fe7c6af9 [REFACTOR][TIRx] Simplify the transform API (#20635)
15fe7c6af9 is described below

commit 15fe7c6af9b4f7681948ed9615490e1f1e0c1d95
Author: Tianqi Chen <[email protected]>
AuthorDate: Fri Oct 9 18:42:43 2026 -0400

    [REFACTOR][TIRx] Simplify the transform API (#20635)
    
    Remove the unused TIRx private-function inlining and thread-axis
    remapping APIs and the unimplemented static-memory planner declaration.
    Rename `TilePrimitiveDispatch` to `TileDispatch` consistently across
    native and Python interfaces, pass identity, callers, source naming, and
    documentation.
    
    The dispatch implementation and lowering order are preserved.
---
 docs/tirx/arch/lowering_pipeline.rst               |   4 +-
 docs/tirx/arch/tile_dispatch.rst                   |   2 +-
 include/tvm/tirx/transform.h                       |  29 +-
 .../cuda/tile_primitive/copy/vec_auto_reg.py       |   4 +-
 python/tvm/backend/trn/pipeline.py                 |   2 +-
 python/tvm/backend/trn/transform/__init__.py       |   2 +-
 python/tvm/tirx/transform/transform.py             |  15 +-
 src/tirx/analysis/filter_canonical.cc              |   2 +-
 src/tirx/analysis/filter_canonical.h               |   8 +-
 src/tirx/transform/inline_private_functions.cc     | 320 ---------------------
 src/tirx/transform/lower_tirx.cc                   |   4 +-
 src/tirx/transform/remap_thread_axis.cc            | 113 --------
 ...tile_primitive_dispatch.cc => tile_dispatch.cc} |  14 +-
 .../test_tir_inline_private_functions.py           | 251 ----------------
 .../operator/tile_primitive/cuda/copy/test_reg.py  |   2 +-
 15 files changed, 25 insertions(+), 747 deletions(-)

diff --git a/docs/tirx/arch/lowering_pipeline.rst 
b/docs/tirx/arch/lowering_pipeline.rst
index e4a7844560..37f7fa5ad8 100644
--- a/docs/tirx/arch/lowering_pipeline.rst
+++ b/docs/tirx/arch/lowering_pipeline.rst
@@ -126,9 +126,9 @@ Inside LowerTIRx
 
 .. code-block:: text
 
-    LowerTIRx = Sequential([ TilePrimitiveDispatch, LowerTIRxCleanup ])
+    LowerTIRx = Sequential([ TileDispatch, LowerTIRxCleanup ])
 
-- **``TilePrimitiveDispatch``** replaces every tensor ``Evaluate(Call)`` with 
the body emitted by its
+- **``TileDispatch``** replaces every tensor ``Evaluate(Call)`` with the body 
emitted by its
   instruction lowerer, including delayed mathematical composites as described 
in
   :doc:`tile_dispatch`.  In the same pass it removes the ``device_entry``
   marker, resolves standalone scope-id definitions to ``Bind`` statements,
diff --git a/docs/tirx/arch/tile_dispatch.rst b/docs/tirx/arch/tile_dispatch.rst
index a62738bbca..fd7f04f9ef 100644
--- a/docs/tirx/arch/tile_dispatch.rst
+++ b/docs/tirx/arch/tile_dispatch.rst
@@ -24,7 +24,7 @@ in ``python/tvm/backend/{cuda,trn}/tensor_instructions.py`` 
using the shared
 ``python/tvm/tirx/tensor_instruction.py`` machinery. C++ reflected attribute
 types and the native Call validator are in ``src/tirx/op/tile.cc``.
 
-``tirx.TilePrimitiveDispatch`` remains the first phase of ``LowerTIRx``.
+``tirx.TileDispatch`` remains the first phase of ``LowerTIRx``.
 The pass recognizes ``Evaluate(Call)`` by the operator's ``TIRxOpCategory``:
 ``tile_primitive`` or ``tile_composite``. It validates the call, resolves the
 scope against the active thread set, constructs a ``DispatchContext``, and
diff --git a/include/tvm/tirx/transform.h b/include/tvm/tirx/transform.h
index a5e68d54be..a000e82f93 100644
--- a/include/tvm/tirx/transform.h
+++ b/include/tvm/tirx/transform.h
@@ -154,18 +154,6 @@ TVM_DLL Pass LowerThreadAllreduce();
  */
 TVM_DLL Pass MakePackedAPI();
 
-/*!
- * \brief Remap the thread axis
- *
- *  This can be used to get equivalent program which uses
- *  threadIdx.y in place of threadIdx.x by passing
- *  {"threadIdx.x": "threadIdx.y"}
- *
- *
- * \return The pass.
- */
-TVM_DLL Pass RemapThreadAxis(ffi::Map<ffi::String, ffi::String> axis_map);
-
 /*!
  * \brief Annotate, split, and lower host/device functions.
  *
@@ -267,13 +255,6 @@ TVM_DLL Pass BF16StorageLegalize();
  */
 TVM_DLL Pass FP8StorageLegalize();
 
-/*!
- * \brief Inline calls to private functions
- *
- * \return The pass.
- */
-TVM_DLL Pass InlinePrivateFunctions();
-
 /*!
  * \brief Rewrite the pointer content type of arguments,
  *  as well as Alloc internal to the function to use
@@ -298,14 +279,6 @@ TVM_DLL Pass FlattenBuffer();
  */
 TVM_DLL Pass CommonSubexprElim();
 
-/*!
- * \brief This is the unified static memory planner pass that will
- * plan for memory intra- and inter- Functions together. The pass
- * requires all the function to be Functions including the main.
- * \return The pass.
- */
-TVM_DLL Pass UnifiedStaticMemoryPlanner();
-
 /*!
  * \brief Annotate a Function with a given target.
  * \return The pass.
@@ -332,7 +305,7 @@ TVM_DLL Pass Filter(ffi::TypedFunction<bool(Function)> 
fcond);
  * launch_thread RegionStmts wrapping the dispatched body.
  * \return The pass.
  */
-TVM_DLL Pass TilePrimitiveDispatch();
+TVM_DLL Pass TileDispatch();
 
 /*!
  * \brief Finalize TIRx lowering by applying layout rewriters and cleanup 
passes.
diff --git a/python/tvm/backend/cuda/tile_primitive/copy/vec_auto_reg.py 
b/python/tvm/backend/cuda/tile_primitive/copy/vec_auto_reg.py
index a411e1a502..c9c6542028 100644
--- a/python/tvm/backend/cuda/tile_primitive/copy/vec_auto_reg.py
+++ b/python/tvm/backend/cuda/tile_primitive/copy/vec_auto_reg.py
@@ -364,9 +364,9 @@ def _axis_decl(axis_name: str, sctx: DispatchContext):
     """Declare the runtime Var for one thread axis (called inside impl body).
 
     Each scope_id declarator emits a ``ScopeIdDef`` stmt at the current
-    builder frame. ``TilePrimitiveDispatch`` re-gathers + resolves all
+    builder frame. ``TileDispatch`` re-gathers + resolves all
     ScopeIdDefs after dispatch (see ``ResolveAllScopeBinds`` in
-    ``tile_primitive_dispatch.cc``), so dispatch-introduced vars are bound
+    ``tile_dispatch.cc``), so dispatch-introduced vars are bound
     alongside kernel-declared ones.
 
     Extents are deferred: the kernel header is expected to declare the full
diff --git a/python/tvm/backend/trn/pipeline.py 
b/python/tvm/backend/trn/pipeline.py
index c2679e207b..dd9b252e1c 100644
--- a/python/tvm/backend/trn/pipeline.py
+++ b/python/tvm/backend/trn/pipeline.py
@@ -32,7 +32,7 @@ def trn_pipeline():
         passes = [
             trn_transform.TrnPrivateBufferAlloc(),
             trn_transform.TrnNaiveAllocator(),
-            tirx.transform.TilePrimitiveDispatch(),
+            tirx.transform.TileDispatch(),
             trn_transform.LowerTrainiumLayout(),
             tvm.s_tir.transform.DecorateDeviceScope(),
             tirx.transform.StmtSimplify(),
diff --git a/python/tvm/backend/trn/transform/__init__.py 
b/python/tvm/backend/trn/transform/__init__.py
index b74b98b0c6..703f0c6e7f 100644
--- a/python/tvm/backend/trn/transform/__init__.py
+++ b/python/tvm/backend/trn/transform/__init__.py
@@ -36,7 +36,7 @@ def LowerTrainiumLayout():
 def LowerTIRx():
     """Lower TIRx tile primitive calls for the Trainium backend."""
     return tvm.transform.Sequential(
-        [tirx.transform.TilePrimitiveDispatch(), LowerTrainiumLayout()],
+        [tirx.transform.TileDispatch(), LowerTrainiumLayout()],
         name="tirx.backend.trn.LowerTIRx",
     )
 
diff --git a/python/tvm/tirx/transform/transform.py 
b/python/tvm/tirx/transform/transform.py
index c0b5eeea23..12e69f0551 100644
--- a/python/tvm/tirx/transform/transform.py
+++ b/python/tvm/tirx/transform/transform.py
@@ -85,17 +85,6 @@ def StorageRewrite():
     return _ffi_api.StorageRewrite()  # type: ignore
 
 
-def InlinePrivateFunctions():
-    """Inline calls to private functions
-
-    Returns
-    -------
-    fpass : tvm.transform.Pass
-        The result pass
-    """
-    return _ffi_api.InlinePrivateFunctions()  # type: ignore
-
-
 def PointerValueTypeRewrite():
     """
     Rewrite the pointer content type of arguments, as well as Alloc internal 
to the function to use
@@ -459,7 +448,7 @@ def Filter(fcond: Callable):
     return _ffi_api.Filter(fcond)  # type: ignore
 
 
-def TilePrimitiveDispatch():
+def TileDispatch():
     """Lower TIRx tile primitive calls through the active backend dispatch 
table.
 
     Returns
@@ -467,7 +456,7 @@ def TilePrimitiveDispatch():
     fpass : tvm.transform.Pass
         The result pass
     """
-    return _ffi_api.TilePrimitiveDispatch()  # type: ignore
+    return _ffi_api.TileDispatch()  # type: ignore
 
 
 def LowerTIRx():
diff --git a/src/tirx/analysis/filter_canonical.cc 
b/src/tirx/analysis/filter_canonical.cc
index 5e23d921ee..d85c9f76a2 100644
--- a/src/tirx/analysis/filter_canonical.cc
+++ b/src/tirx/analysis/filter_canonical.cc
@@ -55,7 +55,7 @@ PrimExpr StripCast(const PrimExpr& expr) {
 }
 
 // Recognized conjunction shapes: logical-And and bitwise-And nodes.
-// Mirrors FlattenConjuncts in tile_primitive_dispatch.cc so the classifier
+// Mirrors FlattenConjuncts in tile_dispatch.cc so the classifier
 // accepts the same set of "fully conjunctive" predicates that the existing
 // pass-internal helpers do.
 void FlattenConjuncts(const PrimExpr& pred, std::vector<PrimExpr>* out) {
diff --git a/src/tirx/analysis/filter_canonical.h 
b/src/tirx/analysis/filter_canonical.h
index 200fdf6207..a2df5c02a7 100644
--- a/src/tirx/analysis/filter_canonical.h
+++ b/src/tirx/analysis/filter_canonical.h
@@ -30,7 +30,7 @@
  *         | Call("tirx.cuda.elect_sync")
  *
  * Consumers:
- *   1. tile_primitive_dispatch routes a bare `if cond:` to atom-based
+ *   1. tile_dispatch routes a bare `if cond:` to atom-based
  *      narrowing when cond is canonical; otherwise treats it as a regular
  *      data-dependent branch (no narrowing).
  *   2. The `tirx.gpu_thread_filter(var, pred)` escape-hatch wrapper is 
intended for the
@@ -79,7 +79,7 @@ enum class FilterAtomKind {
  * For `kElectSync`:
  *   - `elect_sync_call`: the original `Call("tirx.cuda.elect_sync")` PrimExpr,
  *     preserved verbatim so downstream consumers (e.g. selector construction
- *     in tile_primitive_dispatch) can reuse it without re-synthesizing.
+ *     in tile_dispatch) can reuse it without re-synthesizing.
  *   - `scopeid_var`, `lo`, `hi` are unset.
  */
 struct FilterAtom {
@@ -108,7 +108,7 @@ struct CanonicalForm {
  * The classifier consults this for every variable that appears on the LHS
  * of a comparison atom. The callback abstracts over how scope ids are
  * tracked in the caller's context:
- *   - TilePrimitiveDispatcher passes a lambda that walks its
+ *   - TileDispatcher passes a lambda that walks its
  *     `scope_id_defs_at_level_` stack.
  *   - Tests may pass a simpler lambda over a fixed allow-list of vars.
  *
@@ -135,7 +135,7 @@ using ScopeIdPredicate = std::function<bool(const Var&)>;
  * Implementation notes:
  *   - Conjunction is recognized via both `tir::And` nodes and
  *     `prim.BitwiseAnd` nodes (matching existing FlattenConjuncts behavior
- *     in tile_primitive_dispatch.cc).
+ *     in tile_dispatch.cc).
  *   - Comparison atoms with `const <op> var` are mirrored so the
  *     `scopeid_var` is on the LHS of the returned atom.
  *   - `c1 == c2` (two constants), `v1 == v2` (two vars), and any other
diff --git a/src/tirx/transform/inline_private_functions.cc 
b/src/tirx/transform/inline_private_functions.cc
deleted file mode 100644
index 919d56809c..0000000000
--- a/src/tirx/transform/inline_private_functions.cc
+++ /dev/null
@@ -1,320 +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 inline_private_functions.cc
- * \brief Inline private functions to their callsite
- */
-#include <tvm/ffi/function.h>
-#include <tvm/ffi/reflection/registry.h>
-#include <tvm/ir/prim/op.h>
-#include <tvm/tirx/analysis.h>
-#include <tvm/tirx/stmt.h>
-#include <tvm/tirx/stmt_functor.h>
-#include <tvm/tirx/transform.h>
-
-namespace tvm {
-namespace tirx {
-namespace transform {
-
-namespace {
-
-template <typename T>
-using PSet = std::unordered_set<T, ffi::ObjectPtrHash, ffi::ObjectPtrEqual>;
-
-template <typename T, typename U>
-using PMap = std::unordered_map<T, U, ffi::ObjectPtrHash, ffi::ObjectPtrEqual>;
-
-PMap<GlobalVar, PSet<GlobalVar>> CollectCallMap(const IRModule& mod) {
-  struct Visitor : StmtExprVisitor {
-    GlobalVar current{ffi::UnsafeInit{}};
-    PMap<GlobalVar, PSet<GlobalVar>> caller_lookup;
-
-    ffi::Optional<VisitInterrupt> Visit_(const CallNode* op) final {
-      if (auto gvar = op->op.as<GlobalVar>()) {
-        caller_lookup[gvar.value()].insert(current);
-      }
-      return StmtExprVisitor::Visit_(op);
-    }
-  };
-  auto visitor = ffi::make_object<Visitor>();
-
-  for (const auto& [gvar, base_func] : mod->functions) {
-    if (auto function = base_func.as<FunctionNode>()) {
-      visitor->current = gvar;
-      visitor->Visit(function->body);
-    }
-  }
-
-  return visitor->caller_lookup;
-}
-
-PSet<GlobalVar> CollectRecursiveFunctions(const IRModule& mod) {
-  // Collect all direct callers
-  auto call_map = CollectCallMap(mod);
-
-  // Propagate to find all indirect callers
-  while (true) {
-    bool made_change = false;
-    for (const auto& [callee, callers] : call_map) {
-      for (const auto& caller : callers) {
-        if (auto it = call_map.find(caller); it != call_map.end()) {
-          PSet<GlobalVar>& indirect_callers = it->second;
-
-          auto res = indirect_callers.insert(callee);
-          made_change = made_change || res.second;
-        }
-      }
-    }
-    if (!made_change) {
-      break;
-    }
-  }
-
-  // Filter all GlobalVars that can be called by themselves, either
-  // directly or indirectly.
-  PSet<GlobalVar> recursive_funcs;
-  for (const auto& [caller, callees] : call_map) {
-    if (callees.count(caller)) {
-      recursive_funcs.insert(caller);
-    }
-  }
-  return recursive_funcs;
-}
-
-bool IsInlinableFunction(const GlobalVar& gvar, const Function& function,
-                         const PSet<GlobalVar>& recursive_functions) {
-  // Only inline private functions.  Externally-exposed functions
-  // must be preserved so to avoid breaking callsites outside of
-  // the IRModule.
-  bool is_exposed = 
function->GetAttr<ffi::String>(tvm::attr::kGlobalSymbol).has_value();
-  if (is_exposed) return false;
-
-  // We do not currently implement any analysis for termination of
-  // a function.  If a recursive function requires runtime checks
-  // in order to terminate, we would keep inlining until the
-  // recursive visits segfault.
-  bool is_recursive = recursive_functions.count(gvar);
-  if (is_recursive) return false;
-
-  // We do not currently support inlining of functions that accept
-  // buffer arguments.
-  for (const Var& param : function->params) {
-    if (param->ty.as<TensorTypeNode>()) return false;
-  }
-
-  // Generalize the old SBlockRealize exclusion to all non-native statement 
roots:
-  // they may introduce binder or naming rules that this pass cannot preserve.
-  // Only inline roots supported by native TIRX traversal.
-  struct NativeStmtTable : StmtExprVisitor {
-    static VTable Make() {
-      VTable table;
-      InitVTable(&table);
-      table.Finalize();
-      return table;
-    }
-  };
-  static const auto native_stmts = NativeStmtTable::Make();
-  if (!function->body.has_value() || 
!native_stmts.CanDispatch(function->body.get())) {
-    return false;
-  }
-
-  return true;
-}
-
-ffi::Map<GlobalVar, Function> CollectInlinableFunctions(const IRModule& mod) {
-  auto recursive_functions = CollectRecursiveFunctions(mod);
-
-  ffi::Map<GlobalVar, Function> output;
-  for (const auto& [gvar, base_func] : mod->functions) {
-    if (auto opt = base_func.as<Function>()) {
-      auto function = opt.value();
-      if (IsInlinableFunction(gvar, function, recursive_functions)) {
-        output.Set(gvar, function);
-      }
-    }
-  }
-
-  return output;
-}
-
-class FunctionInliner : public StmtExprMutator {
- public:
-  using StmtExprMutator::Mutate;
-  using StmtExprMutator::Mutate_;
-  explicit FunctionInliner(ffi::Map<GlobalVar, Function> inlinable_funcs)
-      : inlinable_funcs_(inlinable_funcs) {
-    for (const auto& [gvar, callee] : inlinable_funcs_) {
-      removable_funcs_.insert(gvar);
-    }
-  }
-
-  Function VisitFunc(Function func) {
-    current_target_ = func->GetAttr<Target>(tvm::attr::kTarget);
-    auto new_body_result = Mutate(func->body, InplaceMode::kDisallow);
-    bool new_body_unchanged = new_body_result.UnchangedOrSameAs(func->body);
-    auto new_body = std::move(new_body_result).ValueOrUnchanged(func->body);
-    current_target_ = std::nullopt;
-
-    if (!new_body_unchanged) {
-      func.CopyOnWrite()->body = new_body;
-    }
-
-    return func;
-  }
-
-  PSet<GlobalVar> GetRemovableFunctions() const { return removable_funcs_; }
-
- private:
-  UnchangedOr<Stmt> Mutate_(const EvaluateNode* eval, InplaceMode 
inplace_mode) override {
-    if (auto inlined = GetInlinedFunction(eval)) {
-      return inlined.value();
-    } else {
-      return StmtExprMutator::Mutate_(eval, inplace_mode);
-    }
-  }
-
-  ffi::Optional<Stmt> GetInlinedFunction(const EvaluateNode* eval) {
-    auto call = eval->value.as<CallNode>();
-    if (!call) return std::nullopt;
-
-    auto gvar = call->op.as<GlobalVar>();
-    if (!gvar) return std::nullopt;
-
-    auto opt_callee = inlinable_funcs_.Get(gvar.value());
-    if (!opt_callee) return std::nullopt;
-    auto callee = opt_callee.value();
-
-    bool is_same_target = [&]() -> bool {
-      auto callee_target = callee->GetAttr<Target>(tvm::attr::kTarget);
-      if (current_target_ && callee_target) {
-        return callee_target.value()->str() == current_target_.value()->str();
-      } else {
-        return true;
-      }
-    }();
-    if (!is_same_target) return std::nullopt;
-
-    Stmt inlined = InlineArguments(gvar.value(), callee, call->args);
-    return Mutate(inlined, InplaceMode::kDisallow).ValueOrUnchanged(inlined);
-  }
-
-  UnchangedOr<Expr> Mutate_(const CallNode* call, InplaceMode inplace_mode) 
override {
-    // Because the current implementation inlines a subroutine inserts
-    // the `Stmt` body at the point of use, replacement must
-    // occur in a context where a `Stmt` can be returned. Support
-    // of subroutines that are called within an expression
-    // (e.g. Replacing func in `Buf[0] = func(1) + func(2)`) would
-    // require hoisting preprocessing done in the subroutine to the
-    // parent `Stmt`.
-    //
-    // See `TestInlineCallOccurringInExpression` in
-    // `test_tir_inline_private_functions.py` for a test of this
-    // behavior, currently marked with `pytest.mark.xfail`.
-    //
-    // Any callee that hasn't been inlined at this point must be kept
-    // in the output IRModule.
-    if (auto gvar = call->op.as<GlobalVar>()) {
-      removable_funcs_.erase(gvar.value());
-    }
-    return StmtExprMutator::Mutate_(call, inplace_mode);
-  }
-
-  Stmt InlineArguments(const GlobalVar& gvar, Function callee, const 
ffi::Array<Expr>& args) const {
-    TVM_FFI_ICHECK_EQ(callee->params.size(), args.size())
-        << "Callee " << gvar << " accepts " << callee->params.size() << " 
parameters ("
-        << callee->params << "), but is called with " << args.size() << " 
arguments (" << args
-        << ")";
-
-    for (const Var& param : callee->params) {
-      TVM_FFI_ICHECK(!param->ty.as<TensorTypeNode>())
-          << "Inlining of Functions with buffer arguments is not yet 
supported, "
-          << "but callee " << gvar << " has TensorType-annotated parameter " 
<< param;
-    }
-
-    ffi::Map<Var, ffi::Variant<tirx::TensorVar, tvm::Expr>> param_map;
-    for (size_t i = 0; i < callee->params.size(); i++) {
-      param_map.Set(callee->params[i], args[i]);
-    }
-
-    callee = Specialize(callee, param_map);
-
-    return callee->body.value();
-  }
-
-  // Map from GlobalVar to Functions which may be inlined.
-  ffi::Map<GlobalVar, Function> inlinable_funcs_;
-
-  /* \brief Set of callees that may be removed
-   *
-   * Some constructs may not be inlined (e.g. if the call site occurs
-   * outside of an Evaluate node).  For these cases, the output
-   * IRModule must still contain the callee.
-   */
-  PSet<GlobalVar> removable_funcs_;
-
-  ffi::Optional<Target> current_target_ = std::nullopt;
-};
-
-}  // namespace
-
-Pass InlinePrivateFunctions() {
-  auto pass_func = [](IRModule mod, PassContext ctx) {
-    auto inlinable_functions = CollectInlinableFunctions(mod);
-
-    if (inlinable_functions.empty()) {
-      // Early bail-out if the module has no inlinable Functions.
-      return mod;
-    }
-
-    auto mutator = 
ffi::make_object<FunctionInliner>(std::move(inlinable_functions));
-    IRModule updates;
-
-    for (const auto& [gvar, base_func] : mod->functions) {
-      if (auto opt = base_func.as<Function>()) {
-        auto updated = mutator->VisitFunc(opt.value());
-        if (!updated.same_as(base_func)) {
-          updates->Add(gvar, updated);
-        }
-      }
-    }
-
-    if (updates->functions.size()) {
-      auto write_ptr = mod.CopyOnWrite();
-      write_ptr->Update(updates);
-      for (const auto& gvar : mutator->GetRemovableFunctions()) {
-        write_ptr->Remove(gvar);
-      }
-      mod = ConvertSSA()(mod);
-    }
-
-    return mod;
-  };
-  return tvm::transform::CreateModulePass(pass_func, 0, 
"tirx.InlinePrivateFunctions");
-}
-
-TVM_FFI_STATIC_INIT_BLOCK() {
-  namespace refl = tvm::ffi::reflection;
-  refl::GlobalDef().def("tirx.transform.InlinePrivateFunctions", 
InlinePrivateFunctions);
-}
-
-}  // namespace transform
-
-}  // namespace tirx
-}  // namespace tvm
diff --git a/src/tirx/transform/lower_tirx.cc b/src/tirx/transform/lower_tirx.cc
index c351a934e3..b093d59861 100644
--- a/src/tirx/transform/lower_tirx.cc
+++ b/src/tirx/transform/lower_tirx.cc
@@ -34,7 +34,7 @@ namespace tirx {
 namespace transform {
 
 Pass LowerTIRx() {
-  std::vector<tvm::transform::Pass> passes = {TilePrimitiveDispatch()};
+  std::vector<tvm::transform::Pass> passes = {TileDispatch()};
   if (std::getenv("TVM_PRINT_AFTER_TIRX_DISPATCH_OPS")) {
     passes.push_back(tvm::transform::PrintIR());
   }
@@ -45,7 +45,7 @@ Pass LowerTIRx() {
 TVM_FFI_STATIC_INIT_BLOCK() {
   namespace refl = tvm::ffi::reflection;
   refl::GlobalDef()
-      .def("tirx.transform.TilePrimitiveDispatch", TilePrimitiveDispatch)
+      .def("tirx.transform.TileDispatch", TileDispatch)
       .def("tirx.transform.LowerTIRxCleanup", LowerTIRxCleanup)
       .def("tirx.transform.LowerTIRx", LowerTIRx);
 }
diff --git a/src/tirx/transform/remap_thread_axis.cc 
b/src/tirx/transform/remap_thread_axis.cc
deleted file mode 100644
index 2d7e21fd20..0000000000
--- a/src/tirx/transform/remap_thread_axis.cc
+++ /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 remap_thread_axis.cc
- */
-#include <tvm/ffi/function.h>
-#include <tvm/ffi/reflection/registry.h>
-#include <tvm/ir/prim/expr.h>
-#include <tvm/ir/prim/op.h>
-#include <tvm/tirx/op/region.h>
-#include <tvm/tirx/stmt_functor.h>
-#include <tvm/tirx/transform.h>
-
-#include <unordered_map>
-
-namespace tvm {
-namespace tirx {
-
-// Mutator to change the read pattern
-class ThreadAxisRewriter : public StmtExprMutator {
- public:
-  using StmtExprMutator::Mutate;
-  using StmtExprMutator::Mutate_;
-  explicit ThreadAxisRewriter(const std::unordered_map<std::string, 
ffi::String>& tmap)
-      : tmap_(tmap) {}
-
-  Stmt Rewrite(Stmt stmt) { return Mutate(stmt, 
InplaceMode::kAllow).ValueOrUnchanged(stmt); }
-
- private:
-  UnchangedOr<Stmt> Mutate_(const RegionStmtNode* op, InplaceMode 
inplace_mode) final {
-    if (op->op.same_as(tirx::launch_thread_op()) &&
-        
std::string(op->args[0].as_or_throw<StringImm>()->value).rfind("vthread", 0) != 
0) {
-      auto it = tmap_.find(op->args[0].as_or_throw<StringImm>()->value);
-      if (it != tmap_.end()) {
-        PrimExpr old_extent = op->args[1].as_or_throw<PrimExpr>();
-        PrimExpr extent = Mutate(old_extent, 
inplace_mode).ValueOrUnchanged(old_extent);
-        PrimVar old_var = op->body_params[0].as_or_throw<PrimVar>();
-        PrimVar new_var(it->second, extent.ty());
-        ffi::Any previous_remap = VarRemapGet(old_var);
-        VarRemapSet(old_var, new_var);
-        Stmt body = Mutate(op->body, inplace_mode).ValueOrUnchanged(op->body);
-        VarRemapSet(old_var, previous_remap);
-        return RegionStmt(tirx::launch_thread_op(), {StringImm(it->second), 
extent}, {new_var},
-                          DictAttrs(), body, {}, op->span);
-      }
-    }
-    return StmtExprMutator::Mutate_(op, inplace_mode);
-  }
-
-  // The thread map
-  const std::unordered_map<std::string, ffi::String>& tmap_;
-};
-
-Function RemapThreadAxis(Function func, ffi::Map<ffi::String, ffi::String> 
thread_map) {
-  std::unordered_map<std::string, ffi::String> tmap;
-  for (const auto& kv : thread_map) {
-    tmap[kv.first] = kv.second;
-  }
-
-  if (auto opt = 
func->GetAttr<ffi::Array<ffi::String>>(tirx::attr::kKernelLaunchParams)) {
-    TVM_FFI_ICHECK(opt != nullptr) << "Require attribute " << 
tirx::attr::kKernelLaunchParams;
-    auto launch_params = opt.value();
-    // replace the thread axis attribute
-    for (size_t i = 0; i < launch_params.size(); ++i) {
-      auto it = tmap.find(launch_params[i]);
-      if (it != tmap.end()) {
-        launch_params.Set(i, it->second);
-      }
-    }
-
-    func = WithAttr(std::move(func), tirx::attr::kKernelLaunchParams, 
launch_params);
-  }
-
-  if (!func->body.has_value()) return func;
-  auto* n = func.CopyOnWrite();
-  n->body = 
ffi::make_object<ThreadAxisRewriter>(tmap)->Rewrite(std::move(n->body).value());
-  return func;
-}
-
-namespace transform {
-
-Pass RemapThreadAxis(ffi::Map<ffi::String, ffi::String> thread_map) {
-  auto pass_func = [thread_map](Function f, IRModule m, PassContext ctx) {
-    return RemapThreadAxis(std::move(f), thread_map);
-  };
-  return CreateFunctionPass(pass_func, 0, "tirx.RemapThreadAxis");
-}
-
-TVM_FFI_STATIC_INIT_BLOCK() {
-  namespace refl = tvm::ffi::reflection;
-  refl::GlobalDef().def("tirx.transform.RemapThreadAxis", RemapThreadAxis);
-}
-
-}  // namespace transform
-}  // namespace tirx
-}  // namespace tvm
diff --git a/src/tirx/transform/tile_primitive_dispatch.cc 
b/src/tirx/transform/tile_dispatch.cc
similarity index 99%
rename from src/tirx/transform/tile_primitive_dispatch.cc
rename to src/tirx/transform/tile_dispatch.cc
index 75db630df4..ac470c7da9 100644
--- a/src/tirx/transform/tile_primitive_dispatch.cc
+++ b/src/tirx/transform/tile_dispatch.cc
@@ -18,7 +18,7 @@
  */
 
 /*!
- * \file tile_primitive_dispatch.cc
+ * \file tile_dispatch.cc
  * \brief Lower tensor instruction Evaluate(Call) nodes (also resolves 
ScopeIdDef
  * declarations and emits launch params).
  */
@@ -214,14 +214,14 @@ class NoOpCallVerifier : public 
Verifier<NoOpCallVerifier> {
   }
 };
 
-class TilePrimitiveDispatcher : public StmtExprMutator {
+class TileDispatcher : public StmtExprMutator {
  public:
   using StmtExprMutator::Mutate;
   using StmtExprMutator::Mutate_;
-  explicit TilePrimitiveDispatcher(const Target& target) : target_(target) {}
+  explicit TileDispatcher(const Target& target) : target_(target) {}
 
   static Stmt LowerOpCalls(const Stmt& stmt, const Target& target) {
-    return ffi::make_object<TilePrimitiveDispatcher>(target)
+    return ffi::make_object<TileDispatcher>(target)
         ->Mutate(stmt, InplaceMode::kAllow)
         .ValueOrUnchanged(stmt);
   }
@@ -1546,18 +1546,18 @@ Target ResolveTarget(const Function& f) {
 
 namespace transform {
 
-Pass TilePrimitiveDispatch() {
+Pass TileDispatch() {
   auto pass_func = [](Function f, IRModule m, PassContext ctx) {
     if (!f->body.has_value()) return f;
     Target target = ResolveTarget(f);
     auto* n = f.CopyOnWrite();
-    n->body = TilePrimitiveDispatcher::LowerOpCalls(n->body.value(), target);
+    n->body = TileDispatcher::LowerOpCalls(n->body.value(), target);
     if (!NoOpCallVerifier::Verify(n->body.value(), false)) {
       LOG(FATAL) << "Failed to lower the TIRx program: " << f;
     }
     return f;
   };
-  return CreateFunctionPass(pass_func, 0, "tirx.TilePrimitiveDispatch");
+  return CreateFunctionPass(pass_func, 0, "tirx.TileDispatch");
 }
 
 }  // namespace transform
diff --git a/tests/python/tirx-transform/test_tir_inline_private_functions.py 
b/tests/python/tirx-transform/test_tir_inline_private_functions.py
deleted file mode 100644
index d87fcc1c7f..0000000000
--- a/tests/python/tirx-transform/test_tir_inline_private_functions.py
+++ /dev/null
@@ -1,251 +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.
-# ruff: noqa: F821
-
-import pytest
-
-import tvm.testing
-from tvm.script import ir as I
-from tvm.script import tirx as T
-
-
-class BaseTestCase:
-    def test_well_formed(self):
-        After = tvm.tirx.transform.InlinePrivateFunctions()(self.Before)
-        tvm.tirx.analysis.verify_well_formed(After)
-
-    def test_produces_expected(self):
-        After = tvm.tirx.transform.InlinePrivateFunctions()(self.Before)
-        tvm.ir.assert_structural_equal(self.Expected, After)
-
-
-class TestSimple(BaseTestCase):
-    """Simple case directly acting on Function"""
-
-    @I.ir_module
-    class Before:
-        @T.function
-        def main(A: T.Tensor([80, 16], "float32"), B: T.Tensor([64, 16], 
"float32")):
-            for i in range(64):
-                Before.subroutine(T.address_of(A[i, 0]), T.address_of(B[i, 0]))
-
-        @T.function(private=True)
-        def subroutine(A_data: T.handle("float32"), B_data: 
T.handle("float32")):
-            A = T.decl_tensor([16, 16], "float32", data=A_data)
-            B = T.decl_tensor([16], "float32", data=B_data)
-            for i in range(16):
-                B[i] = 0.0
-                for j in range(16):
-                    B[i] = B[i] + A[i, j]
-
-    @I.ir_module
-    class Expected:
-        @T.function
-        def main(A: T.Tensor([80, 16], "float32"), B: T.Tensor([64, 16], 
"float32")):
-            for i in range(64):
-                Aview = T.decl_tensor([16, 16], "float32", 
data=T.address_of(A[i, 0]))
-                Bview = T.decl_tensor([16], "float32", data=T.address_of(B[i, 
0]))
-                for j in range(16):
-                    Bview[j] = 0.0
-                    for k in range(16):
-                        Bview[j] = Bview[j] + Aview[j, k]
-
-
-class TestRetainCrossFunctionSubroutines(BaseTestCase):
-    """Do not inline functions that cross device boundaries
-
-    When lowering TIR, calls for which the callsite and callee have
-    different targets are used at some stages, before being further
-    lowered to explicit device kernel launches.  Since inlining the
-    function would remove this cross-device information,
-    InlinePrivateSubroutines should not inline these cases.
-    """
-
-    @I.ir_module
-    class Before:
-        @T.function
-        def main(A: T.Tensor([80, 16], "float32"), B: T.Tensor([64, 16], 
"float32")):
-            T.func_attr({"target": T.target("llvm")})
-            for i in range(64):
-                Before.subroutine(T.address_of(A[i, 0]), T.address_of(B[i, 0]))
-
-        @T.function(private=True)
-        def subroutine(A_data: T.handle("float32"), B_data: 
T.handle("float32")):
-            T.func_attr({"target": T.target({"kind": "cuda", "arch": 
"sm_80"})})
-            A = T.decl_tensor([16, 16], "float32", data=A_data)
-            B = T.decl_tensor([16], "float32", data=B_data)
-            for i in range(16):
-                B[i] = 0.0
-                for j in range(16):
-                    B[i] = B[i] + A[i, j]
-
-    Expected = Before
-
-
-class TestRetainRecursiveSubroutines(BaseTestCase):
-    """Do not inline recursive functions
-
-    To avoid potentially infinite loops at compile-time, disable
-    inlining of recursive functions.  If inlining of these functions
-    would be useful, this restriction may be relaxed with improved
-    analysis of the subroutine.
-    """
-
-    @I.ir_module
-    class Before:
-        @T.function
-        def main(A: T.Tensor(16, "float32")):
-            Before.subroutine(T.address_of(A[0]), 16)
-
-        @T.function(private=True)
-        def subroutine(A_data: T.handle("float32"), A_size: T.int32):
-            A = T.decl_tensor(A_size, "float32", data=A_data)
-            A[1] = A[0] + A[1]
-
-            if A_size > 1:
-                Before.subroutine(T.address_of(A[1]), A_size - 1)
-
-    Expected = Before
-
-
-class TestDeduplicateBlockName(BaseTestCase):
-    """Block names must be de-duplicated after inlining"""
-
-    @pytest.mark.xfail(reason="Inlining of schedulable TIR not yet supported")
-    def test_produces_expected(self):
-        super().test_produces_expected(self)
-
-    @I.ir_module
-    class Before:
-        @T.function
-        def main(A: T.Tensor([2, 16], "float32"), B: T.Tensor([2, 16], 
"float32")):
-            Before.subroutine(T.address_of(A[0, 0]), T.address_of(B[0, 0]))
-            Before.subroutine(T.address_of(A[1, 0]), T.address_of(B[1, 0]))
-
-        @T.function(private=True)
-        def subroutine(A_data: T.handle("float32"), B_data: 
T.handle("float32")):
-            A = T.decl_tensor(16, "float32", data=A_data)
-            B = T.decl_tensor(16, "float32", data=B_data)
-            for i in range(16):
-                B[i] = A[i] * 2.0
-
-    @I.ir_module
-    class Expected:
-        @T.function
-        def main(A: T.Tensor([80, 16], "float32"), B: T.Tensor([64, 16], 
"float32")):
-            A_data_1 = T.bind(T.address_of(A[0, 0]), T.handle("float32"))
-            A_1 = T.decl_tensor(16, "float32", data=A_data_1)
-            B_data_1: T.let[T.handle("float32")] = T.address_of(B[0, 0])
-            B_1 = T.decl_tensor(16, "float32", data=B_data_1)
-            for i in range(16):
-                B_1[i] = A_1[i] * 2.0
-
-            A_data_2 = T.bind(T.address_of(A[1, 0]), T.handle("float32"))
-            A_2 = T.decl_tensor(16, "float32", data=A_data_2)
-            B_data_2: T.let[T.handle("float32")] = T.address_of(B[1, 0])
-            B_2 = T.decl_tensor(16, "float32", data=B_data_2)
-            for i in range(16):
-                B_2[i] = A_2[i] * 2.0
-
-
-class TestInlineCallOccurringInExpression(BaseTestCase):
-    """Inline a Call node that is used in a function
-
-    The current implementation only replaces `ir.Call` instances that
-    occur in a `tvm.ir.Evaluate` context.  This is the primary use case,
-    used in destination-passing style.
-
-    This unit test is marked as xfail.  If/when the implementation
-    supports inlining of function calls occurring as part of an
-    expression, the annotation can be removed.
-    """
-
-    @pytest.mark.xfail(
-        reason="Inlining of Functions outside of tvm.ir.Evaluate is not yet 
supported"
-    )
-    def test_produces_expected(self):
-        super().test_produces_expected(self)
-
-    @I.ir_module
-    class Before:
-        @T.function
-        def main(A: T.Tensor(16, "float32")):
-            for i in range(16):
-                A[i] = Before.subroutine(i)
-
-        @T.function(private=True)
-        def subroutine(i: T.int32) -> T.float32:
-            cos = T.cos(T.cast(i, "float32"))
-            sin = T.sin(T.cast(i, "float32"))
-            retval = cos * cos + sin * sin
-            return retval
-
-    @I.ir_module
-    class Expected:
-        @T.function
-        def main(A: T.Tensor(16, "float32")):
-            for i in range(16):
-                cos = T.cos(T.cast(i, "float32"))
-                sin = T.sin(T.cast(i, "float32"))
-                retval = cos * cos + sin * sin
-                A[i] = retval
-
-
-class TestInlineFunctionWithBufferArguments(BaseTestCase):
-    """Inline a function that accepts buffer arguments
-
-    The current implementation does not support this usage.  This unit
-    test is provided to display a possible user interaction, and is
-    marked with `@pytest.mark.xfail`.  If/when the implementation
-    supports inlining of function calls with buffer arguments, the
-    annotation can be removed.
-    """
-
-    @pytest.mark.xfail(reason="Inlining of Functions with buffer arguments")
-    def test_produces_expected(self):
-        super().test_produces_expected(self)
-
-    @I.ir_module
-    class Before:
-        @T.function
-        def main(A: T.Tensor(16, "float32")):
-            Before.subroutine(
-                T.stack_make_dltensor(
-                    A.data,
-                    T.stack_make_shape(*A.ty.shape),
-                    0,
-                    len(A.ty.shape),
-                    0.0,
-                    A.ty.elem_offset,
-                )
-            )
-
-        @T.function(private=True)
-        def subroutine(A: T.Tensor(16, "float32")):
-            for i in range(16):
-                A[i] = A[i] * 2.0
-
-    @I.ir_module
-    class Expected:
-        @T.function
-        def main(A: T.Tensor(16, "float32")):
-            for i in range(16):
-                A[i] = A[i] * 2.0
-
-
-if __name__ == "__main__":
-    tvm.testing.main()
diff --git a/tests/python/tirx/operator/tile_primitive/cuda/copy/test_reg.py 
b/tests/python/tirx/operator/tile_primitive/cuda/copy/test_reg.py
index b2253269f9..8ebe0fed1a 100644
--- a/tests/python/tirx/operator/tile_primitive/cuda/copy/test_reg.py
+++ b/tests/python/tirx/operator/tile_primitive/cuda/copy/test_reg.py
@@ -462,7 +462,7 @@ def test_reg_copy_linear_shared_hoists_thread_base():
     @tvm.transform.pass_instrument
     class CaptureDispatch:
         def run_after_pass(self, mod, info):
-            if info.name == "tirx.TilePrimitiveDispatch":
+            if info.name == "tirx.TileDispatch":
                 dispatched.append(mod["main"])
 
     target = tvm.target.Target("cuda")

Reply via email to