Skip to content

feat(vpto): add VPTOSoftPostUpdate pass#962

Merged
zhangstevenunity merged 11 commits into
hw-native-sys:mainfrom
yexiaosu:vmi-post-update
Jul 23, 2026
Merged

feat(vpto): add VPTOSoftPostUpdate pass#962
zhangstevenunity merged 11 commits into
hw-native-sys:mainfrom
yexiaosu:vmi-post-update

Conversation

@yexiaosu

Copy link
Copy Markdown
Contributor

first step of #941

Summary

Add a new MLIR-level pass VPTOSoftPostUpdate that converts non-post-update VPTO memory operations (pto.vlds, pto.vsts, pto.vsstb) inside scf.for loops into post-update form, where the base pointer is automatically advanced and carried through iter_args.

This replaces the need for bisheng's LLVM IR-level hiipu-vf-soft-postupdate pass for these operations, with several advantages:

  • Directly pattern-matches scf.for structure instead of reconstructing loops via LoopInfo + SCEV
  • Preserves PTO pointer semantics (element-unit offsets, explicit types) instead of reverse-engineering from byte arithmetic
  • Covers AIV software loops that bisheng explicitly excludes

What it does

Before:

scf.for %iv = %c0 to %N step %c64 iter_args(...) {
  %vec = pto.vlds %base[%iv] : !pto.ptr<f32, ub> -> !pto.vreg<64xf32>
}

After:

scf.for %iv = %c0 to %N step %c64 iter_args(..., %ptr = %base) {
  %vec, %new_ptr = pto.vlds %ptr[%c64] : !pto.ptr<f32, ub>
      -> !pto.vreg<64xf32>, !pto.ptr<f32, ub>
  scf.yield ..., %new_ptr
}

Pipeline position

VPTOExpandWrapperOps → CSE → VPTOSoftPostUpdate (new) → PTOInferVPTOVecScope → ...

Testing

ninja -C build ptoas
llvm-lit -v build/test/lit --filter 'soft_postupdate'
llvm-lit -v build/test/lit --filter 'vlds|vsts|vsstb|insert_sync|vecscope'

# A5 SIM validation — following existing cases exercising post-update transformation on realistic kernels
ptoas --pto-arch=a5 --pto-backend=vpto --emit-vpto test/vpto/cases/micro-op/vector-load-store/vlds-brc-b32/kernel.pto -o /tmp/vlds-brc-b32.vpto
ptoas --pto-arch=a5 --pto-backend=vpto --emit-vpto test/vpto/cases/micro-op/vector-load-store/issue-173-vsts-signed-signless/kernel.pto -o /tmp/issue-173.vpto
ptoas --pto-arch=a5 --pto-backend=vpto --emit-vpto test/vpto/cases/micro-op/vector-load-store/vsts-packed-dist-mask-granularity/kernel.pto -o /tmp/vsts-packed.vpto
ptoas --pto-arch=a5 --pto-backend=vpto --emit-vpto test/vpto/cases/micro-op/vector-load-store/vlds-brc-b16/kernel.pto -o /tmp/vlds-brc-b16.vpto
ptoas --pto-arch=a5 --pto-backend=vpto --emit-vpto test/vpto/cases/micro-op/vector-load-store/vlds-unpk-b16/kernel.pto -o /tmp/vlds-unpk-b16.vpto
ptoas --pto-arch=a5 --pto-backend=vpto --emit-vpto test/vpto/cases/micro-op/vector-load-store/vlds-post-update/kernel.pto -o /tmp/vlds-post-update.vpto
# Above cases built + run on A5 SIM via run_host_vpto_validation_parallel.sh, all PASS

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

Copy link
Copy Markdown
Contributor

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 introduces the VPTOSoftPostUpdate pass, which optimizes fixed-stride VPTO memory operations (vlds, vsts, vsstb) inside scf.for loops by converting them to post-update form. Feedback on the implementation highlights several critical and high-severity issues: a bug where the IRMapping is not updated after replacing cloned operations, leading to dangling pointers; an optimization miss where unmodified loop-carried arguments are not recognized as having a delta of 0; and an invalid cast from index to index when the stride operand is already of index type. Additionally, the reviewer suggests querying the original operand type instead of hardcoding a 16-bit width for strideNew, avoiding IR pollution with helper operations during aborted analysis, and deduplicating initial pointer creation to prevent redundant instructions.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread lib/PTO/Transforms/VPTOSoftPostUpdate.cpp Outdated
Comment thread lib/PTO/Transforms/VPTOSoftPostUpdate.cpp
Comment thread lib/PTO/Transforms/VPTOSoftPostUpdate.cpp
Comment thread lib/PTO/Transforms/VPTOSoftPostUpdate.cpp Outdated
Comment thread lib/PTO/Transforms/VPTOSoftPostUpdate.cpp
Comment thread lib/PTO/Transforms/VPTOSoftPostUpdate.cpp
yexiaosu added 9 commits July 21, 2026 14:40
Add a new MLIR-level pass that converts non-post-update VPTO memory
operations (vlds, vsts) into their post-update equivalents inside
scf.for loops. The pass uses delta analysis to compute per-iteration
address stride and rewrites the loop to carry the base pointer through
iter_args.

- Add pass declaration, CLI flag --enable-vpto-soft-postupdate
- Integrate into prepareVPTOForEmission pipeline
- Add design document and lit tests
Same-base ops must not chain pointers because they access the same
address within a single iteration. Chaining would shift the second
op's address by one stride.

- Remove baseGroups logic; give each rewrite its own iter_arg
- Update design doc 4.2.5 to reflect the correct behavior
- Strengthen loop-multi-op-same-base.pto CHECK lines

docs: fix legality check numbering in design doc (1,2,4 -> 1,2,3)

refactor(vpto): share iter_arg for same-base same-stride ops

Group rewrites by (base, stride) so that ops accessing the same address
share one iter_arg instead of creating redundant copies. All ops in a
group use the pre-update pointer (block arg); only one updated_base per
group is yielded. Reduces register pressure without chaining.
The entire loop body is cloned into the new ForOp, so offset
computations are preserved for all users. Extra uses of the offset
do not affect correctness — they continue to see the correct value
in the cloned body. The check was rejecting valid candidates, e.g.
two ops sharing the same offset expression.
- Add CHECK for vsts post-update in delta-iv-vlds.pto
- Remove negative-extra-use.pto from design doc (hasNoExtraUses was
  removed, extra uses no longer block transformation)

cleanup: replace make_early_inc_range with plain iteration

Candidate collection does not modify the loop body; the early-increment
iterator is unnecessary and misleading.
Post-update loads/stores from the pointer directly (offset is repurposed
as stride), so the initial iter_arg must equal the first iteration's
effective address. Previously the code used the raw base pointer, which
is only correct when the offset at iter 0 is zero.

Add materializeAtLoopEntry() to evaluate the offset expression at the
loop's lower bound, and computeInitialPtr() to create base + offset via
pto.addptr. Add delta-nonzero-lb.pto test where IV starts at 64.
Add block-stride instruction (vsstb) handling in the delta path and
refactor op-specific logic into a table-driven lookup.

Also move lit tests from test/lit/vpto-soft-postupdate/ to
test/lit/vpto/ per project convention.
- Add full DMA boilerplate to delta-scaled-offset, negative-control-flow,
  negative-already-post, negative-delta-unknown so loop body is not DCE'd
- Fix delta-nonzero-lb CHECK to match actual addptr output
- Use opaque %cond argument in negative-control-flow to prevent
  constant-folding of scf.if
The pass causes performance regressions (cycle +5%~26%) because
BiSheng's auto-sync cannot prove non-overlapping UB access when base
pointers become phi nodes after post-update conversion, leading to
conservative SMEM_BAR insertion. Restore the CLI gate (default off)
so the pass only runs when explicitly requested.

Also fix two minor bugs: avoid redundant IndexCastUI when soAtEntry
is already index-typed, and derive ConstantIntOp bit-width from the
actual strideOperand type instead of hardcoding 16.
Comment thread tools/ptoas/ptoas.cpp Outdated
@zhangstevenunity
zhangstevenunity merged commit 43ca059 into hw-native-sys:main Jul 23, 2026
10 checks passed
@reedhecre

Copy link
Copy Markdown

A5 板测成功

  • 触发方式:merged
  • 源码提交:43ca05971428
  • 结果汇总:OK 21 / FAIL 0 / SKIP 0
  • 日志:/root/ptoas-board-monitor-a5/logs/20260723_091905_merged_pr962.log
  • 结果 TSV:/root/ptoas-board-monitor-a5/logs/20260723_091905_merged_pr962.tsv

@reedhecre

Copy link
Copy Markdown

A3 板测失败

  • 触发方式:merged
  • 源码提交:43ca05971428
  • 结果汇总:OK 219 / FAIL 2 / SKIP 2
  • 日志:/home/zhongxuan/ptoas-board-monitor/runtime/logs/20260722_181906_merged_pr962.log
  • 失败阶段:board-validation / exit=1

失败用例

  • comm_p2p_binding_variants (run, exit=1)
  • comm_p2p (run, exit=1)

@reedhecre

Copy link
Copy Markdown

A3 板测失败详情:PR #962

comm_p2p_binding_variants

stage=run info=exit=1

[ERROR] aclrtSynchronizeStream(stream) failed: 507035 (/home/zhongxuan/ptoas-board-monitor/runtime/runs/20260722_181906_merged_pr962/npu_validation/CommSync/comm_p2p_binding_variants/main.cpp:122)
[ERROR] RecentErrMsg: EZ9999: Inner Error!
EZ9999[PID: 2749602] 2026-07-22-18:47:08.446.093 (EZ9999):  The error from device(chipId:0, dieId:0), serial number is 1041, there is an exception of aivec error, core id is 47, error code = 0x10, dump info: pc start: 0x124000000000, current: 0x124000000164, vec error info: 0x9e000000ab, mte error info: 0xec06000023, ifu error info: 0x22980fa91f040, ccu error info: 0x400001800000004f, cube error info: 0, biu error info: 0, aic error mask: 0x6500020bd00028c, para base: 0x12c100000000.[FUNC:PrintCoreInfo][FILE:device_error_core_proc.cc][LINE:645]
        TraceBack (most recent call last):
       The extend info: errcode:(0x10, 0, 0) errorStr: Illegal instruction, which is usually caused by unaligned UUB addresses. fixp_error0 info: 0x6000023, fixp_error1 info: 0xec, fsmId:1, tslot:7, thread:0, ctxid:0, blk:0, sublk:0, subErrType:4.[FUNC:PrintCoreInfo][FILE:device_error_core_proc.cc][LINE:658]
       Kernel task happen error, retCode=0x31, [vector core exception].[FUNC:PreCheckTaskErr][FILE:davinci_kernel_task.cc][LINE:1729]
       AIV Kernel happen error, retCode=0x31.[FUNC:GetError][FILE:stream.cc][LINE:1475]
       [AIC_INFO] after execute:args print end[FUNC:GetError][FILE:stream.cc][LINE:1475]
       [DFX_INFO]Aicore kernel execute failed, device_id=0, stream_id=46, report_stream_id=46, task_id=0, flip_num=0, fault kernel_name=comm_p2p_binding_variants_kernel, fault kernel info ext=comm_p2p_binding_variants_kernel, program id=0, hash=16541545288638093324.[FUNC:GetError][FILE:stream.cc][LINE:1475]
       rtStreamSynchronize execution failed, reason=vector core exception[FUNC:FuncErrorReason][FILE:error_message_manage.cc][LINE:65]
       synchronize stream failed, runtime result = 507035[FUNC:ReportCallError][FILE:log_inner.cpp][LINE:148]
[2026-07-22 18:47:09] ERROR: testcase failed (exit 1): comm_p2p_binding_variants
comm_p2p

stage=run info=exit=1

[ERROR] aclrtSynchronizeStream(stream) failed: 507035 (/home/zhongxuan/ptoas-board-monitor/runtime/runs/20260722_181906_merged_pr962/npu_validation/CommSync/comm_p2p/main.cpp:122)
[ERROR] RecentErrMsg: EZ9999: Inner Error!
EZ9999[PID: 2757532] 2026-07-22-18:47:27.544.554 (EZ9999):  The error from device(chipId:0, dieId:0), serial number is 1042, there is an exception of aivec error, core id is 2, error code = 0x10, dump info: pc start: 0x124000000000, current: 0x124000000168, vec error info: 0x9e000000ab, mte error info: 0x6d0600009a, ifu error info: 0x204012d3ffe80, ccu error info: 0x400001800000004f, cube error info: 0, biu error info: 0, aic error mask: 0x6500020bd00028c, para base: 0x12c100000000.[FUNC:PrintCoreInfo][FILE:device_error_core_proc.cc][LINE:645]
        TraceBack (most recent call last):
       The extend info: errcode:(0x10, 0, 0) errorStr: Illegal instruction, which is usually caused by unaligned UUB addresses. fixp_error0 info: 0x600009a, fixp_error1 info: 0x6d, fsmId:1, tslot:7, thread:0, ctxid:0, blk:0, sublk:0, subErrType:4.[FUNC:PrintCoreInfo][FILE:device_error_core_proc.cc][LINE:658]
       Kernel task happen error, retCode=0x31, [vector core exception].[FUNC:PreCheckTaskErr][FILE:davinci_kernel_task.cc][LINE:1729]
       AIV Kernel happen error, retCode=0x31.[FUNC:GetError][FILE:stream.cc][LINE:1475]
       [AIC_INFO] after execute:args print end[FUNC:GetError][FILE:stream.cc][LINE:1475]
       [DFX_INFO]Aicore kernel execute failed, device_id=0, stream_id=46, report_stream_id=46, task_id=0, flip_num=0, fault kernel_name=comm_p2p_kernel, fault kernel info ext=comm_p2p_kernel, program id=0, hash=6260346515940177617.[FUNC:GetError][FILE:stream.cc][LINE:1475]
       rtStreamSynchronize execution failed, reason=vector core exception[FUNC:FuncErrorReason][FILE:error_message_manage.cc][LINE:65]
       synchronize stream failed, runtime result = 507035[FUNC:ReportCallError][FILE:log_inner.cpp][LINE:148]
[2026-07-22 18:47:28] ERROR: testcase failed (exit 1): comm_p2p

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.

4 participants