feat(vpto): canonicalize integer-backed castptr for post-update addressing (#591) - #1353
Draft
mouliangyu wants to merge 9 commits into
Draft
Conversation
…ssing Issue #591: vpto re-materializes castptr(base + iv*stride) address arithmetic inside rolled scf.for loops, leaking scalar RV_SADD/RV_SMOVK ops onto the vector pipe. Add two passes that normalize the address form so the existing post-update consumer can strength-reduce it: - pto-canonicalize-integer-address: castptr(byte_addr) -> castptr(canonical root) + addptr(element quotient) in zero-origin (UB) spaces, with exact-division proof, atom-root handling, and pointer-derived rejection; converges to the normal form in one pass. - pto-absorb-addptr: op(addptr(base, A), O) -> op(base, A + O) using only VPTOAddressSemanticsOpInterface (Element-unit offsets). Also adds the missing VPTOAddressSemanticsOpInterface on pto.vstsx2, promotes getElementBytes into a shared helper, wires both passes before VPTOSoftPostUpdate in the ptoas pipeline, and adds lit coverage (C01-C15 canonicalization matrix + absorb fold). End-to-end, the issue-591 repro now emits llvm.hivm.vldsx2.post and a VLDS post-update device body with zero scalar address ops in the tile loop. Design: docs/designs/vpto-integer-address-canonicalization-design-zh.md
Review found two issues in pto-canonicalize-integer-address: - Hoisting castptr(R) above an enclosing scf.for when the atom root R is defined inside the loop produced IR that violates SSA dominance. Only hoist when R is loop-invariant for every skipped loop; otherwise keep the base in place (legal IR, post-update simply does not fire). - The root selection accepted a -1 coefficient while the design contract only allows a +1 atom; reject negative-coefficient atoms. Adds lit coverage for the loop-local atom root, negative-coefficient rejection, nested-loop hoisting, and vstsx2 addptr absorption.
…proof Design C14 requires the quotient to round-trip losslessly into index; the first implementation approximates this with the sufficient condition inputWidth == index width. Narrower inputs are conservatively rejected until PTO defines the zero/sign extension semantics of castptr into the 64-bit address space. Align the rejection message and the design doc with this approximation instead of claiming a full round-trip proof.
castptr i32 inputs today lower straight to inttoptr i32 -> ptr addrspace(6) (no width extension) and compile through bisheng; the narrow-to-64-bit extension is an LLVM inttoptr implementation convention, not a PTO semantic contract. Record this measured fact to justify keeping the 64-bit-only approximation in the canonicalization rewrite.
… convention) LLVM LangRef defines inttoptr width conversion explicitly: narrower integers are zero-extended, wider are truncated. The PTO gap is only that PTO does not document inheriting that semantics; the real LLVM undefined behavior is provenance (inttoptr pointers based on no pointer are UB to dereference), which the zero-origin UB model and this rewrite do not change. Update the measured-evidence note and the C14 approximation note accordingly.
…roof Implement design C14 instead of the 64-bit-only approximation: narrower integer inputs (i32 etc.) are accepted when the byte expression provably does not wrap in its own width, using the LLVM inttoptr zero-extension semantics recorded in design section 2.2. Constant expressions are proved via foldPTOConstant; loop-carried expressions via PTOValueEvolutionAnalysis getRange (non-negative, signed upper bound with headroom). Quotient leaves materialize into index with index_castui (zero-extend). Wider-than-index inputs still truncate and are rejected. Known boundary: the analysis Mul range is currently index-only, so i32 loop recurrences such as muli(iv32, 4096) still return PossibleWrap and are rejected even when mathematically non-wrapping; extending the analysis to non-index arithmetic is future work.
Add two host-validation cases (run_host_vpto_validation.sh, dav_3510 simulator) measuring the rolled-vs-unrolled tile loop on the affine castptr(t*4096) pattern: - rolled (canonicalized): 0 RV_SADD/RV_SMOVK in the tile loop, 16 RV_VLDS post-update loads, kernal ticks 3959 - unrolled (baseline): 2 scalar addr ops in prologue, 15 RV_VLDS/1 RV_VLDI, kernal ticks 3957 rolled is 1.0005x of unrolled (target <= 1.1x) and rvec busy is 70 vs 71, so design section 9 acceptance is met. Record the measured numbers in the design doc, including the known boundary that VPTOSoftPostUpdate does not convert dynamic-trip-count loops on this build (missing hw-native-sys hw-native-sys#1330; cases use a constant trip count).
…tests Full vpto lit run (545 tests) exposed two interaction bugs with the default-on pipeline: - absorb folded arbitrary addptr chains over user pointers, destroying VPTOSoftPostUpdate's sequential base-chain post-update structure (soft_postupdate_sequential-base-chain). Scope the fold to addptr whose base is an integer-backed castptr — the shape produced by pto-canonicalize-integer-address; chains are SoftPostUpdate's job. - canonicalize/absorb changed the emitted shape of tests that previously kept integer castptr forms (auto_vecscope_infer_shared_ptr_capture: castptr(2048) -> castptr(0)+addptr(1024); soft_postupdate_delta-nonzero-lb: addptr recurrence absorbed into op offset). Update their CHECKs to the new canonical form. Also extends coverage: C04 (i8 identity quotient), C06 (trunc rejection), subtraction input, non-linear (srem) rejection, and a negative test that chained addptr over a user pointer is NOT absorbed. After the fix the whole test/lit/vpto suite passes except the out-of-tree baseline scratch file. lit: 544/545 passed (only failure: untracked integer_address_forms_baseline scratch, not part of this change).
The fold now applies only when the addptr base is an integer-backed castptr (the canonical shape); arbitrary addptr chains stay with VPTOSoftPostUpdate's sequential base-chain handling.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
背景
Issue #591:vpto 在 rolled
scf.for里逐迭代重新物化castptr(base + iv*stride)的整数地址算术,泄漏成标量RV_SADD/RV_SMOVK上 vector pipe,序列化 load(WHT N=512 时 1640 个泄漏点,2.45× 退化)。方案
两个新 pass,把地址规范成现有 post-update consumer(
VPTOSoftPostUpdate)能直接消费的形态:pto-canonicalize-integer-address(规则 R,核心)castptr(byte_address)→castptr(规范根) + addptr(element 商)(B−R)/E)+ 位宽 round-trip proof;pto-absorb-addptr(规则 F / C11 fold)op(addptr(base, A), O)→op(base, A+O),合法性仅来自VPTOAddressSemanticsOpInterface(Element 单位、非 post-update、index 加法)。Bisheng 只有 operation-offset 形态才出 post-update。配套:
pto.vstsx2缺失的VPTOAddressSemanticsOpInterface(与vldsx2对称);getElementBytes提升为共享getPTOElementBytes(Type/Value);VPTOSoftPostUpdate前接入两个 pass;docs/designs/vpto-integer-address-canonicalization-design-zh.md;test/dsl/issue_591_repro.pto。端到端验证
issue_591_repro.pto(castptr(iv*4096)的 rolled 循环)经两个新 pass 后:→ SoftPostUpdate →
@llvm.hivm.vldsx2.post.v128f16(ptr, 4096, ...)(phi 携带)→ bisheng device.text与 VLDS post-update 形态逐字节一致,循环体内零标量地址 op(VLDI+SADD 形态为 0x128 字节,post-update 为 0x120 字节)。验证
ninja ptobc PTOASCompiler pto-test-opt构建通过(-Werror);integer_address_canonicalization.pto(RUN1 + IDEMPOTENT 双 RUN)、absorb_addptr_offset.pto全部通过(pto-test-opt + FileCheck);castptr(%param))实测:根 + operation offset →vldsx2.post,与castptr(0)根字节级同构;根 + addptr(未 fold)→ 非 post(见设计文档 §6.5)。测试命令