Skip to content

fix(ir): forbid tile.move in-place reuse (root fix for #2100), revert #2100 workarounds - #2106

Open
YunjiQin wants to merge 3 commits into
hw-native-sys:mainfrom
YunjiQin:fix/forbid-tile-move-input-reuse
Open

fix(ir): forbid tile.move in-place reuse (root fix for #2100), revert #2100 workarounds#2106
YunjiQin wants to merge 3 commits into
hw-native-sys:mainfrom
YunjiQin:fix/forbid-tile-move-input-reuse

Conversation

@YunjiQin

@YunjiQin YunjiQin commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

Root-cause fix for the A5 V→C miscompile that #2100 worked around, plus removal of the now-redundant workarounds.

The TMOV intrinsic cannot execute with src == dst — a same-address move is not a legal instruction, only a no-op. tile.move was defaulting to in-place-safe, which let MemoryReuse colocate a same-space layout-changing move (the A5 V→C ND→NZ fractal adapt) with its source at one Vec address. Codegen then saw matching src/dst addresses and elided the pto.tmov as a no-op, silently dropping the layout adapt (RowMajor TPUSH vs ColMajor TPOP) → silent numerical FAIL.

Marking tile.move .not_inplace_safe() forbids that colocation at the op level, so src and dst always get distinct buffers. This removes the same-address precondition entirely, rather than tolerating it and special-casing the symptom downstream.

Commits

  1. revert(codegen/ir): drop #2100 layout-aware elide and Vec-only reuse gate — revert a90f1584 (fix(codegen/ir): keep layout-aware tmov elide; Vec-only ND↔NZ reuse gate #2100): the codegen same_layout guard on tile.move elision and the AreVecNdNzCompatible Vec-only ND↔NZ reuse gate in MemoryReuse. Both are workarounds superseded by the root fix below.
  2. fix(ir): forbid tile.move output from reusing its input buffer — mark tile.move .not_inplace_safe(); add a regression test asserting a same-space tile.move output gets a buffer distinct from its input.
  3. refactor(codegen): drop same-address tmov elision for tile.move — with the move output never on its input buffer, the same-space same-address elision can never fire under baked addresses; remove that dead branch (and now-unused includes). tile.move always emits pto.tmov on the baked-address path.

Why this supersedes #2100

  • fix(codegen/ir): keep layout-aware tmov elide; Vec-only ND↔NZ reuse gate #2100 kept the illegal same-address colocation legal and (a) taught codegen to keep pto.tmov when blayout/slayout/fractal differ and (b) added a Vec-only ND↔NZ reuse gate. Both special-case the symptom.
  • This PR eliminates the illegal colocation at its source, so neither special-case is needed — a same-address tile.move never reaches codegen.

No collateral cost

Through the current Default pipeline, legitimate same-space same-layout no-op moves are not produced: loop-carry buffers are converged onto one base by MaterializeSemanticAliases / AlignLoopCarriesToInit via in-place retyping, not by inserting a move. Empirically, the same-address codegen elision is never hit by any tests/ut/codegen test even on main (0 hits across the suite). Cross-space moves (Mat→Left, etc.) live in different base-groups and are unaffected. The narrow not_inplace_safe flag does not touch the reuse packer's coalescing of unrelated lifetime-disjoint L0A tiles, so the split-K Left capacity path is unchanged.

PtoAS path is preserved: under memory_planner=PtoAS the reuse gate is skipped and a YieldFixup loop-carry write-back can still collapse onto one tile_buf handle, so the handle-based elision (!EmitTileAddr() branch) is intentionally kept to avoid emitting an illegal same-handle pto.tmov.

Testing

  • tests/ut/ir/transforms/test_memory_reuse.py + tests/ut/codegen/test_pto_codegen_ops.py — 155 passed (incl. new test and the acc→acc regressions)
  • tests/ut/ir/transforms/ + tests/ut/codegen/ — 2850 passed (no reuse / L0 capacity regression)
  • clang-tidy clean; pre-commit (cpplint / clang-format / ruff / pyright) clean

Related

Root-cause fix for the issue addressed by #2100; reverts #2100's workarounds.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: eb874334-a6e4-41d3-a462-6e47eec9f879

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

tile.move is marked as not inplace safe to prevent invalid same-address or same-buffer reuse. A memory-reuse unit test verifies that the moved output receives a different buffer base from its input.

Changes

tile.move aliasing

Layer / File(s) Summary
Move safety contract and validation
src/ir/op/tile_ops/memory.cpp, tests/ut/ir/transforms/test_memory_reuse.py
tile.move disallows inplace-safe reuse, and a unit test asserts that its output buffer does not alias the input buffer.

Estimated code review effort: 2 (Simple) | ~5 minutes

Possibly related PRs

  • hw-native-sys/pypto#2100: Adjusts tile.move handling for layout-sensitive no-op elision and storage-layout compatibility.

Poem

A bunny hops where buffers part,
No tile shall share its neighbor’s start.
TMOV now keeps its space in line,
While tests make aliasing decline.
“Hop, hop!” says Bun—the move is fine!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: preventing tile.move in-place reuse and reverting related workarounds.
Description check ✅ Passed The description is directly about the tile.move aliasing fix and the removed workarounds, so it matches the changeset.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 12a8fc89e3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/ir/op/tile_ops/memory.cpp
@YunjiQin
YunjiQin force-pushed the fix/forbid-tile-move-input-reuse branch from 12a8fc8 to 8f00ac1 Compare July 22, 2026 10:26
@YunjiQin YunjiQin changed the title fix(ir): forbid tile.move output from reusing its input buffer fix(ir): forbid tile.move in-place reuse (root fix for #2100), revert #2100 workarounds Jul 22, 2026
@YunjiQin
YunjiQin force-pushed the fix/forbid-tile-move-input-reuse branch from 8f00ac1 to 0560adf Compare July 23, 2026 01:07
YunjiQin added 3 commits July 22, 2026 18:07
…c-only reuse gate

Revert the two workarounds from hw-native-sys#2100 (a90f158): the codegen same_layout
guard on tile.move elision and the AreVecNdNzCompatible Vec-only ND<->NZ
reuse gate in MemoryReuse. Both are superseded by marking tile.move
.not_inplace_safe(): forbidding the move output from reusing its input
buffer prevents the same-address ND->NZ colocation at its source, so
neither the layout-aware elision special-case nor the per-layout reuse
gate is needed.
Mark tile.move .not_inplace_safe() so MemoryReuse never lands the move
output on its input's buffer. The TMOV intrinsic cannot execute with
src == dst (a same-address move is not a legal instruction, only a
no-op), so a same-space layout-changing move (e.g. the A5 V->C ND->NZ
fractal adapt) colocated with its source would be seen by codegen as a
same-address no-op and wrongly elided, dropping the layout adapt.

Add a regression test asserting a same-space tile.move output gets a
buffer distinct from its input.
With tile.move marked .not_inplace_safe(), MemoryReuse can no longer
place a move output on its input buffer, so under baked addresses src and
dst are always distinct — the same-space same-address elision can never
fire. Remove that dead baked-address branch (and its now-unused includes);
tile.move always emits pto.tmov on the baked-address path.

The PtoAS branch is unchanged: under memory_planner=PtoAS the reuse gate
is skipped and a YieldFixup loop-carry write-back can still collapse onto
one tile_buf handle, so the handle-based elision stays to avoid emitting
an illegal same-handle pto.tmov.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant