Skip to content

Loop-carried ilist update inside for + if can drop previous state #614

@nkanazawa1989

Description

@nkanazawa1989

Summary

When updating a loop-carried ilist in an if body, the branch result can be lowered as a constant payload instead of prev + payload.
This changes semantics (accumulation is lost).

Environment

  • kirin-toolchain==0.22.6
  • Python 3.10.19
  • macOS 15.7.3 (arm64)

Reproducer

1) Bad pattern (can collapse accumulation)

# frontend-agnostic kernel pseudocode
@kernel
def helper_const():
    return [1]  # constant payload

@kernel
def bad(n: int):
    xs = []
    for i in range(n):
        if True:
            xs += helper_const()
    return len(xs)

print(bad(5))  # can be 1 (expected 5)

2) Good pattern (accumulates as expected)

# frontend-agnostic kernel pseudocode
@kernel
def helper_dynamic(v: int):
    return [v]  # payload depends on runtime value

@kernel
def good(n: int):
    xs = []
    v = n
    for i in range(n):
        if True:
            xs += helper_dynamic(v)
    return len(xs)

print(good(5))  # 5

Expected behavior

  • bad(5) should return 5.
  • good(5) should return 5.
  • Semantics should be equivalent to repeated xs = xs + payload in both cases.

Actual behavior

  • bad(5) can return 1.
  • good(5) returns 5.

Why this is a bug (not expected phi/merge behavior)

In SSA/control-flow terms, the branch should compute:

xs_then = xs_prev + const_payload

but observed behavior corresponds to:

xs_then = const_payload

This bypasses loop-carried state (xs_prev) and changes program meaning.

IR evidence

Observed risky shape in branch block:

^1(%i, %xs_2):
│ %xs_1 = py.constant.constant IList([1]) : ...

Expected shape:

^1(%i, %xs_2):
│ %tmp = py.constant.constant IList([1]) : ...
│ %xs_1 = py.binop.add(%xs_2, %tmp) : ...

Notes

  • This appears in for + if with loop-carried ilist updates when payload is (or is specialized into) a constant/literal list.
  • Non-literal/runtime-dependent payloads often keep correct py.binop.add form.
  • Reproduced through a Kirin-based kernel frontend; issue appears in Kirin IR semantics/optimization shape, not frontend-specific syntax.

Request

Please investigate lowering/optimization around branch outputs for loop-carried values in for + if control flow.

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions