Skip to content

Commit a6c7377

Browse files
authored
[REFACTOR][TIRx] Keep AttrStmt node values unboxed (#20030)
AttrStmt.node is an ffi::Any field, so converting POD arguments to PrimExpr makes its representation depend on the caller rather than the declared container type. This change preserves values passed through AttrStmt and T.attr, uses raw zero sentinel nodes consistently, and updates the printer canonicalization.
1 parent a82b34d commit a6c7377

12 files changed

Lines changed: 22 additions & 41 deletions

File tree

python/tvm/tirx/script/builder/ir.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1582,7 +1582,7 @@ def attr(
15821582
with T.attr(node, key, value):
15831583
...
15841584
1585-
Usage 2 — dict sugar (node defaults to ``T.int32(0)``)::
1585+
Usage 2 — dict sugar (node defaults to ``0``)::
15861586
15871587
with T.attr({"key1": value1, "key2": value2}):
15881588
...
@@ -1591,7 +1591,7 @@ def attr(
15911591
----------
15921592
node_or_dict : Any
15931593
If a dict, each key-value pair becomes an AttrStmt with
1594-
``node=T.int32(0)``. Otherwise the node to annotate.
1594+
``node=0``. Otherwise the node to annotate.
15951595
15961596
attr_key : str, optional
15971597
Attribute type key (required when ``node_or_dict`` is not a dict).
@@ -1609,11 +1609,7 @@ def attr(
16091609
for k, v in node_or_dict.items():
16101610
if isinstance(v, bool):
16111611
v = IntImm("bool", v)
1612-
frames.append(
1613-
_ffi_api.Attr( # type: ignore[attr-defined]
1614-
convert(IntImm("int32", 0)), k, convert(v)
1615-
)
1616-
)
1612+
frames.append(_ffi_api.Attr(0, k, convert(v))) # type: ignore[attr-defined]
16171613
if len(frames) == 1:
16181614
return frames[0]
16191615
return utils._FrameScope(frames)

python/tvm/tirx/script/builder/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ def seq_scope():
108108
T.evaluate(j)
109109
result = ib.get()
110110
"""
111-
return T.attr(tirx.const(0, "int32"), "pragma_scope", tirx.StringImm("seq"))
111+
return T.attr(0, "pragma_scope", tirx.StringImm("seq"))
112112

113113

114114
def _unravel_index(index, shape):

python/tvm/tirx/stmt.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ class AttrStmt(Stmt):
491491
492492
Parameters
493493
----------
494-
node : Object
494+
node : Any
495495
The node to annotate the attribute
496496
497497
attr_key : str
@@ -507,14 +507,14 @@ class AttrStmt(Stmt):
507507
The location of the stmt in the source code.
508508
"""
509509

510-
node: Object
510+
node: Any
511511
attr_key: str
512512
value: Expr
513513
body: Stmt
514514
span: Span | None
515515

516516
def __init__(
517-
self, node: Object, attr_key: str, value: Expr, body: Stmt, span: Span | None = None
517+
self, node: Any, attr_key: str, value: Expr, body: Stmt, span: Span | None = None
518518
) -> None:
519519
body = _normalize_legacy_stmt(body)
520520
self.__init_handle_by_constructor__(

src/s_tir/transform/decorate_device_scope.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ namespace s_tir {
3131
using namespace tvm::tirx;
3232

3333
Stmt DecorateDeviceScopeImpl(Stmt&& stmt) {
34-
Stmt body = AttrStmt(IntImm::Int32(0), tirx::attr::device_scope, 0, stmt);
34+
Stmt body = AttrStmt(0, tirx::attr::device_scope, 0, stmt);
3535
return body;
3636
}
3737

src/s_tir/transform/inject_software_pipeline.cc

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -758,10 +758,9 @@ class PipelineRewriter : public StmtExprMutator {
758758
auto attach_wait_scope = [&new_blocks](int i, int stage_id, PrimExpr wait_count) {
759759
auto& block = new_blocks[i].block;
760760
SBlockNode* n = block.CopyOnWrite();
761-
auto zero = IntImm::Int32(0);
762761
n->body =
763-
AttrStmt(zero, s_tir::attr::async_wait_queue_scope, stage_id,
764-
AttrStmt(zero, s_tir::attr::async_wait_inflight_count, wait_count, n->body));
762+
AttrStmt(0, s_tir::attr::async_wait_queue_scope, stage_id,
763+
AttrStmt(0, s_tir::attr::async_wait_inflight_count, wait_count, n->body));
765764
};
766765

767766
if (state.predicate && !ana_normalized->CanProve(state.predicate.value())) {
@@ -805,7 +804,7 @@ class PipelineRewriter : public StmtExprMutator {
805804

806805
for (auto body : group_bodies) {
807806
auto commit_queue_scope =
808-
AttrStmt(IntImm::Int32(0), s_tir::attr::async_commit_queue_scope, stage_id, body);
807+
AttrStmt(0, s_tir::attr::async_commit_queue_scope, stage_id, body);
809808
auto new_block = MakeSBlock(commit_queue_scope, buffer_data_to_buffer_);
810809
stmts.push_back(SBlockRealize({}, predicate, new_block));
811810
}
@@ -925,7 +924,7 @@ class PipelineRewriter : public StmtExprMutator {
925924
}
926925

927926
SBlockNode* n = new_block.CopyOnWrite();
928-
n->body = AttrStmt(IntImm::Int32(0), s_tir::attr::async_scope, 1, n->body);
927+
n->body = AttrStmt(0, s_tir::attr::async_scope, 1, n->body);
929928
}
930929

931930
new_blocks.push_back(

src/s_tir/transform/lower_opaque_block.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ class OpaqueBlockLower : public StmtExprMutator {
8080
std::vector<std::pair<std::string, PrimExpr>> pragma_attrs;
8181
HandleAnnotations(new_block->annotations, &pragma_attrs, /*is_block=*/true);
8282
for (auto it = pragma_attrs.rbegin(); it != pragma_attrs.rend(); ++it) {
83-
body = AttrStmt(IntImm::Int32(0), it->first, it->second, std::move(body));
83+
body = AttrStmt(0, it->first, it->second, std::move(body));
8484
}
8585
return body;
8686
}

src/s_tir/transform/thread_storage_sync.cc

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -298,11 +298,9 @@ class ThreadSyncAfterWaitQueueInserter : public StmtExprMutator {
298298
.as_or_throw<PrimExpr>());
299299
auto inner = op->body.as<AttrStmtNode>();
300300
TVM_FFI_ICHECK(inner && inner->attr_key == s_tir::attr::async_wait_inflight_count);
301-
auto zero = IntImm::Int32(0);
302301
auto new_body = SeqStmt({sync, inner->body});
303-
return AttrStmt(
304-
zero, s_tir::attr::async_wait_queue_scope, op->value,
305-
AttrStmt(zero, s_tir::attr::async_wait_inflight_count, inner->value, new_body));
302+
return AttrStmt(0, s_tir::attr::async_wait_queue_scope, op->value,
303+
AttrStmt(0, s_tir::attr::async_wait_inflight_count, inner->value, new_body));
306304
}
307305
return StmtExprMutator::VisitStmt_(op);
308306
}

src/tirx/ir/stmt.cc

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,6 @@ TVM_FFI_STATIC_INIT_BLOCK() {
9191
namespace refl = tvm::ffi::reflection;
9292
refl::GlobalDef().def("tirx.AttrStmt",
9393
[](Any node, ffi::String attr_key, PrimExpr value, Stmt body, Span span) {
94-
// when node is a POD data type like int or bool, first convert to
95-
// primexpr.
96-
if (node.type_index() < ffi::TypeIndex::kTVMFFISmallStr) {
97-
return AttrStmt(node.cast<PrimExpr>(), attr_key, value, body, span);
98-
}
9994
return AttrStmt(node, attr_key, value, body, span);
10095
});
10196
}

src/tirx/script/builder/ir.cc

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -644,10 +644,6 @@ LaunchThreadFrame LaunchThread(ffi::String thread_tag, PrimExpr extent) {
644644
}
645645

646646
AttrFrame Attr(ffi::Any node, ffi::String attr_key, PrimExpr value) {
647-
// convert POD value to PrimExpr
648-
if (node.type_index() < ffi::TypeIndex::kTVMFFISmallStr) {
649-
node = node.cast<PrimExpr>();
650-
}
651647
ffi::ObjectPtr<AttrFrameNode> n = ffi::make_object<AttrFrameNode>();
652648
n->node = std::move(node);
653649
n->attr_key = attr_key;
@@ -664,8 +660,7 @@ AttrFrame DeviceEntry() {
664660
// enclosing PrimFuncFrame: ``IRBuilderFrameNode::ExitWithScope`` runs
665661
// callbacks before popping itself, so the AttrFrame is closed and its
666662
// emitted ``AttrStmt`` lands in the PrimFunc's body sequence.
667-
AttrFrame frame =
668-
Attr(IntImm::Int32(0), ffi::String(tvm::tirx::attr::kDeviceEntry), IntImm::Bool(true));
663+
AttrFrame frame = Attr(0, ffi::String(tvm::tirx::attr::kDeviceEntry), IntImm::Bool(true));
669664
IRBuilder builder = IRBuilder::Current();
670665
ffi::Optional<PrimFuncFrame> pf_frame = builder->FindFrame<PrimFuncFrame>();
671666
TVM_FFI_ICHECK(pf_frame.has_value())

src/tirx/script/printer/stmt.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -796,10 +796,10 @@ ExprDoc DocsifyLaunchThread(const tirx::AttrStmt& attr_stmt, const AccessPath& a
796796
});
797797
}
798798

799-
/*! \brief Check whether an AttrStmt has node=IntImm(int32, 0) (the dict-attr pattern). */
799+
/*! \brief Check whether an AttrStmt has node=0 (the dict-attr pattern). */
800800
static bool IsDictAttrPattern(const tirx::AttrStmt& stmt) {
801-
if (auto int_imm = stmt->node.as<IntImmNode>()) {
802-
return int_imm->ty.as_or_throw<PrimType>() == PrimType::Int(32) && int_imm->value == 0;
801+
if (auto int_value = stmt->node.as<int64_t>()) {
802+
return int_value.value() == 0;
803803
}
804804
return false;
805805
}

0 commit comments

Comments
 (0)