Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions ptodsl/ptodsl/_ast_rewrite.py
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,16 @@ def _slot_live_before_block(stmts, live_after, static_env, static_iters=None) ->


def _slot_live_before_stmt(stmt, live_after, static_env, static_iters) -> set[_SubscriptSlot]:
if isinstance(stmt, (ast.With, ast.AsyncWith)):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里没有遵循 Python with item 从左到右求值、每项立即绑定 optional_vars 的语义。例如 with cm() as values, cm(values[0]): pass 中,第二项的 values[0] 不是 with 之前的 live-in,但当前实现会把它加入 context_loads,纯 AST probe 也确实返回该 slot。这可能生成未定义或多余的 loop carry。建议从 body_live 开始逆序遍历 items:先 kill 当前 optional_vars 的绑定,再加入该项 context_expr 的 loads,并覆盖 subscript 绑定目标。

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修改

context_loads = set()
bound_bases = set()
for item in stmt.items:
context_loads |= _slot_info(item.context_expr, static_env, static_iters).loads
if item.optional_vars is not None:
bound_bases |= _simple_name_targets(item.optional_vars)
body_live = _slot_live_before_block(stmt.body, live_after, static_env, static_iters)
body_live = {slot for slot in body_live if slot.base not in bound_bases}
return context_loads | body_live
if isinstance(stmt, ast.If):
test_info = _slot_info(stmt.test, static_env, static_iters)
return (
Expand Down
27 changes: 27 additions & 0 deletions ptodsl/tests/test_jit_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -2117,6 +2117,22 @@ def ast_runtime_for_static_slot_carry_probe(cols: pto.i32):
_ = total


@pto.jit(target="a5", mode="explicit")
def ast_runtime_for_static_slot_nested_vecscope_probe(cols: pto.i32):
zero = pto.const(0, dtype=pto.index)

for _ in range(cols):
with pto.vecscope():
values = [zero, zero, zero, zero]
for c in range(64):
values[0] = c
values[1] = c
values[2] = c
values[3] = c
total = values[0] + values[1] + values[2] + values[3]
_ = total


_STATIC_SLOT_GLOBAL_INDEX = 2


Expand Down Expand Up @@ -7107,6 +7123,17 @@ def _enter_inline_simt_with_resource_attr():
and "scf.yield" in ast_runtime_for_static_slot_carry_text,
"static subscript slot carry should lower through scf.for iter_args",
)
ast_runtime_for_static_slot_nested_vecscope_text = (
ast_runtime_for_static_slot_nested_vecscope_probe.compile().mlir_text()
)
expect_parse_roundtrip_and_verify(
ast_runtime_for_static_slot_nested_vecscope_text,
"AST-rewritten nested vecscope runtime for static subscript slots",
)
expect(
ast_runtime_for_static_slot_nested_vecscope_text.count("scf.for") == 2,
"nested vecscope static subscript slots should preserve both authored runtime loops",
)
ast_runtime_for_static_slot_global_index_text = ast_runtime_for_static_slot_global_index_probe.compile().mlir_text()
expect_parse_roundtrip_and_verify(
ast_runtime_for_static_slot_global_index_text,
Expand Down
Loading