Skip to content

[LinxV5] Encode B.IOT source last-use markers - #108

Closed
zhoubot wants to merge 3 commits into
dev-llvm15_56from
codex/biot-last-use-15-56
Closed

zhoubot wants to merge 3 commits into
dev-llvm15_56from
codex/biot-last-use-15-56

Conversation

@zhoubot

@zhoubot zhoubot commented Sep 22, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Implements the compiler side of PTO-SPEC B.IOT and B.IOS last-use contracts
(PTO-ISA/pto-spec#340) on the
linx_blockisa_llvm_musl release lineage (dev-llvm15_56).

This supersedes #107, which targeted dev-llvm15-v5-encoding. That branch is a
WIP lineage that cannot compile the current SuperNPUBench corpus (it rejects the
BSTART.TLSU TLOAD inline-asm operands used by LinxISA/Linx-TileOP-API), so
the change belongs here instead.

Every B.IOT Local source now carries an independent lifetime decision. A source
written with the .reuse suffix keeps its payload readable after the block; a
source without it is the last architectural payload consumer for the
participating PEs. The encoding stays 32-bit and preserves every existing word.

Field Change
Two-source Func (14:12) 010 last/last, 011 reuse/last, 111 last/reuse, 100 reuse/reuse (the previous encoding)
One-source Func=101 bit 26: 0 reuse (all pre-change words), 1 last-use; bits 31:27 stay zero
Destination-only Func=110 unchanged
L (19) still only the effective B.IOT stream terminator, never a lifetime marker

Implementation

  • LinxV5RegisterInfo.td: new Tile_{T,U,M,N}OS{1..16}_RU aliases (t#1.reuse, ...)
    and their entries in the tile source register classes so .reuse parses and prints.
  • LinxV5InstrInfo.td: four two-source and two one-source lifetime variants; the
    bare-source variants are the new defaults, matching "omission means last-use".
    All existing InstAlias forms are kept, including the tile_t1 absolute spellings.
  • LinxV5TRegToOffset.cpp: markTileLastUses freezes each tile source's last-use
    decision from block liveness before operands are rewritten to relative offsets,
    and rewrites retained sources to the _RU alias. A source is last-use when the
    value is neither live out of its block nor read again later in that block.
  • LinxV5MCCodeEmitter.cpp / LinxV5TileOpExpand.*: normalizeBIOTLifetimeOpcode
    selects the concrete encoding from the operand .reuse markers at emission time.
  • LinxV5AsmParser.cpp: accepts the .reuse tile-register suffix.
  • LinxV5Disassembler.cpp: decodes the lifetime forms. The generated decoder only
    covers the non-lifetime variants, so the lifetime fallback rebuilds the operand
    list in the same order and with the same operand decoders as the generated
    decoder (decodePEMode, decodeBIOTDstSizeCode, decodeUImmOperand<1>).

Verification

Toolchain built exactly as SuperNPUBench/README.md prescribes: dev-llvm15_56
plus LinxISA/Linx-TileOP-API @ linx, host-built clang-15 for
linx64v5-unknown-linux-musl.

MC round trip (llvm-mc -show-encoding + llvm-objdump -d), all six lifetime
combinations plus the pre-change words:

B.IOT t#1, mask=1111                  -> 0x04005e13   (bit 26 = last-use)
B.IOT t#1.reuse, mask=1111            -> 0x00005e13   (bit 26 = 0, unchanged)
B.IOT t#1, u#1, mask=1111             -> 0x40002e13   (Func 010)
B.IOT t#1.reuse, u#1, mask=1111       -> 0x40003e13   (Func 011)
B.IOT t#1, u#1.reuse, mask=1111       -> 0x40007e13   (Func 111)
B.IOT t#1.reuse, u#1.reuse, mask=1111 -> 0x40004e13   (Func 100, unchanged)

llvm/test/MC/LinxV5/b.iot.s checks both the encoding and the disassembly of all
those forms (plus the absolute tile_* register spellings); both FileCheck
prefixes pass.

End-to-end on the SuperScalarModel corpus: recompiled SuperNPUBench at revision
78ea4173 (the revision pinned for the SSM release-ops-20260918-repack prebuilt
ELFs) with this toolchain. kernel_matmul_matmul_reuseB_B1_M1024_N1024_K1024_tM128_tN128_tK128
moves from

gfsim: [gfsim] caught std::exception: ASSERTION FAILED: 0 && "Tile register is
not enough for the simulator!"   (prebuilt ELF, all sources reuse/retain)

to

gfrun: R2 = 0 (functional check passes)
gfsim: Total Cycles 719693 (runs to completion)

which is the point of the ISA change: without last-use markers the retained
payload window exhausts the 256 KiB Local pool.

Notes

  • -linxv5-reuse-mark is not restored; marking is unconditional because the
    marker is required by the accepted encoding. With the hidden
    -linxv5-enable-reg-to-offset=false MCA mode the _RU rewrite does not run.
  • Downstream landing order is PTO-SPEC, LLVM, ASL-MODEL coverage, then the
    SuperScalarModel Phase 2 timing model.

Corpus regeneration with this toolchain

Successive builds of the SuperNPUBench one-level corpus (revision 78ea4173,
the input of the SSM release-ops-20260918-repack prebuilt ELFs) with this
toolchain plus LinxISA/Linx-TileOP-API @ 3be8652 (the pin recorded in the
SuperNPUBench ops-20260918 release notes) and linx64v5-unknown-linux-musl
target:

llvm-lit MC/LinxV5 + CodeGen/LinxV5   base 41 failed -> 39 failed
                                      (b.iot.s and reuse.ll repaired; the
                                       rest are pre-existing SIMT/clang-dependent)
MC lifetime round trip                all six combinations ENC + DIS pass
one-level corpus rebuild              154 ELFs, 21 operators OK
SuperScalarModel gfsim pass list      415 pass / 66 fail  (prebuilt corpus)
                                      429 pass / 52 fail  (regenerated corpus)

The 14 repaired entries are the whole matmul family that used to abort with
Tile register is not enough for the simulator!; they now complete with sane
cycle counts, e.g.

kernel_matmul_matmul_reuseB_B1_M1024_N1024_K1024_tM128_tN128_tK128  719693 cycles
kernel_matmul_matmul_shared_B1_M1024_N1024_K1024_tM128_tN256_tK128  645839 cycles
kernel_matmul_matmul_blockM_B1_M1024_N1024_K1024_tM128_tN128_tK64_bM2_bN1  530988 cycles

Remaining downstream gap

The 52 remaining FA failures are not caused by this change. The released
ops-20260918 / ops-20260922 FA binaries are model-compatible and pass on the
unmodified SuperScalarModel, but they carry no last-use information, so the new
reuse/retain decode makes them exhaust the 256 KiB Local pool. Rebuilding FA with
this public branch tip changes the BSTART.TEPL macro shape (the tip emits an
extra BSTART.TEPL TROWEXPANDEXPDIF header where the released compiler emits a
BSTART.TEPL TMAX header plus a 64-bit TROWEXPANDEXPDIF body), which the
current timing model cannot bind sources to.

The released corpus was built from llvm-project dev-llvm15_56 @ 1037cc1cd
(recorded in the SuperNPUBench release notes and in the ELF .comment). That
commit is no longer reachable in LinxISA/llvm-project (the branch was
force-pushed; gh api .../commits/1037cc1cd returns 422), so the exact FA
codegen cannot be reproduced from public sources. Restoring that revision (or
teaching the model the newer TEPL macro form) closes the FA gap; the B.IOT
markers themselves are already proven on the matmul family.

Shared B.IOS extension (PTO-SPEC llvm#347 / PR llvm#341)

Head: 1f113e161f48adc3507b53c4948feaaf048cbf66.

  • Ordinary Shared source: bare Sx encodes bit 26 one (last-use); explicit Sx.reuse encodes bit 26 zero (retained, every old binary word). Destination bit 26 one and bit 27 remain illegal.
  • Shared generated pseudos use value/generation-aware liveness, conservatively retaining on CFG uncertainty; MC lowering carries the decision into B.IOS emission. Direct MC, macro parser/folder, disassembler, and Clang integrated assembler agree.
  • Public TileOp API inline asm uses %S[Shared]: ordinary Shared inputs print .reuse conservatively, even when the whole INLINEASM operand is killed, because a placeholder may occur multiple times in one template. %K requests one exact textual last-use occurrence and fails closed unless the operand is a killed pure input; %R explicitly retains a tied source. Generated pseudos still emit last-use automatically. Existing API wrappers have not been annotated with %K, so their Shared sources will remain retained until a call-site-safe API change; the regenerated corpus must be counted before performance claims.
  • Local markTileLastUses now excludes INLINEASM regdef operands from kill mutation; assertions-on Clang previously crashed on tscatter_fp32_16x16, and the exact compile plus a minimal MIR regression now pass.
  • Focused Local/Shared MC/CodeGen suite: 10/10 PASS, including encoding/disassembly, destination negatives, repeated placeholders, tied operands, loop backedges, live-after %K rejection, and INLINEASM regdef. Clang integrated assembler passed; git diff --check and changed-line clang-format passed. Broader LinxV5 suite before the final small crash fix: 150 PASS, 1 XFAIL, 31 pre-existing/tool-availability failures (not treated as a clean suite).
  • Full reproducible SuperNPUBench source corpus was rebuilt from e74884e using assertions-on Clang at this exact head and the pinned Linx musl/libc++ sysroot: 614 unique ELF files (424 micro, 190 one-level), with all 5 micro and all 29 one-level build scripts attempted. Source-path list matches the prior 614 corpus exactly. Successful and failing family status is explicit in the report; not every source variant compiled successfully.
  • Disassembly of all 614 ELFs finds 23,770 ordinary B.IOS Shared sources, all .reuse and zero last-use. This is correct fail-safe behavior for the unannotated public TileOp API inline-asm wrappers, but this corpus cannot measure Shared early-release benefit. Compiler-generated Shared pseudos and explicit %K can emit bit26=1, as the focused tests show. ELF list, SHA-256 manifest, per-family logs, and marker census: /Users/zhoubot/.codex/artifacts/bios-last-use-corpus-20260923/.

PTO-SPEC issue PTO-ISA/pto-spec#340 restores an independent lifetime
decision for every B.IOT Local source. A source written with the `.reuse`
suffix keeps its payload readable after the block; a source without it is
the last architectural payload consumer for the participating PEs.

The 32-bit encoding keeps every existing word: two-source `Func` 010/011/
111 join the existing 100 to encode last/last, reuse/last, last/reuse and
reuse/reuse, and one-source `Func=101` uses bit 26 (0=reuse, 1=last-use).
`L` remains only the B.IOT stream terminator.

- Add `Tile_TOS/UOS/MOS/NOS{1..16}_RU` register aliases and extend the tile
  source register classes so the `.reuse` spelling parses and prints.
- Define the four two-source and two one-source B.IOT lifetime variants and
  select the concrete encoding from the source `.reuse` markers while the
  MC operand still carries the absolute vtag identity.
- Mark each tile source's last use from block liveness before the operands
  are rewritten to relative offsets, so a value that is live out of its
  block, or read again later in the block, keeps `.reuse`.
- Decode the reuse forms in the disassembler; the generated decoder only
  covers the non-lifetime variants, so the lifetime fallback has to build
  the MC operand list in the same order as the TableGen decoder.

Verification:
- `llvm-lit llvm/test/MC/LinxV5 llvm/test/CodeGen/LinxV5` - 41 failures at
  the base commit, 39 with this change; the difference is exactly the two
  B.IOT lifetime tests that this change repairs. The remaining failures are
  pre-existing SIMT/Block-C failures and tests that need an in-tree clang.
- `llvm/test/MC/LinxV5/b.iot.s` and `llvm/test/CodeGen/LinxV5/reuse.ll`
  pass, and the new `b.iot-lifetime-decode.s` pins the decoded operand
  order for all six lifetime combinations.

Refs: PTO-ISA/pto-spec#340
(cherry picked from commit 0358089)
@zhoubot

zhoubot commented Sep 23, 2026

Copy link
Copy Markdown
Collaborator Author

Independent exact-head re-review completed for fa76e69656fa against dev-llvm15_56@66816b2b5178: APPROVE, zero findings. The amended head fixes all five prior review findings: destination-bearing source operand indices, retain preservation when relative rewriting is disabled/untracked, invalid zero-size destination shorthand, reserved one-source bits [31:27], and TileOp macro folding for all lifetime opcodes. Fresh llvm-mc/llvm-objdump/llc rebuild passed; six targeted lit tests and the expanded 18-test B.IOT/macro suite passed; git diff --check is clean.

zhoubot added a commit to PTO-ISA/pto-spec that referenced this pull request Oct 10, 2026
Adds independent Local `B.IOT` and Shared `B.IOS` source lifetime
markers for #340 and #347, reconciled with #373's independent PE
execution. A first-finishing PE can no longer retire Shared data that
another declared participant still needs; GMOV retires the selected
source PE's Local generation.

## Contract and compatibility

- Ordinary bare sources declare last-use; `.reuse` retains payload. The
`L` bit remains the stream terminator. Existing binary words retain
their old meaning; **reassembling legacy bare-source text changes
behavior**.
- Local retirement preserves descriptor, vtag, relative identity, and
other PE banks. ExecutionMask carriers are excluded. `B.ASSEMBLE`
continuation ParentRefs require reuse.
- Shared occurrence records track the exact Core, invocation, origin,
privilege, instruction site, selectors, generation, and participant
mask. Retirement waits for all declared participants and outstanding
occurrences; recovery invalidates only the affected PE's
acknowledgement. Publication cannot overwrite a pinned generation.
- GMOV captures immutable source-PE/index/generation selections,
including repeated peers. Fault/retry and nonparticipant execution
preserve payload. Zero-row cooperative TMATMUL acknowledges Shared
completion without Local effects.
- Amends ADR-BLOCK-0013 and ADR-BLOCK-0015 with the maintainer-approved
participant-aware decision against baseline
`f3fa24331df452248366550f71cd1be22e62aeb1`. Owning clauses include
`PTO-ARCH-LOCAL-VTAG-LIFETIME-001`, `PTO-ARCH-SHARED-VTAG-LIFETIME-001`,
and `PTO-B-SOURCE-LIFETIME-PE-COMPLETION-001`.

The ASL owners, catalogs, decoder/AVS projections, bilingual instruction
guides, strict layout census, and state inventories are reconciled
together. Draft inventory: 105 Block forms and 572 encoded forms. Binary
fingerprint:
`905c5cae908ed320dd214dc700f08dcb8231dff52f5933a5b1346ac36b987455`.

## Validation

Final head: `5b27cdab976fc648b899fecc8fd49a6dee76d4c5`; base:
`f3fa24331df452248366550f71cd1be22e62aeb1`.

- 29/29 focused ASL points passed on semantic commit
`4b46edef2ccb490cbb0d8754deacc7713168d857`; subsequent commits change
tooling, tests, and the census only. ASL and runner inputs are
unchanged.
- Red/green evidence covers premature Shared retirement, wrong-bank GMOV
retirement, and zero-row TMATMUL acknowledgement.
- Strict census mutation canaries reject wrong helper owners, added
callers, and layout-bearing changes.
- All 14 changed English/Chinese guide pairs have separate review and
verification receipts.

- `make pr-check`: 11/11 PASS, including the full Python suite.
- `make repo-check`: 7/7 PASS, including 572-form binary closure.
- Site typecheck and 14/14 unit tests PASS; English and Chinese
production builds PASS with `NODE_OPTIONS=--max-old-space-size=16384`
after the default heap ran out of memory.
- `git diff --check` PASS. One independent reviewer approved this exact
base/head/tree/diff with no findings; `scripts/prepare-pr --review`
accepted the receipt. This receipt is local, unauthenticated review
evidence, not GitHub approval.

The suggested broad ASL matrix is not claimed as fully executed; the 29
focused points above are the executed subset.

## Downstream and release obligations

Landing order remains PTO-SPEC → LLVM → ASL-MODEL → SuperScalarModel.
Related implementation work: [LLVM
#108](LinxISA/llvm-project#108) and
[SuperScalarModel
#846](LinxISA/SuperScalarModel#846). Downstream
runtime and same-ELF independent-golden coverage remain development
obligations.

The nine added command forms are recorded as **missing/divergent** in
historical executable-model comparison evidence; no execution or ABI
acceptance is fabricated. Frozen 0.58.7 artifacts remain unchanged. Full
exact-commit release validation is pending; this PR does not claim
release readiness or close the full hosted ABI issue #150.

---------

Co-authored-by: zhoubot <637081+zhoubot@users.noreply.github.com>
@VV0003

VV0003 commented Oct 20, 2026

Copy link
Copy Markdown
Collaborator

This PR is superseded by the implementation already present on dev-llvm15_56.

The three changes are now in the target branch as:

  • cf2cbb28d013 — B.IOT source last-use markers
  • a851da05c1ae — B.IOS Shared source lifetime
  • 782630815dce — ignore inline-asm defs in tile last-use marking

The current branch also contains follow-up fixes for masked Tile/lifetime interaction (96b42963282b) and the final PR #131 ISA/regression fixes (47557a08c4b5).

Validation against the current target build (/tmp/linx-llvm-pr131-rebased-build, assertions enabled):

  • B.IOT/B.IOS MC lifetime tests
  • Local/Shared reuse and cross-block codegen tests
  • inline-asm last-use negative/modifier tests
  • Shared register allocation and inline-asm-def MIR regression

Result: 9/9 PASS. No additional code from this historical PR should be merged; closing as superseded.

@VV0003 VV0003 closed this Oct 20, 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.

2 participants