Skip to content

fix(pass): preserve singleton broadcast dims in SplitVectorKernel#984

Merged
Hzfengsy merged 2 commits intohw-native-sys:mainfrom
lyfne123:issue-976-fix-singleton-broadcast-split
Apr 13, 2026
Merged

fix(pass): preserve singleton broadcast dims in SplitVectorKernel#984
Hzfengsy merged 2 commits intohw-native-sys:mainfrom
lyfne123:issue-976-fix-singleton-broadcast-split

Conversation

@lyfne123
Copy link
Copy Markdown
Collaborator

Summary

  • Redesign the split decision algorithm in SplitVectorKernel to be op-semantics-aware instead of unconditionally halving all tile dimensions on the split axis
  • Add IsSingletonDim check: tiles with split-axis extent == 1 (e.g. broadcast [1, 128] under UP_DOWN) are preserved as-is without halving, offset adjustment, or tile tracking
  • Add IsReduceOnSplitAxis detection: reduce ops (tile.sum/max/min, tile.row_sum/max/min) that reduce on the split axis are rejected with a clear error since partial reduction is semantically incorrect
  • Add regression tests for UP_DOWN and LEFT_RIGHT singleton broadcast scenarios, plus a reduce-on-split-axis rejection test

Fixes #976
Closes #975

Test plan

  • All 15 test_split_vector_kernel.py tests pass (12 existing + 3 new)
  • All 980 tests/ut/ir/transforms/ tests pass with no regressions
  • Pre-commit hooks pass (clang-format, cpplint, ruff, pyright)

Made with Cursor

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 13, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Preserve singleton split-axis dimensions for broadcast tiles in SplitVectorKernel and add predicates to detect singleton dims and reductions on the split axis. Halving/offset adjustments are skipped for singleton split dims, and reductions that target the split axis are rejected.

Changes

Cohort / File(s) Summary
SplitVectorKernel AIV Handling
src/ir/transforms/split_vector_kernel_pass.cpp
Added IsSingletonDim and IsReduceOnSplitAxis predicates. When an AIV tile's split-axis extent equals 1, skip halving of result type/shape and of shape/valid_shape tuple elements and leave the statement unchanged. For generic Tile-producing ops, throw on reductions that reduce along the split axis and skip halving for singleton split dims.
Regression & Feature Tests
tests/ut/ir/transforms/test_split_vector_kernel.py
Added tests: test_singleton_broadcast_tile_preserved (UP_DOWN [1,128] preserved), test_reduce_on_split_axis_rejected (reduction on split axis raises), and test_singleton_broadcast_tile_preserved_left_right (LEFT_RIGHT [16,1] preserved).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hopped through tiles both wide and thin,
Found a lonely dim of one, tucked in.
I left it whole, no halve, no fight,
Now broadcasts beam in split-mode light. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(pass): preserve singleton broadcast dims in SplitVectorKernel' directly describes the main change: fixing the SplitVectorKernel pass to preserve singleton dimensions instead of unconditionally halving them.
Description check ✅ Passed The description clearly explains the problem, solution approach, and test coverage. It details the algorithm redesign, new helper predicates, rejection of invalid reductions, and test plan with passing results.
Linked Issues check ✅ Passed The PR implementation fully addresses both linked issues: #976 and #975. The code changes preserve singleton dimensions [#976, #975], add IsReduceOnSplitAxis detection to reject invalid reductions [#976], and include three regression tests covering UP_DOWN, LEFT_RIGHT, and reduce-on-split-axis scenarios [#976].
Out of Scope Changes check ✅ Passed All changes are directly scoped to the linked issues: modifications to SplitVectorKernel pass logic for singleton dimension preservation, helper predicates for validation, and comprehensive regression tests. No unrelated changes detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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 and usage tips.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request enhances the split_vector_kernel_pass by adding logic to handle singleton dimensions and prevent invalid reductions on the split axis. It introduces helper functions IsSingletonDim and IsReduceOnSplitAxis to ensure that singleton tiles are preserved during splitting and that unsupported partial reductions trigger a ValueError. Corresponding unit tests have been added to verify these cases. Review feedback recommends optimizing performance by using GetKind() for type checking and removing a redundant cast in the IsReduceOnSplitAxis function.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/ut/ir/transforms/test_split_vector_kernel.py (1)

447-466: Please add one row-reduction regression too.

The C++ change has a separate tile.row_sum/max/min branch, but this file only exercises the generic pl.sum(axis=0) path. One LEFT_RIGHT row-reduction case would lock down that branch as well.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/ut/ir/transforms/test_split_vector_kernel.py` around lines 447 - 466,
Add a second test that mirrors test_reduce_on_split_axis_rejected but exercises
the LEFT_RIGHT split and a row-reduction: create a new test (e.g.,
test_reduce_on_split_axis_rejected_row) that defines a Before program with
`@pl.function`(..., attrs={"split": pl.SplitMode.LEFT_RIGHT}) and loads a Tile
like in the original test, then calls pl.sum(prev, axis=1, keepdim=True) (row
reduction) and asserts it raises with the same "reduces on the split axis"
message by calling _run_split_vector_kernel(Before).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/ir/transforms/split_vector_kernel_pass.cpp`:
- Around line 325-334: The early return in split_vector_kernel_pass.cpp that
bypasses split tracking for singleton-result tiles (when is_aiv && op_name ==
"tile.load" and IsSingletonDim on TileType) is too permissive; update the check
so only proven broadcast-safe ops are exempt (e.g., explicitly allow known
broadcast-only ops) or conservatively reject ambiguous singleton-result cases so
tile_vars still track offsets; concretely, in the tile.load / tile.slice
handling replace the unconditional is_singleton return with a predicate that
verifies the op is in a whitelist of broadcast-safe ops or that the source is
split-invariant, and ensure the same change is applied to the analogous
early-return branch later (the one referencing tile.slice/tile.store and
tile_vars tracking).

---

Nitpick comments:
In `@tests/ut/ir/transforms/test_split_vector_kernel.py`:
- Around line 447-466: Add a second test that mirrors
test_reduce_on_split_axis_rejected but exercises the LEFT_RIGHT split and a
row-reduction: create a new test (e.g., test_reduce_on_split_axis_rejected_row)
that defines a Before program with `@pl.function`(..., attrs={"split":
pl.SplitMode.LEFT_RIGHT}) and loads a Tile like in the original test, then calls
pl.sum(prev, axis=1, keepdim=True) (row reduction) and asserts it raises with
the same "reduces on the split axis" message by calling
_run_split_vector_kernel(Before).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 6d371d74-94ef-4338-935c-5ceaee3b9ab2

📥 Commits

Reviewing files that changed from the base of the PR and between 460d257 and cd66135.

📒 Files selected for processing (2)
  • src/ir/transforms/split_vector_kernel_pass.cpp
  • tests/ut/ir/transforms/test_split_vector_kernel.py

Redesign the split decision algorithm in SplitVectorKernel to be
op-semantics-aware instead of unconditionally halving all tile dims:

- Add IsSingletonDim check: tiles with split-axis extent == 1 (e.g.
  broadcast [1, 128] under UP_DOWN) are now preserved as-is without
  halving shape, adjusting offsets, or tracking in tile_vars
- Add IsReduceOnSplitAxis detection: reduce ops (tile.sum/max/min,
  tile.row_sum/max/min) that reduce on the split axis are rejected
  with a clear error, since partial reduction is semantically incorrect
- Add regression tests for both UP_DOWN and LEFT_RIGHT singleton
  broadcast scenarios, plus a reduce-on-split-axis rejection test

Fixes hw-native-sys#976
Closes hw-native-sys#975

Made-with: Cursor
@lyfne123 lyfne123 force-pushed the issue-976-fix-singleton-broadcast-split branch from cd66135 to 5b7d946 Compare April 13, 2026 03:42
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
src/ir/transforms/split_vector_kernel_pass.cpp (1)

325-334: ⚠️ Potential issue | 🟠 Major

Don’t treat every singleton split-axis tile as split-invariant.

These early returns still skip split rewriting for any [1, N] / [M, 1] producer. A non-broadcast singleton tile.load or singleton-result op such as tile.slice can now bypass offset rewriting and tile_vars tracking, so later stores may duplicate the same row/column from both lanes. Preserve only proven broadcast-safe cases, or reject ambiguous singleton producers instead of returning the original stmt.

Based on learnings, tile.slice is already emitted in this IR in src/ir/transforms/flatten_tile_nd_to_2d_pass.cpp, so singleton-result tiles are not broadcast-only by construction.

Also applies to: 377-391

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ir/transforms/split_vector_kernel_pass.cpp` around lines 325 - 334, The
early-return that preserves singleton split-dim tiles (in the is_aiv && op_name
== "tile.load" branch using TileType, split_dim and IsSingletonDim) is too
permissive and skips necessary offset rewriting and tile_vars tracking; instead,
change the logic to only bypass rewriting for proven broadcast cases (e.g.,
detect explicit broadcast/stride metadata or inspect the call's
shape/valid_shape args to confirm the singleton is a broadcast source), and
otherwise do not return early—allow the existing tile.load/tile.slice rewrite
path to apply or explicitly reject/raise for ambiguous singleton producers so
stores don't duplicate rows/columns; apply the same fix to the analogous block
around lines 377-391.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/ir/transforms/split_vector_kernel_pass.cpp`:
- Around line 133-147: In IsReduceOnSplitAxis, tile.row_sum/row_max/row_min
should check the input tile's last axis instead of hardcoding split_dim == 1;
obtain the input TileType (like the tile.sum branch does) from
call->args_[0]->GetType(), compute last_axis = tt ?
static_cast<int>(tt->shape_.size()) - 1 : 1 (or bail if tt is null), and return
last_axis == split_dim; update the tile.row_* branch in IsReduceOnSplitAxis to
use that last-axis comparison so rank>2 tiles are handled correctly.

In `@tests/ut/ir/transforms/test_split_vector_kernel.py`:
- Around line 465-466: The test currently uses pytest.raises(Exception,
match="reduces on the split axis") which is too broad; update the assertion to
expect the specific exception type (e.g. ValueError or the project-specific
pypto exception) by changing the pytest.raises call around
_run_split_vector_kernel(Before) to pytest.raises(ValueError, match="reduces on
the split axis") (or the named pypto exception) so the test only passes when the
split-axis reduction check fails in _run_split_vector_kernel.

---

Duplicate comments:
In `@src/ir/transforms/split_vector_kernel_pass.cpp`:
- Around line 325-334: The early-return that preserves singleton split-dim tiles
(in the is_aiv && op_name == "tile.load" branch using TileType, split_dim and
IsSingletonDim) is too permissive and skips necessary offset rewriting and
tile_vars tracking; instead, change the logic to only bypass rewriting for
proven broadcast cases (e.g., detect explicit broadcast/stride metadata or
inspect the call's shape/valid_shape args to confirm the singleton is a
broadcast source), and otherwise do not return early—allow the existing
tile.load/tile.slice rewrite path to apply or explicitly reject/raise for
ambiguous singleton producers so stores don't duplicate rows/columns; apply the
same fix to the analogous block around lines 377-391.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 51d839b8-6294-4df8-8543-ebcc6babaa93

📥 Commits

Reviewing files that changed from the base of the PR and between cd66135 and 5b7d946.

📒 Files selected for processing (2)
  • src/ir/transforms/split_vector_kernel_pass.cpp
  • tests/ut/ir/transforms/test_split_vector_kernel.py

- Remove redundant dynamic_pointer_cast<Call> in IsReduceOnSplitAxis;
  extract input_tile_type lambda to avoid repetition
- Fix tile.row_* reduce detection to use last axis of input tile
  instead of hardcoded dim 1, supporting rank>2 tiles
- Narrow pytest.raises(Exception) to pytest.raises(ValueError) for
  more targeted reduce-on-split-axis rejection test

Made-with: Cursor
@Hzfengsy Hzfengsy merged commit 8c20f15 into hw-native-sys:main Apr 13, 2026
8 checks passed
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.

[Pass Bug]SplitVectorKernel fails on singleton broadcast tile loads in split AIV kernels

2 participants