Skip to content

Fix loop-carried Vector losing multi-dim shape (issue #734) - #759

Merged
xudoyuan merged 2 commits into
mainfrom
fix_issue734
Jun 30, 2026
Merged

Fix loop-carried Vector losing multi-dim shape (issue #734)#759
xudoyuan merged 2 commits into
mainfrom
fix_issue734

Conversation

@xudoyuan

@xudoyuan xudoyuan commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

A Vector's multi-dim logical shape (e.g. (4,1)) lives only on the Python wrapper; the MLIR value is always a flat vector. When a Vector is carried across an scf region boundary (for/while/if), the loop-carried value is rebuilt from the bare block-argument ir.Value, and reconstruction went through the classmethod construct_from_ir_values which has no access to the exemplar instance's shape -- so it collapsed (4,1) -> (4,). The next vec_sum += vec then broadcast (4,) + (4,1) to (4,4) and aborted compilation with a vector<4xf32> vs vector<16xf32> type mismatch.

Fix: add an optional instance-level reconstruction hook Vector.reconstruct_from_ir_value(self, value) that rebuilds the wrapper around the new ir.Value while copying the exemplar's shape/dtype, and prefer it in as_dsl_value before falling back to the classmethod protocol. Other types (Numeric, Constexpr, struct, BuiltinDslType) are unaffected -- they have no such hook and keep using construct_from_ir_values. This fixes Vector carries across for/while/if at once, since they share the same reconstruction path.

Add end-to-end regression test tests/system/test_for_vector_carry_shape_e2e.py (fails pre-fix with the vector<16xf32> mismatch, passes post-fix).

close #734

Motivation

Technical Details

Test Plan

Test Result

Submission Checklist

A Vector's multi-dim logical shape (e.g. (4,1)) lives only on the Python
wrapper; the MLIR value is always a flat vector<Nxf32>. When a Vector is
carried across an scf region boundary (for/while/if), the loop-carried value
is rebuilt from the bare block-argument ir.Value, and reconstruction went
through the classmethod __construct_from_ir_values__ which has no access to
the exemplar instance's shape -- so it collapsed (4,1) -> (4,). The next
vec_sum += vec then broadcast (4,) + (4,1) to (4,4) and aborted compilation
with a vector<4xf32> vs vector<16xf32> type mismatch.

Fix: add an optional instance-level reconstruction hook
Vector.__reconstruct_from_ir_value__(self, value) that rebuilds the wrapper
around the new ir.Value while copying the exemplar's shape/dtype, and prefer
it in as_dsl_value before falling back to the classmethod protocol. Other
types (Numeric, Constexpr, struct, BuiltinDslType) are unaffected -- they have
no such hook and keep using __construct_from_ir_values__. This fixes Vector
carries across for/while/if at once, since they share the same reconstruction
path.

Add end-to-end regression test tests/system/test_for_vector_carry_shape_e2e.py
(fails pre-fix with the vector<16xf32> mismatch, passes post-fix).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@xudoyuan
xudoyuan requested a review from sjfeng1999 June 26, 2026 17:09
Replace __reconstruct_from_ir_value__ with an optional exemplar argument
threaded through __construct_from_ir_values__ and construct_from_ir_values,
so a Vector rebuilt from a bare scf block-argument ir.Value preserves its
shape/dtype. Keeps reconstruction within the DslType protocol and also fixes
the jit/kernel argument rebuild path.
@xudoyuan
xudoyuan merged commit 3552f11 into main Jun 30, 2026
13 checks passed
@xudoyuan
xudoyuan deleted the fix_issue734 branch June 30, 2026 06:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Issue]: shape of for-loop-carried vector value is changed within the loop

3 participants