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 3d3343e1da [REFACTOR][TIRx] Remove obsolete AttrStmt infrastructure
(#20573)
3d3343e1da is described below
commit 3d3343e1daa63ef47025893151574dc133a5d115
Author: Tianqi Chen <[email protected]>
AuthorDate: Tue Oct 6 15:23:11 2026 -0400
[REFACTOR][TIRx] Remove obsolete AttrStmt infrastructure (#20573)
Remove the generic `AttrStmt` node and `T.attr` construction API now
that scoped operations use `RegionStmt`. Retire the corresponding
printer, FFI, visitor, pass, and backend infrastructure.
Opaque lowering preserves loop annotations directly, including CUDA
unroll hints and inherited automatic-unroll policies, without converting
generic `pragma_*` keys into statement wrappers.
---
include/tvm/s_tir/stmt.h | 2 +-
include/tvm/tirx/script/ir_builder/frame.h | 50 ----------
include/tvm/tirx/script/ir_builder/ir.h | 9 --
include/tvm/tirx/stmt.h | 59 ------------
include/tvm/tirx/stmt_functor.h | 6 --
python/tvm/tirx/__init__.py | 2 +-
python/tvm/tirx/script/ir_builder/frame.py | 4 -
.../tvm/tirx/script/ir_builder/parser_protocol.py | 53 +---------
python/tvm/tirx/stmt.py | 41 --------
src/backend/cuda/transforms/lower_iket.cc | 7 --
src/backend/trn/codegen/codegen_trn.cc | 6 --
src/backend/trn/codegen/codegen_trn.h | 1 -
src/backend/vulkan/codegen/codegen_spirv.cc | 6 --
src/backend/vulkan/codegen/codegen_spirv.h | 1 -
src/s_tir/analysis/calculate_allocated_memory.cc | 6 --
src/s_tir/analysis/estimate_flops.cc | 5 -
.../feature_extractor/per_store_feature.cc | 14 ---
src/s_tir/transform/hoist_expression.cc | 35 -------
src/s_tir/transform/inject_virtual_thread.cc | 18 ----
src/s_tir/transform/lower_opaque_block.cc | 100 +++----------------
src/s_tir/transform/lower_thread_binding.cc | 14 ---
src/script/printer/script_printer.cc | 1 -
src/target/llvm/codegen_cpu.cc | 21 ----
src/target/llvm/codegen_cpu.h | 1 -
src/target/llvm/codegen_llvm.cc | 7 --
src/target/llvm/codegen_llvm.h | 1 -
src/target/source/codegen_c.cc | 6 --
src/target/source/codegen_c.h | 1 -
src/tirx/analysis/verify_tirx_well_formed.cc | 3 -
src/tirx/analysis/verify_well_formed.h | 22 +----
src/tirx/ir/ir_mutator_with_analyzer.cc | 5 -
src/tirx/ir/ir_mutator_with_analyzer.h | 1 -
src/tirx/ir/ir_visitor_with_analyzer.cc | 4 -
src/tirx/ir/ir_visitor_with_analyzer.h | 1 -
src/tirx/ir/stmt.cc | 82 ----------------
src/tirx/ir/stmt_functor.cc | 41 --------
src/tirx/ir/tir_visitor_with_path.cc | 8 --
src/tirx/ir/tir_visitor_with_path.h | 1 -
src/tirx/script/ir_builder/frame.cc | 6 --
src/tirx/script/ir_builder/ir.cc | 10 +-
src/tirx/script/printer/stmt.cc | 59 ------------
src/tirx/transform/common_subexpr_elim.cc | 18 +---
src/tirx/transform/ir_utils.cc | 86 -----------------
src/tirx/transform/ir_utils.h | 2 -
src/tirx/transform/lower_thread_allreduce.h | 2 +-
src/tirx/transform/lower_tirx_opaque.cc | 107 +++------------------
src/tirx/transform/lower_tvm_builtin.cc | 16 +--
src/tirx/transform/remove_no_op.cc | 5 -
src/tirx/transform/storage_rewrite.cc | 42 +-------
src/tirx/transform/tvm_ffi_binder.h | 6 +-
src/tirx/transform/unsupported_dtype_legalize.cc | 25 -----
.../transform/test_s_tir_transform_hoist_if.py | 4 +-
.../test_s_tir_transform_lower_opaque_block.py | 38 --------
tests/python/tirx-base/test_tir_constructor.py | 10 --
tests/python/tirx-base/test_tir_nodes.py | 5 -
.../test_tir_transform_convert_ssa.py | 50 ----------
.../test_tir_transform_split_host_device.py | 2 +-
.../python/tirx/script/test_tirx_script_printer.py | 14 ---
58 files changed, 45 insertions(+), 1107 deletions(-)
diff --git a/include/tvm/s_tir/stmt.h b/include/tvm/s_tir/stmt.h
index 8f45f5dc22..3f94232416 100644
--- a/include/tvm/s_tir/stmt.h
+++ b/include/tvm/s_tir/stmt.h
@@ -91,7 +91,7 @@ class MatchBufferRegion : public ffi::ObjectRef {
* T.where(predicate)
* buffer2 = T.alloc_tensor(shape, dtype)
* buffer3 = Ts.match_buffer(source_buffer[start:end, ...])
- * T.attr({attr_key: attr_value, ...})
+ * Ts.sblock_attr({attr_key: attr_value, ...})
* with T.init():
* // init body
* // body
diff --git a/include/tvm/tirx/script/ir_builder/frame.h
b/include/tvm/tirx/script/ir_builder/frame.h
index 28327c515a..a1621d1cb7 100644
--- a/include/tvm/tirx/script/ir_builder/frame.h
+++ b/include/tvm/tirx/script/ir_builder/frame.h
@@ -289,56 +289,6 @@ class RegionFrame : public TIRFrame {
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(RegionFrame, TIRFrame,
RegionFrameNode);
};
-/*!
- * \brief A frame that represents attribute node.
- *
- * \sa AttrFrame
- */
-class AttrFrameNode : public TIRFrameNode {
- public:
- explicit AttrFrameNode(ffi::UnsafeInit tag) : value(tag) {}
-
- explicit AttrFrameNode(Expr value) : value(std::move(value)) {}
-
- /*! \brief The node to annotate the attribute. */
- Any node;
- /*! \brief Attribute type key. */
- ffi::String attr_key;
- /*! \brief The value of the attribute. */
- Expr value;
-
- static void RegisterReflection() {
- namespace refl = tvm::ffi::reflection;
- refl::ObjectDef<AttrFrameNode>()
- .def_ro("node", &AttrFrameNode::node)
- .def_ro("attr_key", &AttrFrameNode::attr_key)
- .def_ro("value", &AttrFrameNode::value);
- }
- TVM_FFI_DECLARE_OBJECT_INFO_FINAL("script.ir_builder.tirx.AttrFrame",
AttrFrameNode,
- TIRFrameNode);
-
- public:
- /*!
- * \brief The method called when exiting RAII scope.
- * \sa tvm::support::With
- */
- void ExitWithScope() final;
-};
-
-/*!
- * \brief Managed reference to AttrFrameNode.
- *
- * \sa AttrFrameNode
- */
-class AttrFrame : public TIRFrame {
- public:
- explicit AttrFrame(ffi::ObjectPtr<AttrFrameNode> data) :
TIRFrame(ffi::UnsafeInit{}) {
- TVM_FFI_ICHECK(data != nullptr);
- data_ = std::move(data);
- }
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(AttrFrame, TIRFrame,
AttrFrameNode);
-};
-
/*!
* \brief A frame that represents while loop.
*
diff --git a/include/tvm/tirx/script/ir_builder/ir.h
b/include/tvm/tirx/script/ir_builder/ir.h
index 07122fb5dd..2c35dcfda0 100644
--- a/include/tvm/tirx/script/ir_builder/ir.h
+++ b/include/tvm/tirx/script/ir_builder/ir.h
@@ -238,15 +238,6 @@ AssertFrame Assert(PrimExpr condition, ffi::String
error_kind,
Var Bind(Expr value, ffi::Optional<Type> type_annotation = std::nullopt,
ffi::Optional<Var> var = std::nullopt);
-/*!
- * \brief Create an attribute.
- * \param node The node to annotate the attribute.
- * \param attr_key Attribute type key.
- * \param value The value of the attribute.
- * \return The result AttrFrame.
- */
-AttrFrame Attr(ffi::Any node, ffi::String attr_key, Expr value);
-
/*!
* \brief Create a while loop.
* \param condition The termination condition of the loop.
diff --git a/include/tvm/tirx/stmt.h b/include/tvm/tirx/stmt.h
index 48fbb8620b..5b414cef47 100644
--- a/include/tvm/tirx/stmt.h
+++ b/include/tvm/tirx/stmt.h
@@ -115,56 +115,6 @@ class Bind : public Stmt {
TVM_DEFINE_OBJECT_REF_COW_METHOD(BindNode);
};
-/*!
- * \brief Define certain auxiliary attribute for the body to be a symbolic
value.
- * This provide auxiliary information for IR passes that transforms body.
- *
- * In terms of effect, this is equivalent to Block(Evaluate(value), body).
- *
- * Examples of possible usage:
- * - Bound of function, variables.
- * - Hint which block corresponds to a parallel region.
- */
-class AttrStmtNode : public StmtNode {
- public:
- explicit AttrStmtNode(ffi::UnsafeInit tag) : value(tag), body(tag) {}
-
- AttrStmtNode(Expr value, Stmt body) : value(std::move(value)),
body(std::move(body)) {}
-
- /*! \brief this is attribute about certain node */
- ffi::Any node;
- /*! \brief the type key of the attribute */
- ffi::String attr_key;
- /*! \brief The attribute value, value is well defined at current scope. */
- Expr value;
- /*! \brief The body statement to be executed */
- Stmt body;
-
- static void RegisterReflection() {
- namespace refl = tvm::ffi::reflection;
- refl::ObjectDef<AttrStmtNode>()
- .def_ro("node", &AttrStmtNode::node)
- .def_ro("attr_key", &AttrStmtNode::attr_key)
- .def_ro("value", &AttrStmtNode::value)
- .def_ro("body", &AttrStmtNode::body);
- }
- TVM_FFI_DECLARE_OBJECT_INFO_FINAL("tirx.AttrStmt", AttrStmtNode, StmtNode);
-};
-
-/*!
- * \brief Managed reference to AttrStmtNode.
- * \sa AttrStmtNode
- */
-class AttrStmt : public Stmt {
- public:
- TVM_DLL AttrStmt(ffi::Any node, ffi::String attr_key, Expr value, Stmt body,
Span span = Span());
-
- explicit AttrStmt(ffi::ObjectPtr<AttrStmtNode> node) : Stmt(std::move(node))
{}
-
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(AttrStmt, Stmt, AttrStmtNode);
- TVM_DEFINE_OBJECT_REF_COW_METHOD(AttrStmtNode);
-};
-
/*!
* \brief A single-body statement whose semantics are defined by an operator.
* Operands are evaluated in the enclosing scope. Body parameters are
definitions
@@ -876,15 +826,6 @@ constexpr const char* buffer_allocated_addr =
"buffer_allocated_addr";
*/
constexpr const char* kPersistentKernel = "tirx.persistent_kernel";
-/*!
- * \brief Check if attr_key is a pragma key extension
- * \param attr_key The attr key to be compared
- * \return true if it is a pragma key
- */
-inline bool IsPragmaKey(const std::string& attr_key) {
- return attr_key.compare(0, 7, "pragma_") == 0;
-}
-
} // namespace attr
/*!
* \brief Create a type annotation expression
diff --git a/include/tvm/tirx/stmt_functor.h b/include/tvm/tirx/stmt_functor.h
index b0268f8b8c..6762f53769 100644
--- a/include/tvm/tirx/stmt_functor.h
+++ b/include/tvm/tirx/stmt_functor.h
@@ -80,9 +80,6 @@ class StmtFunctor<R(const Stmt&, Args...)> {
virtual R Dispatch_(const RegionStmtNode* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
- virtual R Dispatch_(const AttrStmtNode* node, Args... args) {
- return DispatchDefault_(node, std::forward<Args>(args)...);
- }
virtual R Dispatch_(const IfThenElseNode* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
@@ -137,7 +134,6 @@ class StmtFunctor<R(const Stmt&, Args...)> {
return self->DispatchDefault_(node.get(),
std::forward<Args>(args)...);
});
SetDispatch<TSelf, BindNode>(vtable);
- SetDispatch<TSelf, AttrStmtNode>(vtable);
SetDispatch<TSelf, RegionStmtNode>(vtable);
SetDispatch<TSelf, IfThenElseNode>(vtable);
SetDispatch<TSelf, ForNode>(vtable);
@@ -195,7 +191,6 @@ class TVM_DLL StmtExprVisitor : public tvm::ExprVisitor {
using tvm::ExprVisitor::Visit_;
virtual ffi::Optional<VisitInterrupt> Visit_(const BindNode* op);
- virtual ffi::Optional<VisitInterrupt> Visit_(const AttrStmtNode* op);
virtual ffi::Optional<VisitInterrupt> Visit_(const RegionStmtNode* op);
virtual ffi::Optional<VisitInterrupt> Visit_(const IfThenElseNode* op);
virtual ffi::Optional<VisitInterrupt> Visit_(const ForNode* op);
@@ -264,7 +259,6 @@ class TVM_DLL StmtExprMutator : public tvm::ExprMutator {
}
virtual UnchangedOr<Stmt> Mutate_(const BindNode* op, InplaceMode
inplace_mode);
- virtual UnchangedOr<Stmt> Mutate_(const AttrStmtNode* op, InplaceMode
inplace_mode);
virtual UnchangedOr<Stmt> Mutate_(const RegionStmtNode* op, InplaceMode
inplace_mode);
virtual UnchangedOr<Stmt> Mutate_(const IfThenElseNode* op, InplaceMode
inplace_mode);
virtual UnchangedOr<Stmt> Mutate_(const ForNode* op, InplaceMode
inplace_mode);
diff --git a/python/tvm/tirx/__init__.py b/python/tvm/tirx/__init__.py
index 60da49ed28..fbae790743 100644
--- a/python/tvm/tirx/__init__.py
+++ b/python/tvm/tirx/__init__.py
@@ -48,7 +48,7 @@ from .stmt import Stmt, Bind, AssertStmt, ForKind, For,
While, Return, Break, Co
# Legacy alias: LetStmt was folded into the body-less Bind statement.
LetStmt = Bind
-from .stmt import BufferStore, AttrStmt, RegionStmt
+from .stmt import BufferStore, RegionStmt
from .stmt import SeqStmt
from .stmt import IfThenElse, Evaluate, stmt_seq, stmt_list
diff --git a/python/tvm/tirx/script/ir_builder/frame.py
b/python/tvm/tirx/script/ir_builder/frame.py
index cf1065c8de..9ddb9a4d46 100644
--- a/python/tvm/tirx/script/ir_builder/frame.py
+++ b/python/tvm/tirx/script/ir_builder/frame.py
@@ -68,10 +68,6 @@ class ForFrame(TIRFrame):
class AssertFrame(TIRFrame): ...
-@_register_object("script.ir_builder.tirx.AttrFrame")
-class AttrFrame(TIRFrame): ...
-
-
@_register_object("script.ir_builder.tirx.WhileFrame")
class WhileFrame(TIRFrame): ...
diff --git a/python/tvm/tirx/script/ir_builder/parser_protocol.py
b/python/tvm/tirx/script/ir_builder/parser_protocol.py
index 34eb8b90e3..a61379f4bc 100644
--- a/python/tvm/tirx/script/ir_builder/parser_protocol.py
+++ b/python/tvm/tirx/script/ir_builder/parser_protocol.py
@@ -35,7 +35,6 @@ from tvm import ir as _ir
from tvm import tirx as _tir
from tvm.ir import StringImm as _StringImm
from tvm.ir import TensorRegion, Type, is_prim_expr
-from tvm.runtime import convert
from tvm.script.ir_builder import base as _base
from tvm.script.ir_builder.base import AlreadyEmitted
from tvm.script.ir_builder.base import IRBuilder as _IRBuilder
@@ -44,7 +43,7 @@ from tvm.tirx.expr import (
IntImm,
)
-from . import _ffi_api, frame, utils
+from . import _ffi_api, frame
from . import ir as _native
from . import op as _op
from .op import and_ as and_
@@ -438,55 +437,6 @@ def bind( # pylint: disable=invalid-name
return _ffi_api.Bind(value, type_annotation, var) # type:
ignore[attr-defined] # pylint: disable=no-member
-def attr(
- node_or_dict: Any, attr_key: str | None = None, value: Expr | str | None =
None
-) -> frame.AttrFrame | utils._FrameScope:
- """Create an attribute node, or multiple attribute nodes from a dict.
-
- Usage 1 — single attr::
-
- with T.attr(node, key, value):
- ...
-
- Usage 2 — dict sugar (node defaults to ``0``)::
-
- with T.attr({"key1": value1, "key2": value2}):
- ...
-
- Parameters
- ----------
- node_or_dict : Any
- If a dict, each key-value pair becomes an AttrStmt with
- ``node=0``. Otherwise the node to annotate.
-
- attr_key : str, optional
- Attribute type key (required when ``node_or_dict`` is not a dict).
-
- value : Union[Expr, str], optional
- The attribute value (required when ``node_or_dict`` is not a dict).
-
- Returns
- -------
- res : Union[frame.AttrFrame, _FrameScope]
- A single AttrFrame, or a _FrameScope wrapping multiple AttrFrames.
- """
- if isinstance(node_or_dict, dict):
- frames = []
- for k, v in node_or_dict.items():
- if isinstance(v, bool):
- v = IntImm("bool", v)
- frames.append(_ffi_api.Attr(0, k, convert(v))) # type:
ignore[attr-defined]
- if len(frames) == 1:
- return frames[0]
- return utils._FrameScope(frames)
- else:
- if attr_key is None or value is None:
- raise ValueError("T.attr(node, attr_key, value) requires all three
arguments")
- node_or_dict = convert(node_or_dict)
- value = convert(value)
- return _ffi_api.Attr(node_or_dict, attr_key, value) # type:
ignore[attr-defined] # pylint: disable=no-member
-
-
def buffer_store(
buffer: Var, # pylint: disable=redefined-outer-name
value: Expr,
@@ -1028,7 +978,6 @@ __all__ = [
"and_",
"arg_",
"assert_",
- "attr",
"bind",
"bind_",
"break_",
diff --git a/python/tvm/tirx/stmt.py b/python/tvm/tirx/stmt.py
index e91695c811..8c16ca078b 100644
--- a/python/tvm/tirx/stmt.py
+++ b/python/tvm/tirx/stmt.py
@@ -319,47 +319,6 @@ class RegionStmt(Stmt):
)
-@tvm_ffi.register_object("tirx.AttrStmt")
-class AttrStmt(Stmt):
- """AttrStmt node.
-
- Parameters
- ----------
- node : Any
- The node to annotate the attribute
-
- attr_key : str
- Attribute type key.
-
- value : Expr
- The value of the attribute
-
- body : Stmt
- The body statement.
-
- span : Optional[Span]
- The location of the stmt in the source code.
- """
-
- node: Any
- attr_key: str
- value: Expr
- body: Stmt
- span: Span | None
-
- def __init__(
- self, node: Any, attr_key: str, value: Expr, body: Stmt, span: Span |
None = None
- ) -> None:
- self.__init_handle_by_constructor__(
- _ffi_api.AttrStmt,
- node,
- attr_key,
- value,
- body,
- span, # type: ignore
- )
-
-
@tvm_ffi.register_object("tirx.SeqStmt")
class SeqStmt(Stmt):
"""Sequence of statements.
diff --git a/src/backend/cuda/transforms/lower_iket.cc
b/src/backend/cuda/transforms/lower_iket.cc
index 64138c9f8e..136b6e2664 100644
--- a/src/backend/cuda/transforms/lower_iket.cc
+++ b/src/backend/cuda/transforms/lower_iket.cc
@@ -638,13 +638,6 @@ class RemoveStrippedIketNoOps : public StmtExprMutator {
return SideEffect(condition) > CallEffectKind::kReadState ?
Evaluate(condition) : Evaluate(0);
}
- UnchangedOr<Stmt> Mutate_(const AttrStmtNode* attr_stmt, InplaceMode
inplace_mode) final {
- auto result = StmtExprMutator::Mutate_(attr_stmt, inplace_mode);
- if (!result.IsUnchanged()) attr_stmt =
ffi::AnyView(result).as<AttrStmtNode>();
- if (IsEvaluateZero(attr_stmt->body)) return attr_stmt->body;
- return result;
- }
-
UnchangedOr<Stmt> Mutate_(const ForNode* loop, InplaceMode inplace_mode)
final {
auto result = StmtExprMutator::Mutate_(loop, inplace_mode);
if (!result.IsUnchanged()) loop = ffi::AnyView(result).as<ForNode>();
diff --git a/src/backend/trn/codegen/codegen_trn.cc
b/src/backend/trn/codegen/codegen_trn.cc
index 6d611a0700..e1bc98c4af 100644
--- a/src/backend/trn/codegen/codegen_trn.cc
+++ b/src/backend/trn/codegen/codegen_trn.cc
@@ -277,12 +277,6 @@ void CodeGenTrainium::DispatchAllocTensor(const BindNode*
op, const CallNode* bu
}
}
-void CodeGenTrainium::Dispatch_(const AttrStmtNode* op) {
- TVM_FFI_CHECK(op->attr_key != "thread_extent" && op->attr_key !=
"virtual_thread", ValueError)
- << "Launch attributes are retired; use tirx.launch_thread RegionStmt";
- this->PrintStmt(op->body);
-}
-
void CodeGenTrainium::Dispatch_(const RegionStmtNode* op) {
static const Op tensorized_instruction =
Op::Get("tirx.nki.tensorized_instruction");
if (op->op.same_as(tensorized_instruction)) {
diff --git a/src/backend/trn/codegen/codegen_trn.h
b/src/backend/trn/codegen/codegen_trn.h
index 5f1d16441f..45a1f04ce4 100644
--- a/src/backend/trn/codegen/codegen_trn.h
+++ b/src/backend/trn/codegen/codegen_trn.h
@@ -60,7 +60,6 @@ class CodeGenTrainium final : public CodeGenC {
void PrintType(const PrimType& t, std::ostream& os) final; // NOLINT(*)
void Dispatch_(const BindNode* op) final;
void DispatchAllocTensor(const BindNode* op, const CallNode* buffer_call);
- void Dispatch_(const AttrStmtNode* op) final; //
NOLINT(*)
void Dispatch_(const RegionStmtNode* op) final; //
NOLINT(*)
void Dispatch_(const ForNode* op) final; //
NOLINT(*)
void Dispatch_(const BufferStoreNode* op) final; //
NOLINT(*)=
diff --git a/src/backend/vulkan/codegen/codegen_spirv.cc
b/src/backend/vulkan/codegen/codegen_spirv.cc
index 1ec8d0498b..c9f6d1f5b5 100644
--- a/src/backend/vulkan/codegen/codegen_spirv.cc
+++ b/src/backend/vulkan/codegen/codegen_spirv.cc
@@ -1006,12 +1006,6 @@ void CodeGenSPIRV::Dispatch_(const RegionStmtNode* op) {
}
}
-void CodeGenSPIRV::Dispatch_(const AttrStmtNode* op) {
- TVM_FFI_CHECK(op->attr_key != "thread_extent" && op->attr_key !=
"virtual_thread", ValueError)
- << "Launch attributes are retired; use tirx.launch_thread RegionStmt";
- this->Dispatch(op->body);
-}
-
void CodeGenSPIRV::Dispatch_(const AssertStmtNode* op) {
// AssertStmt is a leaf — no body to visit.
}
diff --git a/src/backend/vulkan/codegen/codegen_spirv.h
b/src/backend/vulkan/codegen/codegen_spirv.h
index b7732f88c0..867fac6d5c 100644
--- a/src/backend/vulkan/codegen/codegen_spirv.h
+++ b/src/backend/vulkan/codegen/codegen_spirv.h
@@ -121,7 +121,6 @@ class CodeGenSPIRV : public
tirx::ExprFunctor<spirv::Value(const Expr&)>,
void DispatchDeclTensor(const BindNode* op, const CallNode* buffer_call);
void DispatchAllocTensor(const BindNode* op, const CallNode* buffer_call);
void Dispatch_(const RegionStmtNode* op) override;
- void Dispatch_(const AttrStmtNode* op) override;
void Dispatch_(const AssertStmtNode* op) override;
void Dispatch_(const BindNode* op) override;
void Dispatch_(const SeqStmtNode* op) override;
diff --git a/src/s_tir/analysis/calculate_allocated_memory.cc
b/src/s_tir/analysis/calculate_allocated_memory.cc
index 21bfaaa3a6..696a74fe77 100644
--- a/src/s_tir/analysis/calculate_allocated_memory.cc
+++ b/src/s_tir/analysis/calculate_allocated_memory.cc
@@ -107,12 +107,6 @@ class AllocTensorCalculator : public StmtExprVisitor {
_current_size = snapshot;
return std::nullopt;
}
- ffi::Optional<VisitInterrupt> Visit_(const AttrStmtNode* op) override {
- auto snapshot = _current_size;
- TVM_FFI_S_VISIT_MAYBE_EARLY_RETURN(StmtExprVisitor::Visit_(op));
- _current_size = snapshot;
- return std::nullopt;
- }
ffi::Optional<VisitInterrupt> Visit_(const RegionStmtNode* op) override {
auto snapshot = _current_size;
TVM_FFI_S_VISIT_MAYBE_EARLY_RETURN(StmtExprVisitor::Visit_(op));
diff --git a/src/s_tir/analysis/estimate_flops.cc
b/src/s_tir/analysis/estimate_flops.cc
index 49ff6521b2..5ac83f32ec 100644
--- a/src/s_tir/analysis/estimate_flops.cc
+++ b/src/s_tir/analysis/estimate_flops.cc
@@ -166,11 +166,6 @@ class FlopEstimator : private
tirx::ExprFunctor<TResult(const Expr& n)>,
}
TResult Dispatch_(const TensorLoadNode* op) override { return TResult(); }
- TResult Dispatch_(const AttrStmtNode* op) override {
- TResult result = Dispatch(op->body);
- result += Dispatch(op->value);
- return result;
- }
TResult Dispatch_(const RegionStmtNode* op) override {
TResult result = Dispatch(op->body);
for (const Expr& arg : op->args) result += Dispatch(arg);
diff --git a/src/s_tir/meta_schedule/feature_extractor/per_store_feature.cc
b/src/s_tir/meta_schedule/feature_extractor/per_store_feature.cc
index 4f6bbe0351..d50c5c6ec6 100644
--- a/src/s_tir/meta_schedule/feature_extractor/per_store_feature.cc
+++ b/src/s_tir/meta_schedule/feature_extractor/per_store_feature.cc
@@ -358,20 +358,6 @@ Pass SimplifyForFeatureExtraction(bool
normalize_thread_bindings = false) {
}
}
- UnchangedOr<Stmt> Mutate_(const AttrStmtNode* op, InplaceMode
inplace_mode) final {
- if (!normalize_thread_bindings_) return StmtExprMutator::Mutate_(op,
inplace_mode);
- auto node = Mutate(op->node, inplace_mode);
- auto value = Mutate(op->value, inplace_mode);
- auto body = Mutate(op->body, inplace_mode);
- if (node.UnchangedOrSameAs(op->node) &&
value.UnchangedOrSameAs(op->value) &&
- body.UnchangedOrSameAs(op->body)) {
- return ffi::Unchanged();
- }
- return AttrStmt(std::move(node).ValueOrUnchanged(op->node), op->attr_key,
- std::move(value).ValueOrUnchanged(op->value),
- std::move(body).ValueOrUnchanged(op->body), op->span);
- }
-
UnchangedOr<Stmt> Mutate_(const SBlockNode* op, InplaceMode inplace_mode)
final {
if (!normalize_thread_bindings_) return StmtExprMutator::Mutate_(op,
inplace_mode);
auto annotations = Mutate(op->annotations, inplace_mode)
diff --git a/src/s_tir/transform/hoist_expression.cc
b/src/s_tir/transform/hoist_expression.cc
index c641aeeb2a..1a21024639 100644
--- a/src/s_tir/transform/hoist_expression.cc
+++ b/src/s_tir/transform/hoist_expression.cc
@@ -270,30 +270,6 @@ class HoistInfoCollector : public StmtExprVisitor {
return std::nullopt;
}
- ffi::Optional<VisitInterrupt> Visit_(const AttrStmtNode* op) final {
- Var var{ffi::UnsafeInit{}};
- if (const auto* node_iter_var = op->node.as<IterVarNode>()) {
- var = node_iter_var->var;
- } else if (auto opt = op->node.as<Var>()) {
- var = opt.value();
- } else {
- return Parent::Visit_(op);
- }
-
- active_block_vars.insert(var.get());
- active_loop_vars.insert(var.get());
- active_loops.push_back({var, ffi::GetRef<Stmt>(op)});
-
- TVM_FFI_S_VISIT_MAYBE_EARLY_RETURN(Parent::Visit_(op));
-
- completed_loops.push_back(active_loops.back());
- active_loops.pop_back();
-
- active_loop_vars.erase(var.get());
- active_block_vars.erase(var.get());
- return std::nullopt;
- }
-
ffi::Optional<VisitInterrupt> Visit_(const RegionStmtNode* op) final {
if (op->op.same_as(tirx::builtin::launch_thread())) {
Var var = op->body_params[0].as_or_throw<PrimVar>();
@@ -572,17 +548,6 @@ class ExpressionHoister : public
s_tir::IRMutatorWithAnalyzer {
return WrapHoistedStatements(stmt, it->second);
}
- UnchangedOr<Stmt> Mutate_(const AttrStmtNode* op, InplaceMode inplace_mode)
final {
- Stmt stmt = Parent::Mutate_(op,
inplace_mode).ValueOrUnchanged(ffi::GetRef<Stmt>(op));
-
- auto it = loop_info_lookup.find(op);
- if (it == loop_info_lookup.end()) {
- return stmt;
- } else {
- return WrapHoistedStatements(stmt, it->second);
- }
- }
-
UnchangedOr<Stmt> Mutate_(const RegionStmtNode* op, InplaceMode
inplace_mode) final {
Stmt stmt = Parent::Mutate_(op,
inplace_mode).ValueOrUnchanged(ffi::GetRef<Stmt>(op));
auto it = loop_info_lookup.find(op);
diff --git a/src/s_tir/transform/inject_virtual_thread.cc
b/src/s_tir/transform/inject_virtual_thread.cc
index a97567cd94..c5b50328a0 100644
--- a/src/s_tir/transform/inject_virtual_thread.cc
+++ b/src/s_tir/transform/inject_virtual_thread.cc
@@ -456,24 +456,6 @@ class VTInjector : public s_tir::IRMutatorWithAnalyzer {
op->span);
}
- // Attribute
- UnchangedOr<Stmt> Mutate_(const AttrStmtNode* op, InplaceMode inplace_mode)
final {
- auto value_result = this->Mutate(op->value, inplace_mode);
- bool value_unchanged = value_result.UnchangedOrSameAs(op->value);
- Expr value = std::move(value_result).ValueOrUnchanged(op->value);
- if (visit_touched_var_ && !vt_loop_injected_) {
- return InjectVTLoop(ffi::GetRef<Stmt>(op), true);
- } else {
- auto body_result = this->Mutate(op->body, inplace_mode);
- bool body_unchanged = body_result.UnchangedOrSameAs(op->body);
- Stmt body = std::move(body_result).ValueOrUnchanged(op->body);
- if (value_unchanged && body_unchanged) {
- return ffi::Unchanged();
- } else {
- return AttrStmt(op->node, op->attr_key, value, body);
- }
- }
- }
// Bind
UnchangedOr<Stmt> Mutate_(const BindNode* op, InplaceMode inplace_mode)
final {
if (const auto* call = op->value.as<CallNode>();
diff --git a/src/s_tir/transform/lower_opaque_block.cc
b/src/s_tir/transform/lower_opaque_block.cc
index 908c3904db..d6f276861f 100644
--- a/src/s_tir/transform/lower_opaque_block.cc
+++ b/src/s_tir/transform/lower_opaque_block.cc
@@ -57,21 +57,6 @@ class OpaqueBlockLower : public StmtExprMutator {
std::optional<ffi::Any> unroll_explicit;
};
- UnchangedOr<Stmt> Mutate_(const AttrStmtNode* op, InplaceMode inplace_mode)
final {
- // Attribute metadata can reference a unit loop variable that is replaced.
- // Rewrite it before descending into body-local definitions.
- auto node = this->Mutate(op->node, inplace_mode);
- auto value = this->Mutate(op->value, inplace_mode);
- auto body = this->Mutate(op->body, inplace_mode);
- if (node.UnchangedOrSameAs(op->node) && value.UnchangedOrSameAs(op->value)
&&
- body.UnchangedOrSameAs(op->body)) {
- return ffi::Unchanged();
- }
- return AttrStmt(std::move(node).ValueOrUnchanged(op->node), op->attr_key,
- std::move(value).ValueOrUnchanged(op->value),
- std::move(body).ValueOrUnchanged(op->body), op->span);
- }
-
UnchangedOr<Stmt> Mutate_(const SBlockRealizeNode* op, InplaceMode
inplace_mode) final {
// We have convert blocks into opaque blocks in previous passes.
TVM_FFI_ICHECK(op->iter_values.empty())
@@ -115,12 +100,6 @@ class OpaqueBlockLower : public StmtExprMutator {
DictAttrs(allocate_annotations))),
std::move(body));
}
- // Step 4. Handle annotations, block annotations are not preserved by
default.
- std::vector<std::pair<std::string, Expr>> pragma_attrs;
- HandleAnnotations(new_block->annotations, &pragma_attrs,
/*is_block=*/true);
- for (auto it = pragma_attrs.rbegin(); it != pragma_attrs.rend(); ++it) {
- body = AttrStmt(0, it->first, it->second, std::move(body));
- }
return body;
}
@@ -139,7 +118,6 @@ class OpaqueBlockLower : public StmtExprMutator {
// Keep policy on surviving descendants when this owner is lowered away.
auto parent_policy = unroll_policy_.Current();
- std::vector<std::pair<std::string, Expr>> pragma_attrs;
ffi::Map<ffi::String, ffi::Any> new_annotations;
auto annotations = op->annotations;
Stmt body = unroll_policy_.WithNewScope([&]() {
@@ -153,29 +131,18 @@ class OpaqueBlockLower : public StmtExprMutator {
annotations.Set(tirx::attr::unroll_explicit,
policy.unroll_explicit.value());
}
// Rewrite annotations before visiting body-local definitions.
- new_annotations = HandleAnnotations(annotations, &pragma_attrs,
/*is_block=*/false);
+ new_annotations = HandleAnnotations(annotations);
return this->Mutate(op->body, inplace_mode).ValueOrUnchanged(op->body);
});
VarRemapSet(op->loop_var, previous_remap);
- // Step 4. Keep thread-binding loops until LowerThreadBinding.
+ // Step 2. Keep thread-binding loops until LowerThreadBinding.
if (op->kind != ForKind::kThreadBinding && is_one(extent) &&
op->annotations.empty() &&
!op->annotations.count(s_tir::attr::irregular_loop_mark)) {
return body;
}
- if (op->kind != ForKind::kThreadBinding) {
- body = For(op->loop_var, min, extent, op->kind, std::move(body),
op->thread_binding,
- new_annotations, step);
- }
- // Step 5. Insert nested attrs inside thread-binding scope.
- for (auto it = pragma_attrs.rbegin(); it != pragma_attrs.rend(); ++it) {
- body = AttrStmt(op->loop_var, it->first, it->second, std::move(body));
- }
- if (op->kind == ForKind::kThreadBinding) {
- body = For(op->loop_var, std::move(min), std::move(extent), op->kind,
std::move(body),
- op->thread_binding, std::move(new_annotations),
std::move(step), op->span);
- }
- return body;
+ return For(op->loop_var, std::move(min), std::move(extent), op->kind,
std::move(body),
+ op->thread_binding, std::move(new_annotations),
std::move(step), op->span);
}
void UpdateUnrollPolicy(const ffi::Map<ffi::String, ffi::Any>& annotations) {
@@ -193,61 +160,22 @@ class OpaqueBlockLower : public StmtExprMutator {
// Effective policy is materialized on each surviving loop, preserving
nested overrides.
ScopeStack<UnrollPolicy> unroll_policy_;
- /*! \brief Convert attr value from annotation map into Expr. */
- Expr ConvertAttrValue(const ffi::String& key, const Any& obj) {
- if (auto expr = obj.try_cast<Expr>()) {
- return expr.value();
- } else if (auto str = obj.try_cast<ffi::String>()) {
- return std::move(StringImm(str.value()));
- } else {
- TVM_FFI_THROW(InternalError) << "Illegal attribute of key " << key << ",
value type "
- << obj.GetTypeKey() << " not supported";
- }
- }
-
- /*!
- * \brief Helper to handle annotation dict.
- * (1) if the attr key is prefixed by `pragma_`, move to ordered kv list.
They
- * are lowered to `AttrStmt` by legacy TE schedule convention.
- * (2) the non-pragma loop annotations are preserved
- * (3) the non-pragma block annotations are dropped
- * \return New annotation dict with preserved keys. Also update pragma attr
pairs ordered by key.
- */
+ // Preserve loop annotations while remapping enclosing bindings. Null
optional
+ // policies do not override inherited values or reach code generation.
ffi::Map<ffi::String, ffi::Any> HandleAnnotations(
- const ffi::Map<ffi::String, ffi::Any>& annotations,
- std::vector<std::pair<std::string, Expr>>* pragma_attrs, bool is_block) {
- ffi::Map<ffi::String, ffi::Any> preserved_annotations;
- pragma_attrs->clear();
- for (const auto& kv : annotations) {
- const ffi::String& key = kv.first;
- if ((key == tirx::attr::auto_unroll_max_step || key ==
tirx::attr::unroll_explicit) &&
- kv.second == nullptr) {
+ const ffi::Map<ffi::String, ffi::Any>& annotations) {
+ ffi::Map<ffi::String, ffi::Any> preserved;
+ for (const auto& [key, value] : annotations) {
+ if ((key == tirx::attr::auto_unroll_max_step || key ==
tirx::attr::unroll_explicit ||
+ key == "pragma_unroll") &&
+ value == nullptr) {
continue;
}
- if (tirx::attr::IsPragmaKey(key)) {
- if (kv.second == nullptr) {
- continue;
- }
-
- auto value = this->Mutate(kv.second,
InplaceMode::kDisallow).ValueOrUnchanged(kv.second);
- pragma_attrs->emplace_back(key, ConvertAttrValue(key, value));
- } else if (!is_block) {
- // Preserve the annotation while remapping enclosing launch bindings,
- // including expressions nested in annotation containers.
- auto value = this->Mutate(kv.second,
InplaceMode::kDisallow).ValueOrUnchanged(kv.second);
- preserved_annotations.Set(key, value);
- }
+ preserved.Set(key, this->Mutate(value,
InplaceMode::kDisallow).ValueOrUnchanged(value));
}
- std::sort(pragma_attrs->begin(), pragma_attrs->end(),
- [](const auto& p1, const auto& p2) { return p1.first < p2.first;
});
- return preserved_annotations;
+ return preserved;
}
- /*! \brief Record the loop_var and loop start value of unit loops, whose
extent is one. */
-
- /*! \brief Attr keys to preserve into loop annotations. */
- std::unordered_set<std::string> preserved_annotations_;
-
/*! \brief The map from buffer var to its storage alignment information. */
std::unordered_map<Var, StorageAlignAnnotation> storage_align_;
};
diff --git a/src/s_tir/transform/lower_thread_binding.cc
b/src/s_tir/transform/lower_thread_binding.cc
index a57fde7973..d6d3dd87a9 100644
--- a/src/s_tir/transform/lower_thread_binding.cc
+++ b/src/s_tir/transform/lower_thread_binding.cc
@@ -34,20 +34,6 @@ class ThreadBindingLowerer : public StmtExprMutator {
using StmtExprMutator::Mutate_;
private:
- UnchangedOr<Stmt> Mutate_(const AttrStmtNode* op, InplaceMode inplace_mode)
final {
- // Attribute metadata can refer to an enclosing loop's lexical binding.
- auto node = Mutate(op->node, inplace_mode);
- auto value = Mutate(op->value, inplace_mode);
- auto body = Mutate(op->body, inplace_mode);
- if (node.UnchangedOrSameAs(op->node) && value.UnchangedOrSameAs(op->value)
&&
- body.UnchangedOrSameAs(op->body)) {
- return ffi::Unchanged();
- }
- return AttrStmt(std::move(node).ValueOrUnchanged(op->node), op->attr_key,
- std::move(value).ValueOrUnchanged(op->value),
- std::move(body).ValueOrUnchanged(op->body), op->span);
- }
-
UnchangedOr<Stmt> Mutate_(const SBlockNode* op, InplaceMode inplace_mode)
final {
auto annotations = Mutate(op->annotations, inplace_mode)
.as_or_throw<UnchangedOr<ffi::Map<ffi::String,
ffi::Any>>>();
diff --git a/src/script/printer/script_printer.cc
b/src/script/printer/script_printer.cc
index 04bbdcb850..3360ea9fed 100644
--- a/src/script/printer/script_printer.cc
+++ b/src/script/printer/script_printer.cc
@@ -123,7 +123,6 @@ TVM_FFI_STATIC_INIT_BLOCK() {
RegisterScriptRepr<te::CommReducerNode>();
RegisterScriptRepr<te::ReduceNode>();
RegisterScriptRepr<tirx::AssertStmtNode>();
- RegisterScriptRepr<tirx::AttrStmtNode>();
RegisterScriptRepr<tirx::RegionStmtNode>();
RegisterScriptRepr<tirx::BindNode>();
RegisterScriptRepr<tirx::BreakNode>();
diff --git a/src/target/llvm/codegen_cpu.cc b/src/target/llvm/codegen_cpu.cc
index 62d0113ac9..35f1260569 100644
--- a/src/target/llvm/codegen_cpu.cc
+++ b/src/target/llvm/codegen_cpu.cc
@@ -1141,27 +1141,6 @@ void CodeGenCPU::Dispatch_(const RegionStmtNode* op) {
}
}
-void CodeGenCPU::Dispatch_(const AttrStmtNode* op) {
- EmitDebugLocation(op);
- if (tirx::attr::IsPragmaKey(op->attr_key)) {
- if (op->attr_key == "pragma_parallel_stride_pattern") {
- TVM_FFI_THROW(ValueError)
- << "pragma_parallel_stride_pattern is retired; annotate every
affected parallel For "
- << "with parallel_stride_pattern=True, including later loops in the
same launch "
- << "outside the former attribute body";
- } else if (op->attr_key == "pragma_parallel_barrier_when_finish") {
- TVM_FFI_THROW(ValueError)
- << "pragma_parallel_barrier_when_finish is retired; place
cpu_parallel_barrier() "
- << "after the former attribute body inside the parallel launch";
- } else {
- LOG(WARNING) << "Unknown pragma " << op->attr_key;
- this->Dispatch(op->body);
- }
- } else {
- CodeGenLLVM::Dispatch_(op);
- }
-}
-
void CodeGenCPU::Dispatch_(const ForNode* op) {
EmitDebugLocation(op);
if (op->kind == ForKind::kSerial || op->kind == ForKind::kUnrolled) {
diff --git a/src/target/llvm/codegen_cpu.h b/src/target/llvm/codegen_cpu.h
index dba07332d8..e9549a82bd 100644
--- a/src/target/llvm/codegen_cpu.h
+++ b/src/target/llvm/codegen_cpu.h
@@ -73,7 +73,6 @@ class CodeGenCPU : public CodeGenLLVM {
std::unique_ptr<llvm::Module> Finish() override;
void Dispatch_(const AssertStmtNode* op) override;
void Dispatch_(const RegionStmtNode* op) override;
- void Dispatch_(const AttrStmtNode* op) override;
void Dispatch_(const ForNode* op) override;
llvm::Value* CreateIntrinsic(const CallNode* op) override;
llvm::Value* CreateCallExtern(Type ret_type, ffi::String global_symbol,
diff --git a/src/target/llvm/codegen_llvm.cc b/src/target/llvm/codegen_llvm.cc
index 9d8f6da7b2..dfd8d97dd7 100644
--- a/src/target/llvm/codegen_llvm.cc
+++ b/src/target/llvm/codegen_llvm.cc
@@ -2265,13 +2265,6 @@ void CodeGenLLVM::Dispatch_(const RegionStmtNode* op) {
}
}
-void CodeGenLLVM::Dispatch_(const AttrStmtNode* op) {
- TVM_FFI_CHECK(op->attr_key != "thread_extent" && op->attr_key !=
"virtual_thread", ValueError)
- << "Launch attributes are retired; use tirx.launch_thread RegionStmt";
- EmitDebugLocation(op);
- this->Dispatch(op->body);
-}
-
void CodeGenLLVM::Dispatch_(const AssertStmtNode* op) {
EmitDebugLocation(op);
// AssertStmt is a leaf — no body to visit.
diff --git a/src/target/llvm/codegen_llvm.h b/src/target/llvm/codegen_llvm.h
index c077d21563..199953add3 100644
--- a/src/target/llvm/codegen_llvm.h
+++ b/src/target/llvm/codegen_llvm.h
@@ -246,7 +246,6 @@ class CodeGenLLVM : public
tirx::ExprFunctor<llvm::Value*(const Expr&)>,
void Dispatch_(const IfThenElseNode* op) override;
void DispatchAllocTensor(const BindNode* op, const CallNode* buffer_call);
void Dispatch_(const RegionStmtNode* op) override;
- void Dispatch_(const AttrStmtNode* op) override;
void Dispatch_(const AssertStmtNode* op) override;
void Dispatch_(const BindNode* op) override;
void Dispatch_(const SeqStmtNode* op) override;
diff --git a/src/target/source/codegen_c.cc b/src/target/source/codegen_c.cc
index 68d40b5107..be5bdd5ae0 100644
--- a/src/target/source/codegen_c.cc
+++ b/src/target/source/codegen_c.cc
@@ -1319,12 +1319,6 @@ void CodeGenC::Dispatch_(const RegionStmtNode* op) {
}
}
-void CodeGenC::Dispatch_(const AttrStmtNode* op) {
- TVM_FFI_CHECK(op->attr_key != "thread_extent" && op->attr_key !=
"virtual_thread", ValueError)
- << "Launch attributes are retired; use tirx.launch_thread RegionStmt";
- this->PrintStmt(op->body);
-}
-
void CodeGenC::PrintEscapedCString(const std::string& str, std::ostream& os) {
os << "\"";
for (unsigned char c : str) {
diff --git a/src/target/source/codegen_c.h b/src/target/source/codegen_c.h
index bf96b0a2c5..96af65a167 100644
--- a/src/target/source/codegen_c.h
+++ b/src/target/source/codegen_c.h
@@ -219,7 +219,6 @@ class CodeGenC : public tirx::ExprFunctor<void(const Expr&,
std::ostream&)>,
void Dispatch_(const IfThenElseNode* op) override;
void DispatchAllocTensor(const BindNode* op, const CallNode* buffer_call);
void Dispatch_(const RegionStmtNode* op) override;
- void Dispatch_(const AttrStmtNode* op) override;
void Dispatch_(const AssertStmtNode* op) override;
void Dispatch_(const EvaluateNode* op) override;
void Dispatch_(const SeqStmtNode* op) override;
diff --git a/src/tirx/analysis/verify_tirx_well_formed.cc
b/src/tirx/analysis/verify_tirx_well_formed.cc
index 1e3acb4bde..8adb59131b 100644
--- a/src/tirx/analysis/verify_tirx_well_formed.cc
+++ b/src/tirx/analysis/verify_tirx_well_formed.cc
@@ -144,9 +144,6 @@ class DeviceFuncVerifier : public
Verifier<DeviceFuncVerifier> {
};
bool VerifyTIRxWellFormed(const PrimFunc& func, bool assert_mode, bool
device_func) {
- if (!RetiredLaunchAttrVerifier<TIRVisitorWithPath>::Verify(func,
assert_mode)) {
- return false;
- }
if (!ExecScopeVerifier::Verify(func, assert_mode)) {
return false;
}
diff --git a/src/tirx/analysis/verify_well_formed.h
b/src/tirx/analysis/verify_well_formed.h
index df779c8214..27e92b2615 100644
--- a/src/tirx/analysis/verify_well_formed.h
+++ b/src/tirx/analysis/verify_well_formed.h
@@ -28,25 +28,6 @@ namespace tvm {
namespace tirx {
using AccessPath = ffi::reflection::AccessPath;
-/*! \brief Reject retired launch attributes, including loaded IR. */
-template <typename PathVisitor>
-class RetiredLaunchAttrVerifier
- : public Verifier<RetiredLaunchAttrVerifier<PathVisitor>, PathVisitor> {
- using Verifier = tirx::Verifier<RetiredLaunchAttrVerifier<PathVisitor>,
PathVisitor>;
-
- public:
- using Verifier::Verifier;
- using Verifier::Verify;
-
- private:
- void Dispatch_(const AttrStmtNode* op, AccessPath path) override {
- bool retired = op->attr_key == "thread_extent" || op->attr_key ==
"virtual_thread";
- Verify(!retired) << "ValueError: Retired thread launch attribute at " <<
path
- << "; use RegionStmt launch_thread";
- if (!retired) PathVisitor::Dispatch_(op, path);
- }
-};
-
template <typename PathVisitor>
class UndefinedVarVerifier : public
Verifier<UndefinedVarVerifier<PathVisitor>, PathVisitor> {
using Verifier = tirx::Verifier<UndefinedVarVerifier<PathVisitor>,
PathVisitor>;
@@ -322,8 +303,7 @@ class LoopControlVerifier : public
Verifier<LoopControlVerifier<PathVisitor>, Pa
template <typename PathVisitor, typename NodeRef>
bool VerifyWellFormedCommon(const NodeRef& node, bool assert_mode) {
- return RetiredLaunchAttrVerifier<PathVisitor>::Verify(node, assert_mode) &&
- UndefinedVarVerifier<PathVisitor>::Verify(node, assert_mode) &&
+ return UndefinedVarVerifier<PathVisitor>::Verify(node, assert_mode) &&
UndefinedBufferVerifier<PathVisitor>::Verify(node, assert_mode) &&
TensorLoadTypeVerifier<PathVisitor>::Verify(node, assert_mode) &&
LoopControlVerifier<PathVisitor>::Verify(node, assert_mode);
diff --git a/src/tirx/ir/ir_mutator_with_analyzer.cc
b/src/tirx/ir/ir_mutator_with_analyzer.cc
index 2f430f535d..4b72595516 100644
--- a/src/tirx/ir/ir_mutator_with_analyzer.cc
+++ b/src/tirx/ir/ir_mutator_with_analyzer.cc
@@ -211,11 +211,6 @@ UnchangedOr<Stmt> IRMutatorWithAnalyzer::Mutate_(const
IfThenElseNode* op,
});
}
-UnchangedOr<Stmt> IRMutatorWithAnalyzer::Mutate_(const AttrStmtNode* op,
InplaceMode inplace_mode) {
- return constraint_scope_.WithNewScope(
- [&]() { return StmtExprMutator::Mutate_(op, inplace_mode); });
-}
-
UnchangedOr<Stmt> IRMutatorWithAnalyzer::Mutate_(const RegionStmtNode* op,
InplaceMode inplace_mode) {
return constraint_scope_.WithNewScope([&]() -> UnchangedOr<Stmt> {
diff --git a/src/tirx/ir/ir_mutator_with_analyzer.h
b/src/tirx/ir/ir_mutator_with_analyzer.h
index 8cc4e29de1..dd4dd7e1c3 100644
--- a/src/tirx/ir/ir_mutator_with_analyzer.h
+++ b/src/tirx/ir/ir_mutator_with_analyzer.h
@@ -60,7 +60,6 @@ class IRMutatorWithAnalyzer : public StmtExprMutator {
UnchangedOr<Stmt> Mutate_(const ForNode* op, InplaceMode inplace_mode)
override;
UnchangedOr<Stmt> Mutate_(const BindNode* op, InplaceMode inplace_mode)
override;
UnchangedOr<Stmt> Mutate_(const IfThenElseNode* op, InplaceMode
inplace_mode) override;
- UnchangedOr<Stmt> Mutate_(const AttrStmtNode* op, InplaceMode inplace_mode)
override;
UnchangedOr<Stmt> Mutate_(const RegionStmtNode* op, InplaceMode
inplace_mode) override;
UnchangedOr<Stmt> Mutate_(const AssertStmtNode* op, InplaceMode
inplace_mode) override;
UnchangedOr<Expr> Mutate_(const CallNode* op, InplaceMode inplace_mode)
override;
diff --git a/src/tirx/ir/ir_visitor_with_analyzer.cc
b/src/tirx/ir/ir_visitor_with_analyzer.cc
index 0094fcfecd..63d8eec00a 100644
--- a/src/tirx/ir/ir_visitor_with_analyzer.cc
+++ b/src/tirx/ir/ir_visitor_with_analyzer.cc
@@ -79,10 +79,6 @@ ffi::Optional<VisitInterrupt>
IRVisitorWithAnalyzer::Visit_(const IfThenElseNode
});
}
-ffi::Optional<VisitInterrupt> IRVisitorWithAnalyzer::Visit_(const
AttrStmtNode* op) {
- return constraint_scope_.WithNewScope([&]() { return
StmtExprVisitor::Visit_(op); });
-}
-
ffi::Optional<VisitInterrupt> IRVisitorWithAnalyzer::Visit_(const
RegionStmtNode* op) {
return constraint_scope_.WithNewScope([&]() -> ffi::Optional<VisitInterrupt>
{
if (op->op.same_as(tirx::builtin::launch_thread())) {
diff --git a/src/tirx/ir/ir_visitor_with_analyzer.h
b/src/tirx/ir/ir_visitor_with_analyzer.h
index affdde2dc6..1a6a8f3a0b 100644
--- a/src/tirx/ir/ir_visitor_with_analyzer.h
+++ b/src/tirx/ir/ir_visitor_with_analyzer.h
@@ -45,7 +45,6 @@ class IRVisitorWithAnalyzer : public StmtExprVisitor {
ffi::Optional<VisitInterrupt> Visit_(const ForNode* op);
ffi::Optional<VisitInterrupt> Visit_(const BindNode* op);
ffi::Optional<VisitInterrupt> Visit_(const IfThenElseNode* op);
- ffi::Optional<VisitInterrupt> Visit_(const AttrStmtNode* op);
ffi::Optional<VisitInterrupt> Visit_(const RegionStmtNode* op);
ffi::Optional<VisitInterrupt> Visit_(const AssertStmtNode* op);
ffi::Optional<VisitInterrupt> Visit_(const CallNode* op);
diff --git a/src/tirx/ir/stmt.cc b/src/tirx/ir/stmt.cc
index 874861b318..7694f664f5 100644
--- a/src/tirx/ir/stmt.cc
+++ b/src/tirx/ir/stmt.cc
@@ -149,60 +149,6 @@ TVM_FFI_INLINE ffi::Expected<ffi::UnchangedOr<ffi::Any>>
BindMaybeInplaceMutate(
return ffi::Unchanged();
}
-TVM_FFI_INLINE ffi::Expected<ffi::Optional<ffi::VisitInterrupt>> AttrStmtVisit(
- ffi::StructuralVisitorObj* visitor, ffi::AnyView value) noexcept {
- // skips: attr_key
- const AttrStmtNode* self =
- ffi::details::AnyUnsafe::RawObjectPtrFromAnyViewAfterCheck<const
AttrStmtNode>(value);
- TVM_FFI_S_VISIT_MAYBE_EARLY_RETURN(visitor->VisitExpected(self->node));
- TVM_FFI_S_VISIT_MAYBE_EARLY_RETURN(visitor->VisitExpected(self->value));
- TVM_FFI_S_VISIT_MAYBE_EARLY_RETURN(visitor->VisitExpected(self->body));
- return std::nullopt;
-}
-
-TVM_FFI_INLINE ffi::Expected<ffi::UnchangedOr<ffi::Any>> AttrStmtMutate(
- ffi::StructuralMutatorObj* mutator, ffi::AnyView value) noexcept {
- // skips: attr_key
- const AttrStmtNode* self =
- ffi::details::AnyUnsafe::RawObjectPtrFromAnyViewAfterCheck<const
AttrStmtNode>(value);
- TVM_FFI_S_MUTATE_ASSIGN_OR_RETURN(ffi::UnchangedOr<ffi::Any>, mapped_node,
- mutator->MutateExpected(self->node));
- TVM_FFI_S_MUTATE_ASSIGN_OR_RETURN(ffi::UnchangedOr<Expr>, mapped_value,
- mutator->MutateExpected(self->value));
- TVM_FFI_S_MUTATE_ASSIGN_OR_RETURN(ffi::UnchangedOr<Stmt>, mapped_body,
- mutator->MutateExpected(self->body));
- if (mapped_node.UnchangedOrSameAs(self->node) &&
mapped_value.UnchangedOrSameAs(self->value) &&
- mapped_body.UnchangedOrSameAs(self->body)) {
- return ffi::Unchanged();
- }
- ffi::ObjectPtr<AttrStmtNode> copy = ffi::make_object<AttrStmtNode>(*self);
- copy->node = std::move(mapped_node).ValueOrUnchanged(std::move(copy->node));
- copy->value =
std::move(mapped_value).ValueOrUnchanged(std::move(copy->value));
- copy->body = std::move(mapped_body).ValueOrUnchanged(std::move(copy->body));
- return ffi::Any(std::move(copy));
-}
-
-TVM_FFI_INLINE ffi::Expected<ffi::UnchangedOr<ffi::Any>>
AttrStmtMaybeInplaceMutate(
- ffi::StructuralMutatorObj* mutator, ffi::AnyView value) noexcept {
- // skips: attr_key
- AttrStmtNode* self = const_cast<AttrStmtNode*>(
- ffi::details::AnyUnsafe::RawObjectPtrFromAnyViewAfterCheck<const
AttrStmtNode>(value));
- TVM_FFI_S_MUTATE_ASSIGN_OR_RETURN(ffi::UnchangedOr<ffi::Any>, mapped_node,
- mutator->MutateExpected(self->node,
ffi::InplaceMode::kAllow));
- TVM_FFI_S_MUTATE_ASSIGN_OR_RETURN(ffi::UnchangedOr<Expr>, mapped_value,
- mutator->MutateExpected(self->value,
ffi::InplaceMode::kAllow));
- TVM_FFI_S_MUTATE_ASSIGN_OR_RETURN(ffi::UnchangedOr<Stmt>, mapped_body,
- mutator->MutateExpected(self->body,
ffi::InplaceMode::kAllow));
- if (mapped_node.UnchangedOrSameAs(self->node) &&
mapped_value.UnchangedOrSameAs(self->value) &&
- mapped_body.UnchangedOrSameAs(self->body)) {
- return ffi::Unchanged();
- }
- if (!mapped_node.IsUnchanged()) self->node =
std::move(mapped_node).ValueUnchecked();
- if (!mapped_value.IsUnchanged()) self->value =
std::move(mapped_value).ValueUnchecked();
- if (!mapped_body.IsUnchanged()) self->body =
std::move(mapped_body).ValueUnchecked();
- return ffi::Unchanged();
-}
-
TVM_FFI_INLINE ffi::Expected<ffi::Optional<ffi::VisitInterrupt>>
RegionStmtVisit(
ffi::StructuralVisitorObj* visitor, ffi::AnyView value) noexcept {
const RegionStmtNode* self =
@@ -775,34 +721,6 @@ TVM_FFI_STATIC_INIT_BLOCK() {
[](Var var, Expr value, Span span) { return Bind(var,
value, span); });
}
-// AttrStmt
-AttrStmt::AttrStmt(ffi::Any node, ffi::String attr_key, Expr value, Stmt body,
Span span)
- : Stmt(ffi::UnsafeInit{}) {
- TVM_FFI_CHECK(attr_key != "thread_extent" && attr_key != "virtual_thread",
ValueError)
- << "Thread launch attributes are retired; use launch_thread(tag,
extent)";
- auto n = ffi::make_object<AttrStmtNode>(std::move(value), std::move(body));
- n->node = node;
- n->attr_key = std::move(attr_key);
- n->span = std::move(span);
- data_ = std::move(n);
-}
-
-TVM_FFI_STATIC_INIT_BLOCK() {
- namespace refl = tvm::ffi::reflection;
- AttrStmtNode::RegisterReflection();
- refl::TypeAttrDef<AttrStmtNode>()
- .attr(refl::type_attr::kStructuralVisit,
ffi::FStructuralVisit::FromNative<&AttrStmtVisit>())
- .attr(refl::type_attr::kStructuralMutate,
- ffi::FStructuralMutate::FromNative<&AttrStmtMutate>())
- .attr(refl::type_attr::kStructuralMaybeInplaceMutate,
- ffi::FStructuralMutate::FromNative<&AttrStmtMaybeInplaceMutate>());
-
- refl::GlobalDef().def("tirx.AttrStmt",
- [](Any node, ffi::String attr_key, Expr value, Stmt
body, Span span) {
- return AttrStmt(node, attr_key, value, body, span);
- });
-}
-
// RegionStmt
RegionStmt::RegionStmt(Op op, ffi::Array<Expr> args, ffi::Array<Var>
body_params, DictAttrs attrs,
Stmt body, ffi::Array<Var> result_vars, Span span)
diff --git a/src/tirx/ir/stmt_functor.cc b/src/tirx/ir/stmt_functor.cc
index d061831506..ae1b53fac8 100644
--- a/src/tirx/ir/stmt_functor.cc
+++ b/src/tirx/ir/stmt_functor.cc
@@ -43,7 +43,6 @@ namespace tirx {
void StmtExprVisitor::InitVTable(VTable* vtable) {
tvm::ExprVisitor::InitVTable(vtable);
SetDispatch<StmtExprVisitor, BindNode>(vtable);
- SetDispatch<StmtExprVisitor, AttrStmtNode>(vtable);
SetDispatch<StmtExprVisitor, RegionStmtNode>(vtable);
SetDispatch<StmtExprVisitor, IfThenElseNode>(vtable);
SetDispatch<StmtExprVisitor, ForNode>(vtable);
@@ -134,11 +133,6 @@ ffi::Optional<VisitInterrupt>
StmtExprVisitor::Visit_(const BindNode* op) {
[&]() { return this->Visit(op->var); });
}
-ffi::Optional<VisitInterrupt> StmtExprVisitor::Visit_(const AttrStmtNode* op) {
- TVM_FFI_S_VISIT_MAYBE_EARLY_RETURN(this->Visit(op->value));
- return this->Visit(op->body);
-}
-
ffi::Optional<VisitInterrupt> StmtExprVisitor::Visit_(const RegionStmtNode*
op) {
TVM_FFI_S_VISIT_MAYBE_EARLY_RETURN(this->Visit(op->attrs));
TVM_FFI_S_VISIT_MAYBE_EARLY_RETURN(this->Visit(op->args));
@@ -247,7 +241,6 @@ ffi::Optional<VisitInterrupt> StmtExprVisitor::Visit_(const
TilePrimitiveCallNod
void StmtExprMutator::InitVTable(VTable* vtable) {
tvm::ExprMutator::InitVTable(vtable);
SetDispatch<StmtExprMutator, BindNode>(vtable);
- SetDispatch<StmtExprMutator, AttrStmtNode>(vtable);
SetDispatch<StmtExprMutator, RegionStmtNode>(vtable);
SetDispatch<StmtExprMutator, IfThenElseNode>(vtable);
SetDispatch<StmtExprMutator, ForNode>(vtable);
@@ -293,23 +286,6 @@ UnchangedOr<Stmt> StmtExprMutator::Mutate_(const BindNode*
op, InplaceMode inpla
return Stmt(std::move(copy));
}
-UnchangedOr<Stmt> StmtExprMutator::Mutate_(const AttrStmtNode* op, InplaceMode
inplace_mode) {
- auto value = Mutate(op->value, inplace_mode);
- auto body = Mutate(op->body, inplace_mode);
- if (value.UnchangedOrSameAs(op->value) && body.UnchangedOrSameAs(op->body))
- return ffi::Unchanged();
- if (inplace_mode == InplaceMode::kAllow) {
- auto* writable = const_cast<AttrStmtNode*>(op);
- if (!value.IsUnchanged()) writable->value =
std::move(value).ValueUnchecked();
- if (!body.IsUnchanged()) writable->body = std::move(body).ValueUnchecked();
- return ffi::Unchanged();
- }
- auto copy = ffi::make_object<AttrStmtNode>(*op);
- if (!value.IsUnchanged()) copy->value = std::move(value).ValueUnchecked();
- if (!body.IsUnchanged()) copy->body = std::move(body).ValueUnchecked();
- return Stmt(std::move(copy));
-}
-
UnchangedOr<Stmt> StmtExprMutator::Mutate_(const RegionStmtNode* op,
InplaceMode inplace_mode) {
auto attrs = Mutate(op->attrs,
inplace_mode).as_or_throw<UnchangedOr<DictAttrs>>();
auto args = Mutate(op->args,
inplace_mode).as_or_throw<UnchangedOr<ffi::Array<Expr>>>();
@@ -608,23 +584,6 @@ class IRSubstituteWithDataTypeLegalization : public
DataTypeLegalizer {
}
return load;
}
-
- UnchangedOr<Stmt> Mutate_(const AttrStmtNode* op, InplaceMode inplace_mode)
final {
- Stmt ret = StmtExprMutator::Mutate_(op,
inplace_mode).ValueOrUnchanged(ffi::GetRef<Stmt>(op));
- op = ret.as<AttrStmtNode>();
- // remap var node in attr
- if (auto var_node = op->node.as<Var>()) {
- ffi::Any mapped = VarRemapGet(var_node.value());
- if (mapped.type_index() != ffi::TypeIndex::kTVMFFINone) {
- Expr node =
-
std::move(mapped).as_or_throw<UnchangedOr<Expr>>().ValueOrUnchanged(var_node.value());
- if (!node.same_as(var_node.value())) {
- return AttrStmt(node, op->attr_key, op->value, op->body);
- }
- }
- }
- return ret;
- }
};
Stmt SubstituteWithDataTypeLegalization(Stmt stmt,
diff --git a/src/tirx/ir/tir_visitor_with_path.cc
b/src/tirx/ir/tir_visitor_with_path.cc
index c0595a1168..54cd11dbe8 100644
--- a/src/tirx/ir/tir_visitor_with_path.cc
+++ b/src/tirx/ir/tir_visitor_with_path.cc
@@ -179,14 +179,6 @@ void TIRVisitorWithPath::Dispatch_(const BindNode* op,
AccessPath path) {
bind_scope_.Current().push_back(WithDef(op->var, path->Attr("var")));
}
-void TIRVisitorWithPath::Dispatch_(const AttrStmtNode* op, AccessPath path) {
- Visit(op->value, path->Attr("value"));
- if (auto expr = op->node.as<PrimExpr>()) {
- Visit(expr.value(), path->Attr("node"));
- }
- bind_scope_.WithNewScope([&]() { Visit(op->body, path->Attr("body")); });
-}
-
void TIRVisitorWithPath::Dispatch_(const RegionStmtNode* op, AccessPath path) {
Visit(op->args, path->Attr("args"));
Visit(ffi::AnyView(op->attrs), path->Attr("attrs"));
diff --git a/src/tirx/ir/tir_visitor_with_path.h
b/src/tirx/ir/tir_visitor_with_path.h
index 72050a9a11..80208d7f7d 100644
--- a/src/tirx/ir/tir_visitor_with_path.h
+++ b/src/tirx/ir/tir_visitor_with_path.h
@@ -148,7 +148,6 @@ class TIRVisitorWithPath : protected ExprFunctor<void(const
Expr&, ffi::reflecti
using StmtFunctor::Dispatch;
void Dispatch_(const BindNode* op, ffi::reflection::AccessPath path)
override;
- void Dispatch_(const AttrStmtNode* op, ffi::reflection::AccessPath path)
override;
void Dispatch_(const RegionStmtNode* op, ffi::reflection::AccessPath path)
override;
void Dispatch_(const IfThenElseNode* op, ffi::reflection::AccessPath path)
override;
void Dispatch_(const ForNode* op, ffi::reflection::AccessPath path) override;
diff --git a/src/tirx/script/ir_builder/frame.cc
b/src/tirx/script/ir_builder/frame.cc
index 7dba06f37c..5939eaff2d 100644
--- a/src/tirx/script/ir_builder/frame.cc
+++ b/src/tirx/script/ir_builder/frame.cc
@@ -43,7 +43,6 @@ TVM_FFI_STATIC_INIT_BLOCK() {
ForFrameNode::RegisterReflection();
AssertFrameNode::RegisterReflection();
RegionFrameNode::RegisterReflection();
- AttrFrameNode::RegisterReflection();
WhileFrameNode::RegisterReflection();
IfFrameNode::RegisterReflection();
ThenFrameNode::RegisterReflection();
@@ -220,11 +219,6 @@ void RegionFrameNode::ExitWithScope() {
source_span);
}
-void AttrFrameNode::ExitWithScope() {
- TIRFrameNode::ExitWithScope();
- AddToParent(tvm::tirx::AttrStmt(node, attr_key, value, AsStmt(stmts),
source_span), source_span);
-}
-
void WhileFrameNode::ExitWithScope() {
TIRFrameNode::ExitWithScope();
AddToParent(tvm::tirx::While(condition, AsStmt(stmts), source_span),
source_span);
diff --git a/src/tirx/script/ir_builder/ir.cc b/src/tirx/script/ir_builder/ir.cc
index 636e079ff3..7d4d468df9 100644
--- a/src/tirx/script/ir_builder/ir.cc
+++ b/src/tirx/script/ir_builder/ir.cc
@@ -188,7 +188,7 @@ ffi::Array<tvm::tirx::Var>
ScopeId(ffi::Optional<ffi::Array<PrimExpr>> extents,
}
// Emit a standalone ScopeIdDefStmt to the current TIRFrame's stmts list.
// The def is visible to all subsequent stmts within the same enclosing
- // scope (PrimFunc body, AttrStmt body, ExecScope body, etc.).
+ // scope (PrimFunc body, RegionStmt body, ExecScope body, etc.).
tvm::tirx::ScopeIdDef def(
scope_ids.Map([](tvm::tirx::Var var) { return
var.as_or_throw<tvm::PrimVar>(); }), extents,
tvm::tirx::StringPairToScopeBinding(parent, cur));
@@ -432,13 +432,6 @@ RegionFrame LaunchThread(ffi::String thread_tag, PrimExpr
extent) {
return Region(tvm::tirx::builtin::launch_thread(), {StringImm(thread_tag),
extent}, {var});
}
-AttrFrame Attr(ffi::Any node, ffi::String attr_key, Expr value) {
- ffi::ObjectPtr<AttrFrameNode> n = ffi::make_object<AttrFrameNode>(value);
- n->node = std::move(node);
- n->attr_key = attr_key;
- return AttrFrame(n);
-}
-
WhileFrame While(PrimExpr condition) {
ffi::ObjectPtr<WhileFrameNode> n =
ffi::make_object<WhileFrameNode>(condition);
return WhileFrame(n);
@@ -705,7 +698,6 @@ TVM_FFI_STATIC_INIT_BLOCK() {
.def("script.ir_builder.tirx.Grid", Grid)
.def("script.ir_builder.tirx.Assert", Assert)
.def("script.ir_builder.tirx.Bind", Bind)
- .def("script.ir_builder.tirx.Attr", Attr)
.def("script.ir_builder.tirx.While", While)
.def("script.ir_builder.tirx.Return", Return)
.def("script.ir_builder.tirx.Break", Break)
diff --git a/src/tirx/script/printer/stmt.cc b/src/tirx/script/printer/stmt.cc
index 0ffc17c34d..352fc1d69e 100644
--- a/src/tirx/script/printer/stmt.cc
+++ b/src/tirx/script/printer/stmt.cc
@@ -426,65 +426,6 @@ TVM_FFI_STATIC_INIT_BLOCK() {
kDocTranslate, FDocTranslate::FromNative<&RegionStmtDocTranslate>());
}
-ffi::Optional<ExprDoc> AttrStmtDocTranslate(DocTranslatorObj* d, ffi::AnyView
input,
- const ffi::Object* destination) {
- const auto* stmt =
- ffi::details::AnyUnsafe::RawObjectPtrFromAnyViewAfterCheck<const
tirx::AttrStmtNode>(input);
- TVM_FFI_CHECK(destination == nullptr, TypeError)
- << "printer statement-only node cannot fulfill a destination";
- ffi::Optional<ExprDoc> lhs = std::nullopt;
- ExprDoc rhs(ffi::UnsafeInit{});
- tirx::Stmt body = stmt->body;
- TVM_FFI_CHECK(stmt->attr_key != "thread_extent" && stmt->attr_key !=
"virtual_thread", ValueError)
- << "Thread launch attributes are no longer supported; use RegionStmt
launch_thread";
- if (stmt->attr_key == "tirx_hint") {
- if (auto attrs = stmt->node.as<ffi::Map<ffi::String, ffi::Any>>()) {
- ffi::Array<ExprDoc> args;
- ffi::Array<ffi::String> keys;
- ffi::Array<ExprDoc> values;
- for (const auto& [key, value] : attrs.value()) {
- if (key == "message")
- args.push_back(AnyValue(d, value));
- else {
- keys.push_back(key);
- values.push_back(AnyValue(d, value));
- }
- }
- rhs = NamespaceDoc("tirx")->Attr("hint")->Call(args, keys, values);
- }
- }
- if (!rhs.defined()) {
- if (auto zero = stmt->node.as<int64_t>(); zero.has_value() && zero.value()
== 0) {
- ffi::Array<ExprDoc> keys;
- ffi::Array<ExprDoc> values;
- auto current = ffi::GetRef<tirx::AttrStmt>(stmt);
- while (true) {
- keys.push_back(LiteralDoc::Str(current->attr_key, std::nullopt));
- values.push_back(d->Translate(current->value).value());
- auto next = current->body.as<tirx::AttrStmt>();
- if (!next.has_value()) break;
- auto next_zero = next.value()->node.as<int64_t>();
- if (!next_zero.has_value() || next_zero.value() != 0) break;
- current = next.value();
- }
- body = current->body;
- rhs = NamespaceDoc("tirx")->Attr("attr")->Call({DictDoc(keys, values)});
- } else {
- ExprDoc node = AnyValue(d, stmt->node);
- rhs = NamespaceDoc("tirx")->Attr("attr")->Call(
- {node, LiteralDoc::Str(stmt->attr_key, std::nullopt),
d->Translate(stmt->value).value()});
- }
- }
- d->Emit(ScopeDoc(lhs, rhs, Body(body, d), /*allow_concise_scoping=*/true),
- ffi::GetRef<ffi::ObjectRef>(stmt));
- return std::nullopt;
-}
-
-TVM_FFI_STATIC_INIT_BLOCK() {
- ffi::reflection::TypeAttrDef<tirx::AttrStmtNode>().attr(
- kDocTranslate, FDocTranslate::FromNative<&AttrStmtDocTranslate>());
-}
-
} // namespace
} // namespace details
diff --git a/src/tirx/transform/common_subexpr_elim.cc
b/src/tirx/transform/common_subexpr_elim.cc
index d6cb658dab..364492c095 100644
--- a/src/tirx/transform/common_subexpr_elim.cc
+++ b/src/tirx/transform/common_subexpr_elim.cc
@@ -27,7 +27,7 @@
*
* Phase 1 — **CSEPlanner** (analysis, no mutation)
* Walks the TIR tree bottom-up and builds:
- * - A *scope tree* that mirrors the nesting structure of
For/If/While/AttrStmt.
+ * - A *scope tree* that mirrors the nesting structure of
For/If/While/RegionStmt.
* - An *expression DAG* mapping each structurally-unique eligible
expression
* to its occurrence count, LCA scope, first-use location, and direct
* children (which shallower expressions it contains).
@@ -56,7 +56,7 @@
*
* Scope tree
* ----------
- * Each For, IfThenElse (each branch), While, and AttrStmt body creates a new
+ * Each For, IfThenElse (each branch), While, and RegionStmt body creates a new
* scope. The scope tree enables computing the Lowest Common Ancestor (LCA) of
* all scopes where an expression occurs, which determines the correct
insertion
* point — the narrowest scope that dominates all uses.
@@ -122,7 +122,7 @@ using InsertBeforeTable =
* \brief Phase 1 of the two-phase CSE pass.
*
* CSEPlanner is a read-only visitor that scans the TIR tree bottom-up and
builds:
- * 1. A **scope tree** (vector of ScopeEntry) reflecting
For/If/While/AttrStmt nesting.
+ * 1. A **scope tree** (vector of ScopeEntry) reflecting
For/If/While/RegionStmt nesting.
* 2. An **expression DAG** (ExprTable) where each node is an eligible
expression
* with occurrence count, expr_depth, LCA scope, first-use location, and
* direct children (other table entries reachable without passing through
@@ -166,7 +166,7 @@ class CSEPlanner : public StmtExprVisitor {
* \brief One node in the scope tree.
*
* The scope tree mirrors the nesting structure of the TIR program.
- * Each scope-creating statement (For, IfThenElse branch, While, AttrStmt)
+ * Each scope-creating statement (For, IfThenElse branch, While, RegionStmt)
* gets its own ScopeEntry. The root scope (depth 0) represents the function
* body itself.
*/
@@ -625,16 +625,6 @@ class CSEPlanner : public StmtExprVisitor {
return std::nullopt;
}
- /*! \brief AttrStmt: value in parent scope, body in child scope. */
- ffi::Optional<VisitInterrupt> Visit_(const AttrStmtNode* op) override {
- TVM_FFI_S_VISIT_MAYBE_EARLY_RETURN(Visit(op->value));
- int saved = current_scope_;
- current_scope_ = AllocScope(saved, ffi::GetRef<Stmt>(op));
- TVM_FFI_S_VISIT_MAYBE_EARLY_RETURN(Visit(op->body));
- current_scope_ = saved;
- return std::nullopt;
- }
-
// ------------------------------------------------------------------
// ComputePlan: convert scan results into the output plan
// ------------------------------------------------------------------
diff --git a/src/tirx/transform/ir_utils.cc b/src/tirx/transform/ir_utils.cc
index caec09540d..ac6167a932 100644
--- a/src/tirx/transform/ir_utils.cc
+++ b/src/tirx/transform/ir_utils.cc
@@ -53,11 +53,6 @@ Stmt MergeNest(const std::vector<Stmt>& nest, Stmt body) {
} else if (const auto* bind = s.as<BindNode>()) {
// Bind has no body -- prepend it before the accumulated body in a
SeqStmt.
body = SeqStmt::Flatten(ffi::GetRef<Stmt>(bind), body);
- } else if (const auto* attr = s.as<AttrStmtNode>()) {
- auto n = ffi::make_object<AttrStmtNode>(*attr);
- TVM_FFI_ICHECK(is_no_op(n->body));
- n->body = body;
- body = Stmt(n);
} else if (const auto* ite = s.as<IfThenElseNode>()) {
auto n = ffi::make_object<IfThenElseNode>(*ite);
TVM_FFI_ICHECK(is_no_op(n->then_case));
@@ -149,7 +144,6 @@ PrimFunc IRConvertSSA::VisitPrimFunc(PrimFunc func) {
// Pop function-scope remaps in reverse order
PopAllRemapsInCurrentScope();
- function_scope_var_remap_.clear();
return func;
}
@@ -197,9 +191,6 @@ Var IRConvertSSA::GetRemappedVar(Var var) {
if (auto it = scoped_var_remap_.find(var.get());
it != scoped_var_remap_.end() && it->second.size()) {
return it->second.back();
- } else if (auto it = function_scope_var_remap_.find(var.get());
- it != function_scope_var_remap_.end()) {
- return it->second;
} else {
return var;
}
@@ -281,83 +272,6 @@ UnchangedOr<Stmt> IRConvertSSA::Mutate_(const
RegionStmtNode* op, InplaceMode in
std::move(results), op->span);
}
-UnchangedOr<Stmt> IRConvertSSA::Mutate_(const AttrStmtNode* op, InplaceMode
inplace_mode) {
- if (const IterVarNode* iter_var = op->node.as<IterVarNode>()) {
- Range dom = iter_var->dom;
- if (dom.defined()) {
- // Retain the original domain while comparing and rebuilding its
replacement.
- auto min = Mutate(dom->min,
InplaceMode::kDisallow).ValueOrUnchanged(dom->min);
- auto extent = Mutate(dom->extent,
InplaceMode::kDisallow).ValueOrUnchanged(dom->extent);
- if (!min.same_as(iter_var->dom->min) ||
!extent.same_as(iter_var->dom->extent)) {
- dom = Range::FromMinExtent(min, extent);
- }
- }
-
- Var var = iter_var->var;
- bool delayed_define = false;
- if (auto it = function_scope_var_remap_.find(var.get());
- it != function_scope_var_remap_.end()) {
- var = it->second;
- } else if (defined_.count(var.get())) {
- Var new_var(var->name, var->ty);
-
- function_scope_var_remap_.insert({var.get(), new_var});
- var = new_var;
- } else {
- // An attribute can refer to a variable defined by a later ForNode.
- // Preserve the same variable definition in the attribute and the loop.
- //
- // Preserve the annotated variable's identity for later definitions
- // and independent functions, without introducing a lexical body binding.
- delayed_define = true;
- }
-
- IterVar new_iter_var;
- if (dom.same_as(iter_var->dom) && var.same_as(iter_var->var)) {
- new_iter_var = ffi::GetRef<IterVar>(iter_var);
- } else {
- new_iter_var = IterVar(dom, var.as_or_throw<PrimVar>(),
iter_var->iter_type,
- iter_var->thread_tag, iter_var->span);
- }
- auto value_result = Mutate(op->value, inplace_mode);
- bool value_unchanged = value_result.UnchangedOrSameAs(op->value);
- auto value = std::move(value_result).ValueOrUnchanged(op->value);
- auto body = scope_.WithNewScope(
- [&]() -> Stmt { return Mutate(op->body,
inplace_mode).ValueOrUnchanged(op->body); });
-
- Stmt output = ffi::GetRef<Stmt>(op);
- if (new_iter_var.get() == iter_var && body.same_as(op->body) &&
value_unchanged) {
- output = ffi::GetRef<Stmt>(op);
- } else {
- output = AttrStmt(new_iter_var, op->attr_key, value, body,
iter_var->span);
- }
-
- if (delayed_define) {
- if (!defined_.count(var.get())) {
- function_scope_var_remap_.insert({var.get(), var});
- defined_.insert(var.get());
- }
- }
-
- return output;
-
- } else if (const VarNode* v = op->node.as<VarNode>()) {
- Stmt stmt = scope_.WithNewScope([&]() -> Stmt {
- return StmtExprMutator::Mutate_(op,
inplace_mode).ValueOrUnchanged(ffi::GetRef<Stmt>(op));
- });
- op = stmt.as<AttrStmtNode>();
- if (scoped_var_remap_.count(v) && scoped_var_remap_[v].size() != 0) {
- return AttrStmt(scoped_var_remap_[v].back(), op->attr_key, op->value,
op->body);
- } else {
- return stmt;
- }
- } else {
- return scope_.WithNewScope([&]() -> Stmt {
- return StmtExprMutator::Mutate_(op,
inplace_mode).ValueOrUnchanged(ffi::GetRef<Stmt>(op));
- });
- }
-}
-
Var IRConvertSSA::MakeNewVar(const Var& old_var) {
return Var(old_var->name, old_var->ty, old_var->span);
}
diff --git a/src/tirx/transform/ir_utils.h b/src/tirx/transform/ir_utils.h
index db29ba0fb5..a3fc4fcb12 100644
--- a/src/tirx/transform/ir_utils.h
+++ b/src/tirx/transform/ir_utils.h
@@ -246,7 +246,6 @@ class IRConvertSSA : public StmtExprMutator {
UnchangedOr<Stmt> Mutate_(const IfThenElseNode* op, InplaceMode
inplace_mode) final;
UnchangedOr<Stmt> Mutate_(const ForNode* op, InplaceMode inplace_mode) final;
UnchangedOr<Stmt> Mutate_(const WhileNode* op, InplaceMode inplace_mode)
final;
- UnchangedOr<Stmt> Mutate_(const AttrStmtNode* op, InplaceMode inplace_mode)
final;
UnchangedOr<Stmt> Mutate_(const RegionStmtNode* op, InplaceMode
inplace_mode) final;
UnchangedOr<PrimExpr> Mutate_(const prim::LetNode* op, InplaceMode
inplace_mode) final;
static Var MakeNewVar(const Var& old_var);
@@ -307,7 +306,6 @@ class IRConvertSSA : public StmtExprMutator {
std::unordered_map<const VarNode*, std::vector<Var>> scoped_var_remap_;
std::unordered_set<const VarNode*> defined_;
- std::unordered_map<const VarNode*, Var> function_scope_var_remap_;
ScopeStack<ScopeLevel> scope_;
};
diff --git a/src/tirx/transform/lower_thread_allreduce.h
b/src/tirx/transform/lower_thread_allreduce.h
index 4e03b7d92a..9b8f5b7740 100644
--- a/src/tirx/transform/lower_thread_allreduce.h
+++ b/src/tirx/transform/lower_thread_allreduce.h
@@ -104,7 +104,7 @@ class ThreadAllreduceBuilder final : public DialectMutator {
UnchangedOr<Stmt> MutateAllocTensor(const BindNode* op, InplaceMode
inplace_mode) {
buffer_aliases_.Set(op->var, op->var);
// In flat IR, alloc_remap_ may not yet be populated when this AllocTensor
is visited
- // (the remap is set up by MakeAllreduce which runs during
AttrStmt/Evaluate visit
+ // (the remap is set up by MakeAllreduce which runs during Evaluate visit
// that appears later in the sequence). We record the original data
pointer and
// attempt the remap; if it's not ready, the post-processing pass will
handle it.
const VarNode* orig_data_ptr = op->var.get();
diff --git a/src/tirx/transform/lower_tirx_opaque.cc
b/src/tirx/transform/lower_tirx_opaque.cc
index f30beeaaa4..21aa83bb6d 100644
--- a/src/tirx/transform/lower_tirx_opaque.cc
+++ b/src/tirx/transform/lower_tirx_opaque.cc
@@ -22,10 +22,9 @@
* \brief Lower opaque constructs in TIRX programs. This is the tirx-specific
* counterpart of s_tirx::LowerOpaqueBlock, handling only the non-SBlock
* parts: AllocTensor lowering, For(thread_binding) →
RegionStmt(launch_thread),
- * unit loop elimination, and pragma annotation handling.
+ * unit loop elimination, and loop policy inheritance.
*/
-#include <tvm/ffi/extra/structural_visit.h>
#include <tvm/ffi/reflection/registry.h>
#include <tvm/ir/scope_stack.h>
#include <tvm/runtime/logging.h>
@@ -63,22 +62,6 @@ class TIRxOpaqueLower : public StmtExprMutator {
std::optional<ffi::Any> unroll_explicit;
};
- UnchangedOr<Stmt> Mutate_(const AttrStmtNode* op, InplaceMode inplace_mode)
final {
- // Attribute subjects may contain references to the loop binding being
- // replaced, including expressions and IterVar fields. Rewrite metadata
- // before the body introduces any additional local remaps.
- auto node = Mutate(op->node, inplace_mode);
- auto value = Mutate(op->value, inplace_mode);
- auto body = Mutate(op->body, inplace_mode);
- if (node.UnchangedOrSameAs(op->node) && value.UnchangedOrSameAs(op->value)
&&
- body.UnchangedOrSameAs(op->body)) {
- return ffi::Unchanged();
- }
- return AttrStmt(std::move(node).ValueOrUnchanged(op->node), op->attr_key,
- std::move(value).ValueOrUnchanged(op->value),
- std::move(body).ValueOrUnchanged(op->body), op->span);
- }
-
UnchangedOr<Stmt> Mutate_(const ForNode* op, InplaceMode inplace_mode) final
{
// Step 1. Update unit loop info.
PrimExpr min = this->Mutate(op->min,
inplace_mode).ValueOrUnchanged(op->min);
@@ -117,28 +100,7 @@ class TIRxOpaqueLower : public StmtExprMutator {
});
VarRemapSet(op->loop_var, previous_remap);
- // Step 3. Handle annotations
- std::vector<std::pair<std::string, Expr>> pragma_attrs;
- ffi::Map<ffi::String, ffi::Any> new_annotations =
HandleAnnotations(annotations, &pragma_attrs);
- if (op->kind != ForKind::kThreadBinding) {
- // A pragma that uses this loop's own Var must remain inside its scope.
- // Pragmas using only enclosing bindings retain their wrapper position.
- std::vector<std::pair<std::string, Expr>> outer_pragmas;
- for (auto it = pragma_attrs.rbegin(); it != pragma_attrs.rend(); ++it) {
- auto uses_loop_var = [&](const Var& var) ->
ffi::Expected<ffi::WalkResult> {
- return var.same_as(op->loop_var) ?
ffi::WalkResult::Interrupt(ffi::VisitInterrupt(var))
- : ffi::WalkResult::Advance();
- };
- if (ffi::StructuralWalk<ffi::WalkOrder::kPreOrder>(it->second,
uses_loop_var).has_value()) {
- body = AttrStmt(op->loop_var, it->first, it->second,
std::move(body));
- } else {
- outer_pragmas.push_back(*it);
- }
- }
- std::reverse(outer_pragmas.begin(), outer_pragmas.end());
- pragma_attrs = std::move(outer_pragmas);
- }
- // Step 4. Create new For loop accordingly
+ // Step 2. Create the lowered loop or launch region.
if (op->kind == ForKind::kThreadBinding) {
// Case 1. Thread binding → RegionStmt(launch_thread)
TVM_FFI_ICHECK(!op->annotations.count("loop_partition_hint") ||
@@ -152,12 +114,7 @@ class TIRxOpaqueLower : public StmtExprMutator {
} else {
// Case 3. An ordinary loop
body = For(op->loop_var, std::move(min), std::move(extent), op->kind,
std::move(body),
- std::nullopt, new_annotations, step);
- }
- // Step 5. Insert nested attrs for pragma annotations
- for (auto it = pragma_attrs.rbegin(); it != pragma_attrs.rend(); ++it) {
- Var var = op->kind == ForKind::kThreadBinding ? Var(launch_var) :
Var(op->loop_var);
- body = AttrStmt(var, it->first, it->second, std::move(body));
+ std::nullopt, FilterAnnotations(annotations), step);
}
if (op->kind == ForKind::kThreadBinding) {
return RegionStmt(tirx::builtin::launch_thread(),
@@ -182,58 +139,20 @@ class TIRxOpaqueLower : public StmtExprMutator {
// Effective policy is materialized on each surviving loop, preserving
nested overrides.
ScopeStack<UnrollPolicy> unroll_policy_;
- /*! \brief Convert attr value from annotation map into Expr. */
- Expr ConvertAttrValue(const ffi::String& key, const Any& obj) {
- if (auto expr = obj.try_cast<Expr>()) {
- return expr.value();
- } else if (auto str = obj.try_cast<ffi::String>()) {
- return std::move(StringImm(str.value()));
- } else {
- LOG(FATAL) << "Illegal attribute of key " << key << ", value type " <<
obj.GetTypeKey()
- << " not supported";
- }
- }
-
- /*!
- * \brief Handle loop annotation dict.
- * (1) if the attr key is prefixed by `pragma_`, move to ordered kv list
- * (lowered to `AttrStmt` by legacy TE schedule convention), except for
- * `pragma_unroll`, whose bool-or-integer value must remain on the loop.
- * (2) non-pragma loop annotations are preserved.
- * \return New annotation dict with preserved keys. Also update pragma attr
pairs ordered by key.
- */
- ffi::Map<ffi::String, ffi::Any> HandleAnnotations(
- const ffi::Map<ffi::String, ffi::Any>& annotations,
- std::vector<std::pair<std::string, Expr>>* pragma_attrs) {
- ffi::Map<ffi::String, ffi::Any> preserved_annotations;
- pragma_attrs->clear();
- for (const auto& kv : annotations) {
- const ffi::String& key = kv.first;
- if ((key == tirx::attr::auto_unroll_max_step || key ==
tirx::attr::unroll_explicit) &&
- kv.second == nullptr) {
+ // Null optional policies do not override inherited values or reach code
generation.
+ ffi::Map<ffi::String, ffi::Any> FilterAnnotations(
+ const ffi::Map<ffi::String, ffi::Any>& annotations) {
+ ffi::Map<ffi::String, ffi::Any> preserved;
+ for (const auto& [key, value] : annotations) {
+ if ((key == tirx::attr::auto_unroll_max_step || key ==
tirx::attr::unroll_explicit ||
+ key == "pragma_unroll") &&
+ value == nullptr) {
continue;
}
- if (key == "pragma_unroll") {
- if (kv.second != nullptr) {
- preserved_annotations.Set(key, kv.second);
- }
- } else if (tirx::attr::IsPragmaKey(key)) {
- if (kv.second == nullptr) {
- continue;
- }
-
- pragma_attrs->emplace_back(key, ConvertAttrValue(key, kv.second));
- } else {
- // Loop annotations are always preserved
- preserved_annotations.Set(key, kv.second);
- }
+ preserved.Set(key, value);
}
- std::sort(pragma_attrs->begin(), pragma_attrs->end(),
- [](const auto& p1, const auto& p2) { return p1.first < p2.first;
});
- return preserved_annotations;
+ return preserved;
}
-
- /*! \brief Record the loop_var and loop start value of unit loops, whose
extent is one. */
};
namespace transform {
diff --git a/src/tirx/transform/lower_tvm_builtin.cc
b/src/tirx/transform/lower_tvm_builtin.cc
index 2046074656..eb5e21ee6e 100644
--- a/src/tirx/transform/lower_tvm_builtin.cc
+++ b/src/tirx/transform/lower_tvm_builtin.cc
@@ -367,20 +367,6 @@ class BuiltinLower : public StmtExprMutator {
});
}
- UnchangedOr<Stmt> Mutate_(const AttrStmtNode* op, InplaceMode inplace_mode)
final {
- return scope_.WithNewScope([&]() -> Stmt {
- Stmt visited =
- StmtExprMutator::Mutate_(op,
inplace_mode).ValueOrUnchanged(ffi::GetRef<Stmt>(op));
- if (!scope_.Current().pending_frees.empty()) {
- const auto* attr = visited.as<AttrStmtNode>();
- if (attr) {
- return AttrStmt(attr->node, attr->attr_key, attr->value,
AppendPendingFrees(attr->body),
- attr->span);
- }
- }
- return visited;
- });
- }
UnchangedOr<Stmt> Mutate_(const ForNode* op, InplaceMode inplace_mode) final
{
auto min_result = this->Mutate(op->min, inplace_mode);
bool min_unchanged = min_result.UnchangedOrSameAs(op->min);
@@ -735,7 +721,7 @@ class BuiltinLower : public StmtExprMutator {
*
* When a Bind allocates via nd_mem_alloc_with_scope, the corresponding
* free_nd stmt is pushed to the current scope's pending_frees. Body-carrying
- * stmts (For, IfThenElse, AttrStmt) create new scopes via
+ * stmts (For, IfThenElse, RegionStmt) create new scopes via
* WithNewScope. On scope exit, pending_frees are appended after the body.
* AllocTensor (flat, no body) pushes its free to the enclosing scope.
*/
diff --git a/src/tirx/transform/remove_no_op.cc
b/src/tirx/transform/remove_no_op.cc
index 5d9033d77a..8235e58c26 100644
--- a/src/tirx/transform/remove_no_op.cc
+++ b/src/tirx/transform/remove_no_op.cc
@@ -91,11 +91,6 @@ class NoOpRemover : public IRMutatorWithAnalyzer {
: Parent(analyzer), ignore_profiler_call_(ignore_profiler_call) {}
private:
- UnchangedOr<Stmt> Mutate_(const AttrStmtNode* op, InplaceMode inplace_mode)
final {
- Stmt stmt = Parent::Mutate_(op,
inplace_mode).ValueOrUnchanged(ffi::GetRef<Stmt>(op));
- op = stmt.as<AttrStmtNode>();
- return is_no_op(op->body) ? MakeEvaluate(op->value) : stmt;
- }
UnchangedOr<Stmt> Mutate_(const IfThenElseNode* op, InplaceMode
inplace_mode) final {
Stmt stmt = Parent::Mutate_(op,
inplace_mode).ValueOrUnchanged(ffi::GetRef<Stmt>(op));
op = stmt.as<IfThenElseNode>();
diff --git a/src/tirx/transform/storage_rewrite.cc
b/src/tirx/transform/storage_rewrite.cc
index 7c5fb6c943..24ac6e62e6 100644
--- a/src/tirx/transform/storage_rewrite.cc
+++ b/src/tirx/transform/storage_rewrite.cc
@@ -346,9 +346,7 @@ class InplaceOpVerifier : public StmtExprVisitor {
dst_ = dst;
src_ = src;
result_ = true;
- if (stmt->IsInstance<AttrStmtNode>()) {
- Visit_(static_cast<const AttrStmtNode*>(stmt));
- } else if (stmt->IsInstance<ForNode>()) {
+ if (stmt->IsInstance<ForNode>()) {
Visit_(static_cast<const ForNode*>(stmt));
} else if (stmt->IsInstance<IfThenElseNode>()) {
Visit_(static_cast<const IfThenElseNode*>(stmt));
@@ -681,23 +679,6 @@ class StoragePlanRewriter : public StmtExprMutator {
return region;
}
- UnchangedOr<Stmt> Mutate_(const AttrStmtNode* op, InplaceMode inplace_mode)
final {
- if (attr::IsPragmaKey(op->attr_key)) {
- // remake all the allocation at the attach scope.
- if (attach_map_.count(op)) {
- auto& svec = attach_map_[op];
- Stmt stmt =
- StmtExprMutator::Mutate_(op,
inplace_mode).ValueOrUnchanged(ffi::GetRef<Stmt>(op));
- op = stmt.as<AttrStmtNode>();
- return AttrStmt(op->node, op->attr_key, op->value, MakeAttach(svec,
op->body));
- } else {
- return StmtExprMutator::Mutate_(op, inplace_mode);
- }
- } else {
- return StmtExprMutator::Mutate_(op, inplace_mode);
- }
- }
-
UnchangedOr<Stmt> Mutate_(const ForNode* op, InplaceMode inplace_mode) final
{
TVM_FFI_ICHECK(op->kind != ForKind::kVectorized) << "VectorizeLoop before
LiftStorageAlloc";
// remake all the allocation at the attach scope.
@@ -1176,12 +1157,7 @@ class StoragePlanRewriter : public StmtExprMutator {
}
}
// enter/exit new scope
- if (s.stmt->IsInstance<AttrStmtNode>()) {
- const auto* op = static_cast<const AttrStmtNode*>(s.stmt);
- if (attr::IsPragmaKey(op->attr_key)) {
- PlanNewScope(op);
- }
- } else if (s.stmt->IsInstance<RegionStmtNode>()) {
+ if (s.stmt->IsInstance<RegionStmtNode>()) {
PlanNewScope(s.stmt);
} else if (s.stmt->IsInstance<ForNode>()) {
const auto* op = static_cast<const ForNode*>(s.stmt);
@@ -2149,20 +2125,6 @@ class VectorTypeRewriter : public StmtExprMutator {
using StmtExprMutator::Mutate;
using StmtExprMutator::Mutate_;
- UnchangedOr<Stmt> Mutate_(const AttrStmtNode* op, InplaceMode
inplace_mode) final {
- Stmt stmt =
- StmtExprMutator::Mutate_(op,
inplace_mode).ValueOrUnchanged(ffi::GetRef<Stmt>(op));
- op = stmt.as<AttrStmtNode>();
- TVM_FFI_ICHECK(op != nullptr);
- if (auto var = op->node.as<Var>()) {
- auto mapped = VarRemapGet(var.value());
- if (mapped != nullptr) {
- return AttrStmt(mapped.as_or_throw<Var>(), op->attr_key,
op->value, op->body, op->span);
- }
- }
- return stmt;
- }
-
UnchangedOr<Expr> Mutate_(const CallNode* op, InplaceMode inplace_mode)
final {
auto result = StmtExprMutator::Mutate_(op, inplace_mode);
if (!result.IsUnchanged()) {
diff --git a/src/tirx/transform/tvm_ffi_binder.h
b/src/tirx/transform/tvm_ffi_binder.h
index 8fc9ae1200..e012c80c6b 100644
--- a/src/tirx/transform/tvm_ffi_binder.h
+++ b/src/tirx/transform/tvm_ffi_binder.h
@@ -59,7 +59,7 @@ namespace tirx {
* by a later buffer's shape (batch_size). Separating definitions from
* checks guarantees all variables are in scope when assertions reference them.
*
- * - init_nest: Binds, DeclTensors for shape/strides arrays, AttrStmts —
+ * - init_nest: Binds, DeclTensors for shape/strides arrays —
* all value-loading code that defines variables.
* - asserts: AssertStmts — all validation checks.
* - decl_buffers: DeclTensor for buffer-typed parameters — buffer
declarations.
@@ -96,7 +96,7 @@ class TVMFFIABIBuilder {
struct Result {
/*! \brief Var -> VarDefInfo map for defined variables. */
std::unordered_map<const VarNode*, VarDefInfo> var_defs;
- /*! \brief Variable definitions (Binds, shape/strides DeclTensors,
AttrStmts). */
+ /*! \brief Variable definitions (Binds, shape/strides DeclTensors). */
std::vector<Stmt> init_nest;
/*! \brief Validation checks (all AssertStmts). */
std::vector<Stmt> asserts;
@@ -385,7 +385,7 @@ class TVMFFIABIBuilder {
/*! \brief The definition map: VarNode* -> VarDefInfo (value +
first_def_path). */
std::unordered_map<const VarNode*, VarDefInfo> var_defs_;
- /*! \brief Variable definitions: Binds, shape/strides DeclTensors,
AttrStmts. */
+ /*! \brief Variable definitions: Binds, shape/strides DeclTensors. */
std::vector<Stmt> init_nest_;
/*! \brief Validation checks: all AssertStmts. */
std::vector<Stmt> asserts_;
diff --git a/src/tirx/transform/unsupported_dtype_legalize.cc
b/src/tirx/transform/unsupported_dtype_legalize.cc
index a629658458..54b4dd1767 100644
--- a/src/tirx/transform/unsupported_dtype_legalize.cc
+++ b/src/tirx/transform/unsupported_dtype_legalize.cc
@@ -398,18 +398,6 @@ class ComputeLegalizer : public StmtExprMutator {
}
}
- UnchangedOr<Stmt> Mutate_(const AttrStmtNode* op, InplaceMode inplace_mode)
final {
- Stmt ret = StmtExprMutator::Mutate_(op,
inplace_mode).ValueOrUnchanged(ffi::GetRef<Stmt>(op));
- op = ret.as<AttrStmtNode>();
- if (auto var = op->node.as<Var>()) {
- auto mapped = VarRemapGet(var.value());
- if (mapped != nullptr) {
- return AttrStmt(mapped.as_or_throw<Var>(), op->attr_key, op->value,
op->body);
- }
- }
- return ret;
- }
-
UnchangedOr<PrimExpr> Mutate_(const TensorLoadNode* op, InplaceMode
inplace_mode) final {
TensorVar buffer = GetRemappedBuffer(op->source.as_or_throw<TensorVar>());
auto indices = Mutate(op->indices, inplace_mode)
@@ -594,19 +582,6 @@ class StorageLegalizer : public StmtExprMutator {
}
}
- UnchangedOr<Stmt> Mutate_(const AttrStmtNode* op, InplaceMode inplace_mode)
final {
- Stmt ret = StmtExprMutator::Mutate_(op,
inplace_mode).ValueOrUnchanged(ffi::GetRef<Stmt>(op));
- op = ret.as<AttrStmtNode>();
-
- if (auto var = op->node.as<Var>()) {
- auto mapped = VarRemapGet(var.value());
- if (mapped != nullptr) {
- return AttrStmt(mapped.as_or_throw<Var>(), op->attr_key, op->value,
op->body);
- }
- }
- return ret;
- }
-
UnchangedOr<PrimExpr> Mutate_(const TensorLoadNode* op, InplaceMode
inplace_mode) final {
TensorVar buffer = GetRemappedBuffer(op->source.as_or_throw<TensorVar>());
auto indices = Mutate(op->indices, inplace_mode)
diff --git a/tests/python/s_tir/transform/test_s_tir_transform_hoist_if.py
b/tests/python/s_tir/transform/test_s_tir_transform_hoist_if.py
index 894689d1b8..4a69d3ec5e 100644
--- a/tests/python/s_tir/transform/test_s_tir_transform_hoist_if.py
+++ b/tests/python/s_tir/transform/test_s_tir_transform_hoist_if.py
@@ -50,8 +50,6 @@ def verify_structure(stmt, expected_struct):
elif isinstance(op, tvm.tirx.RegionStmt):
assert op.op.name == "tirx.launch_thread"
val = [(op.body,), ("tirx.RegionStmt", op.op.name,
int(op.args[1]))]
- elif isinstance(op, tvm.tirx.AttrStmt):
- val = [(op.body,), ("tirx.AttrStmt", op.attr_key, int(op.value))]
else:
return
node_dict[key] = val
@@ -161,7 +159,7 @@ def test_no_else():
verify_structure(new_stmt, expected_struct)
-def test_attr_stmt():
+def test_thread_launch():
dshape = (32, 64)
@Ts.prim_func(private=True)
diff --git
a/tests/python/s_tir/transform/test_s_tir_transform_lower_opaque_block.py
b/tests/python/s_tir/transform/test_s_tir_transform_lower_opaque_block.py
index caa0a5fa58..900cdc9593 100644
--- a/tests/python/s_tir/transform/test_s_tir_transform_lower_opaque_block.py
+++ b/tests/python/s_tir/transform/test_s_tir_transform_lower_opaque_block.py
@@ -303,12 +303,6 @@ def transformed_symbolic_strided_buffer_func(A:
T.Tensor((1, n, 10240))):
)
[email protected]_func
-def annotated_loops(A: T.Tensor((16,), "float32")) -> None:
- for i in range(0, 16, annotations={"pragma_1": "str_value", "pragma_2": 1,
"pragma_3": 0.0}):
- A[i] = 0.0
-
-
@Ts.prim_func
def boolean_handling_before(a: T.Tensor(10, "bool"), b: T.Tensor(10, "bool"))
-> None:
for i0 in T.serial(10):
@@ -357,38 +351,6 @@ def test_symbolic_strided_buffer():
_check(compacted_symbolic_strided_buffer_func,
transformed_symbolic_strided_buffer_func)
-def test_annotated_loops():
- mod = tvm.IRModule.from_expr(annotated_loops.with_attr("global_symbol",
"main"))
- mod = tvm.s_tir.transform.LowerOpaqueBlock()(mod)
- attr1 = mod["main"].body
- attr2 = attr1.body
- attr3 = attr2.body
- assert attr1.attr_key == "pragma_1" and attr1.value == "str_value"
- assert attr2.attr_key == "pragma_2"
- tvm.ir.assert_structural_equal(attr2.value, tvm.tirx.IntImm("int32", 1))
- assert attr3.attr_key == "pragma_3"
- tvm.ir.assert_structural_equal(attr3.value, tvm.tirx.FloatImm("float32",
0.0))
-
-
-def test_annotated_block():
- @Ts.prim_func
- def annotated_block() -> None:
- with Ts.sblock():
- Ts.sblock_attr({"pragma_1": "str_value", "pragma_2": 1,
"pragma_3": 0.0})
- T.evaluate(0)
-
- mod = tvm.IRModule.from_expr(annotated_block.with_attr("global_symbol",
"main"))
- mod = tvm.s_tir.transform.LowerOpaqueBlock()(mod)
- attr1 = mod["main"].body
- attr2 = attr1.body
- attr3 = attr2.body
- assert attr1.attr_key == "pragma_1" and attr1.value == "str_value"
- assert attr2.attr_key == "pragma_2"
- tvm.ir.assert_structural_equal(attr2.value, tvm.tirx.IntImm("int32", 1))
- assert attr3.attr_key == "pragma_3"
- tvm.ir.assert_structural_equal(attr3.value, tvm.tirx.FloatImm("float32",
0.0))
-
-
def test_preserved_annotations():
@Ts.prim_func
def before(A: T.Tensor(8, "float32"), B: T.Tensor(8, "float32")):
diff --git a/tests/python/tirx-base/test_tir_constructor.py
b/tests/python/tirx-base/test_tir_constructor.py
index a65e88eb84..60fc6a9f9a 100644
--- a/tests/python/tirx-base/test_tir_constructor.py
+++ b/tests/python/tirx-base/test_tir_constructor.py
@@ -292,10 +292,6 @@ def test_stmt_constructor():
assert x.var == v
assert x.value.value == 1
- x = tvm.tirx.AttrStmt(v == 1, "xx", 1, tvm.tirx.Evaluate(1))
- assert isinstance(x, tvm.tirx.AttrStmt)
- assert x.value.value == 1
-
x = tvm.tirx.AssertStmt(
tvm.tirx.const(1, "bool"),
tvm.ir.StringImm("RuntimeError"),
@@ -339,12 +335,6 @@ def test_stmt_constructor():
assert _is_buffer_binding(x, "tirx.alloc_tensor")
assert x.var == buf
- x = tvm.tirx.AttrStmt(buffer_var, "xyz", 1, nop)
- assert isinstance(x, tvm.tirx.AttrStmt)
- assert x.node == buffer_var
- assert x.attr_key == "xyz"
- assert x.body == nop
-
x = tvm.tirx.IfThenElse(tvm.tirx.const(1, "bool"), tvm.tirx.Evaluate(11),
nop)
assert isinstance(x, tvm.tirx.IfThenElse)
assert x.then_case.value.value == 11
diff --git a/tests/python/tirx-base/test_tir_nodes.py
b/tests/python/tirx-base/test_tir_nodes.py
index f1c03f794a..2f247b37d2 100644
--- a/tests/python/tirx-base/test_tir_nodes.py
+++ b/tests/python/tirx-base/test_tir_nodes.py
@@ -111,11 +111,6 @@ def test_cast():
def test_attr():
- x = tvm.tirx.Var("x", "int32")
- y = tvm.tirx.Var("y", "int32")
- stmt = tvm.tirx.AttrStmt(y, "stride", 10, tvm.tirx.Evaluate(x + 1))
- assert stmt.node == y
-
a = tvm.runtime.convert(1)
assert a == 1
try:
diff --git a/tests/python/tirx-transform/test_tir_transform_convert_ssa.py
b/tests/python/tirx-transform/test_tir_transform_convert_ssa.py
index 6ef9260492..36dc126ce8 100644
--- a/tests/python/tirx-transform/test_tir_transform_convert_ssa.py
+++ b/tests/python/tirx-transform/test_tir_transform_convert_ssa.py
@@ -453,56 +453,6 @@ def test_thread_idx_reused_within_and_across_functions():
tvm.ir.assert_structural_equal(after, expected)
-def test_track_forward_declarations_in_attr_stmt():
- """T.attr statements may refer to a about-to-be-defined tirx.Var"""
-
- # Generate the PrimFunc, which is already SSA
- #
- # This is constructed directly, rather than using TVMScript.
- # This test case requires a `tirx.AttrStmt` that references a
- # variable, followed by the `tirx.For` defining that variable.
- # This is not expressible in TVMScript, as it only provides the
- # loop iterator within the body of the loop.
- i0_outer_outer = tirx.Var("i0_outer_outer", "int32")
- i0_outer_inner = tirx.Var("i0_outer_inner", "int32")
- i0_inner = tirx.Var("i0_inner", "int32")
-
- A = tirx.decl_tensor(1024, "float32", "A")
- B = tirx.decl_tensor(1024, "float32", "B")
-
- index = i0_outer_outer * 52 + i0_outer_inner * 4 + i0_inner
-
- stmt = tirx.BufferStore(B, tirx.TensorLoad(A, [index]), [index])
- stmt = tirx.IfThenElse(i0_outer_outer * 13 + i0_outer_inner < 256, stmt,
None)
- stmt = tirx.For(i0_inner, 0, 4, tirx.ForKind.VECTORIZED, stmt)
- stmt = tirx.For(i0_outer_inner, 0, 13, tirx.ForKind.PARALLEL, stmt)
- stmt = tirx.AttrStmt(
- T.iter_var(i0_outer_inner, None, "DataPar", ""),
- "pragma_parallal_barrier_when_finish",
- 1,
- stmt,
- )
- stmt = tirx.AttrStmt(
- T.iter_var(i0_outer_inner, None, "DataPar", ""),
- "pragma_parallal_stride_pattern",
- 1,
- stmt,
- )
- stmt = tirx.For(i0_outer_outer, 0, 20, tirx.ForKind.SERIAL, stmt)
- stmt = tirx.AttrStmt(
- T.iter_var(i0_outer_outer, None, "DataPar", ""),
- "pragma_parallal_launch_point",
- 1,
- stmt,
- )
-
- before = tirx.PrimFunc([A, B], stmt)
-
- mod = tvm.IRModule.from_expr(before)
- after = tvm.tirx.transform.ConvertSSA()(mod)
- tvm.ir.assert_structural_equal(after["main"], before)
-
-
def test_shared_shape_var_in_buffer_params_and_alloc_buffer():
"""Shape var shared across buffer params and AllocTensor should not be
renamed.
diff --git
a/tests/python/tirx-transform/test_tir_transform_split_host_device.py
b/tests/python/tirx-transform/test_tir_transform_split_host_device.py
index 2c90bf735e..d71439a79d 100644
--- a/tests/python/tirx-transform/test_tir_transform_split_host_device.py
+++ b/tests/python/tirx-transform/test_tir_transform_split_host_device.py
@@ -159,7 +159,7 @@ def test_device_kernel_nonzero_return_is_rejected():
def test_split_host_device_without_func_host_attribute():
"""Like test_split_host_device, but no host specified in the host's target
- The `T.attr` specifying the device still requires splitting out
+ The device scope region still requires splitting out
the kernel.
"""
diff --git a/tests/python/tirx/script/test_tirx_script_printer.py
b/tests/python/tirx/script/test_tirx_script_printer.py
index b77418b537..348512e790 100644
--- a/tests/python/tirx/script/test_tirx_script_printer.py
+++ b/tests/python/tirx/script/test_tirx_script_printer.py
@@ -204,20 +204,6 @@ for i in range(128):
)
-def test_attr_stmt():
- with IRBuilder() as ib:
- with TB.attr("pragma", "unroll", 1):
- TB.evaluate(0)
- obj = ib.get()
- _assert_print(
- obj,
- """
-with T.attr("pragma", "unroll", 1):
- T.evaluate(0)
-""",
- )
-
-
def test_assert_stmt():
with IRBuilder() as ib:
with TB.prim_func():