Skip to content

fix(vmi): propagate layouts through integer negation - #1407

Closed
chenshengxin2026 wants to merge 1 commit into
hw-native-sys:mainfrom
chenshengxin2026:fix/issue-1373-vmi-negi-layout
Closed

chenshengxin2026 wants to merge 1 commit into
hw-native-sys:mainfrom
chenshengxin2026:fix/issue-1373-vmi-negi-layout

Conversation

@chenshengxin2026

@chenshengxin2026 chenshengxin2026 commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Summary

Root cause

The unified integer vneg lowers to pto.vmi.negi before layout assignment (ptoas_pipeline.cpp runs vmi-lower-unified-to-legacy ahead of vmi-layout-assignment), but VMINegIOp was missing from isSameLayoutOp in VMILayoutPropagation.cpp.

VMILayoutPropagator::propagateThrough is fail-open: when no transfer is registered for an op it returns success() without recording any constraint. Propagation therefore had no edge between negi's source and result, the two ports were assigned incompatible layouts independently, and the VMI verifier rejected the result:

'pto.vmi.negi' op requires all layout-assigned VMI data values to have the same layout

This also explains why the identical vnot code reported in the issue worked: VMINotOp was already in the list.

The constraint added here is exactly as strong as the op's own contract — VMINegIOp::verify() already calls verifyAllSameVRegShapeAndLayout(..., requireSameElement=true) — so it cannot over-constrain. It also restores consistency across the layout passes: VMINegIOp was already registered in VMILayoutAssignment.cpp, VMILayoutRematerialize.cpp and VMILayoutSinkMaterialization.cpp; propagation was the only one missing it.

Tests

test/lit/vmi_new/vmi_ptoas_cli_integer_vneg_layout.pto covers all six failing cases from the issue (i8 vl1/vl64/vl128, i16 vl1/vl64, i32 vl1) with two RUN lines:

  1. pto-test-opt stopping after layout assignment — the primary regression. It isolates the layout invariant from every later stage and asserts the concrete, non-contiguous layout on both negi ports (num_groups = 1, slots = 8 for the vl1 cases, contiguous, lane_stride = 2|4 for the rest), plus the full load/negi/store chain for vneg_i8_vl64. Pinning the concrete layout matters: a bare "a vneg survived" check would keep passing if a future change collapsed these cases to plain contiguous, silently retiring the coverage.
  2. ptoas --emit-vpto — proves the whole pipeline completes, guarded by --implicit-check-not so the residual-VMI check applies to the entire output rather than only the region after the last match. This run needs provably 32-byte-aligned dynamic offsets, otherwise physical read legalization fails first and masks the layout regression; the first run has no such prerequisite.

Verification:

  • both RUN lines fail on a pre-fix compiler and pass with this change; the layout-assignment run surfaces all six failures directly, whereas the end-to-end run aborts on the first one
  • test/lit/vmi_new: 553/553 pass
  • full test/lit: no related failures (the only red test locally is npu_validation/deepseek_score_inputs.test, which needs numpy, absent from the local environment)
  • built locally in Release with PTOAS_ENABLE_WERROR=ON

Note on the current CI status

vmi-source-patch-check and build-and-test are red for reasons unrelated to this change; both reproduce on other open PRs and on plain main:

  • vmi-source-patch-check: packaging/ptoas-vmi/pyproject.toml.patch no longer applies to main's pyproject.toml. Verified by applying the patch to main content directly, with no PR involved.
  • build-and-test: the "Validate strict CMake 4 configure" step errors on the deprecated FetchContent_Populate call at cmake/fetch_cann_cmake.cmake:67 under CMake 4.1.3. It fails at configure time, before anything is compiled or any test is run.

As a consequence CI has not yet exercised the new lit test; the results above are from local runs against a build carrying this fix.

Follow-up

#1458 tracks the underlying fragility this bug came from: the same-layout op set is hand-maintained in four separate lists, and layout propagation is fail-open for unregistered ops.

Fixes #1373

The unified integer negation lowers to pto.vmi.negi before layout
assignment, but VMINegIOp was missing from isSameLayoutOp in
VMILayoutPropagation.cpp. Layout propagation therefore had no transfer
for negi and silently placed no constraint between its source and
result, letting the two ports be assigned incompatible layouts. That
tripped the VMI verifier reported in issue hw-native-sys#1373:

  'pto.vmi.negi' op requires all layout-assigned VMI data values to
  have the same layout

Treat VMINegIOp as a same-layout VMI op during layout propagation. This
restores the op's own invariant -- VMINegIOp::verify() already calls
verifyAllSameVRegShapeAndLayout with requireSameElement -- so the
constraint is exactly as strong as the op requires, not stronger. It
also makes the four layout passes agree again: VMINegIOp was already
registered in VMILayoutAssignment.cpp, VMILayoutRematerialize.cpp and
VMILayoutSinkMaterialization.cpp, and propagation was the only one
missing it.

Add regression coverage for the six integer non-mask cases from the
issue (i8 vl1/vl64/vl128, i16 vl1/vl64, i32 vl1) with two RUN lines:

- A pto-test-opt run that stops right after layout assignment. This is
  the primary regression, matching the dominant convention in
  test/lit/vmi_new, and it reproduces all six failures directly rather
  than aborting on the first one. It asserts the concrete, non-
  contiguous layout on both negi ports, so the coverage cannot silently
  lapse if a future change collapses these cases to plain contiguous.

- A full ptoas --emit-vpto run proving the pipeline completes, guarded
  by --implicit-check-not so the residual-VMI check covers the whole
  output instead of only the region after the last match. This run
  needs provably 32-byte aligned dynamic offsets, otherwise physical
  read legalization fails first and masks the layout regression.

Verified against a build carrying the fix: both RUN lines fail on the
pre-fix compiler and pass after it, and test/lit/vmi_new is 553/553.
@chenshengxin2026
chenshengxin2026 force-pushed the fix/issue-1373-vmi-negi-layout branch from 199c6b8 to fa4e994 Compare September 4, 2026 01:33
@github-actions
github-actions Bot force-pushed the main branch 3 times, most recently from 4687426 to 7e2ec3e Compare September 4, 2026 10:01
@Zhendong404
Zhendong404 deleted the branch hw-native-sys:main September 5, 2026 08:52
@Zhendong404 Zhendong404 closed this Sep 5, 2026
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.

[Bug] PTODSL-vmi,vneg 整数类型用例触发 VMI layout 不一致错误

2 participants