feat(vpto): add VPTOSoftPostUpdate pass#962
Conversation
There was a problem hiding this comment.
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.
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
1687f46 to
c7992e7
Compare
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.
A5 板测成功
|
A3 板测失败
失败用例
|
A3 板测失败详情:PR #962comm_p2p_binding_variants
comm_p2p
|
first step of #941
Summary
Add a new MLIR-level pass
VPTOSoftPostUpdatethat converts non-post-update VPTO memory operations (pto.vlds,pto.vsts,pto.vsstb) insidescf.forloops into post-update form, where the base pointer is automatically advanced and carried throughiter_args.This replaces the need for bisheng's LLVM IR-level
hiipu-vf-soft-postupdatepass for these operations, with several advantages:scf.forstructure instead of reconstructing loops viaLoopInfo+ SCEVWhat it does
Before:
After:
Pipeline position
VPTOExpandWrapperOps → CSE → VPTOSoftPostUpdate (new) → PTOInferVPTOVecScope → ...
Testing