Skip to content

feat(shader): decode s_rfe_b64, s_sethalt, s_sendmsghalt and s_code_end - #1306

Closed
pandather wants to merge 1 commit into
boykopovar:mainfrom
pandather:feat/shader-decode-scalar-halt-ops
Closed

pandather wants to merge 1 commit into
boykopovar:mainfrom
pandather:feat/shader-decode-scalar-halt-ops

Conversation

@pandather

Copy link
Copy Markdown
Contributor

What

Decodes the four remaining scalar control instructions that were rejected as unsupported: S_RFE_B64 (SOP1 0x22), S_SETHALT (SOPP 0x0D), S_SENDMSGHALT (SOPP 0x11) and S_CODE_END (SOPP 0x1F). Following the pattern of #895 (s_call_b64): the decoder recognises them from the encoding, IR translation throws a named "not implemented" error until the backend models wave halt/return semantics.

s_rfe_b64 is modelled as an indirect jump like s_setpc_b64: measured on RDNA2 hardware (gfx1031) with the hardware oracle, a jump to the address in its scalar source reaches code past s_endpgm, identical to s_setpc_b64 with the same target. The CFG target resolvers and the embedded vertex fetch analysis treat it as s_setpc_b64; the decoder gives it no destination, as LLVM encodes none.

s_sethalt is implemented for the immediates measured on gfx1031: 0, 2 and 4 run through to the end of the kernel with the store after them visible; 1, 3 and 5 never retire the wave (debugger halt without a debugger), so they throw in IR translation; immediates above 5 are unverified and throw.

s_sendmsghalt and s_code_end throw in IR translation: the message goes to graphics control hardware the port does not model, and code_end measured on gfx1031 inactivates the HSA queue with
HSA_STATUS_ERROR_ILLEGAL_INSTRUCTION, so a throw is the faithful host behaviour.

Provenance: AMD machine-readable GPU ISA spec (amdgpu_isa_rdna2.xml, https://gpuopen.com/machine-readable-isa/ — the same source tools/rdna_isa.txt's header cites). Encodings cross-checked against three values already in the decoder and merged PR text: s_getpc_b64 = 0x1F, s_call_b64 = 0x16 (#895), s_swappc_b64 = 0x21 (#1124). Operands per spec: s_rfe_b64 has SSRC0 only and no destination (the NULL-dst form of s_swappc_b64 keeps mapping to setpc as before); the three SOPP ops carry SIMM16.

SOPP reaches 37/37 in tools/progress.py; shaders 1139 -> 1143 / 1166 (98.03%).

Tested

Windows 11, NVIDIA Blackwell desktop GPU (driver 616.92), MinGW-w64 GCC 15.2.0 (winlibs x86_64-ucrt-posix-seh r7). Full ctest:
396/396, including the new scalar_halt_ops test — it decodes each instruction from raw words, checks family/operands/source counts, and asserts the named translation throw both directly through TranslateInstruction and through a full program translate. python3 tools/check_conventions.py --base origin/main passes.

Checklist

  • Based on current main; no other open PR implements the same functions (checked against all 202 open PRs, descriptions and comment threads)
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • AI-assisted: yes

Decodes the four remaining scalar control instructions with encodings from
the AMD machine-readable RDNA2 ISA spec: S_RFE_B64 (SOP1 0x22), S_SETHALT
(SOPP 0x0D), S_SENDMSGHALT (SOPP 0x11) and S_CODE_END (SOPP 0x1F).

s_rfe_b64 is modelled as an indirect jump like s_setpc_b64: measured on
RDNA2 hardware (gfx1031) with the hardware oracle, a jump to the address
in its scalar source reaches code past s_endpgm, identical to
s_setpc_b64 with the same target. The CFG target resolvers and the
embedded vertex fetch analysis treat it as s_setpc_b64; the decoder gives
it no destination, as LLVM encodes none.

s_sethalt is implemented for the immediates measured on gfx1031: 0, 2 and
4 run through to the end of the kernel with the store after them visible;
1, 3 and 5 never retire the wave (debugger halt without a debugger), so
they throw in IR translation; immediates above 5 are unverified and throw.

s_sendmsghalt and s_code_end throw in IR translation: the message goes to
graphics control hardware the port does not model, and code_end measured
on gfx1031 inactivates the HSA queue with
HSA_STATUS_ERROR_ILLEGAL_INSTRUCTION, so a throw is the faithful host
behaviour.

SOPP reaches 37/37 in tools/progress.py; shaders 1139 -> 1143 / 1166.
@adriadam10

Copy link
Copy Markdown
Collaborator

Thanks for the PR. Closing it as a duplicate of #1253, merged today: main already decodes s_rfe_b64, s_sethalt, s_sendmsghalt and s_code_end and translates them (ScalarInstructions.cpp: s_sethalt with SIMM16[0] clear is a no-op, the halting forms, s_sendmsghalt, a reached s_code_end and s_rfe_b64 throw with the reason; linear decoding stops at s_code_end). #1253 was already open when this one was created, so the "no other open PR" checklist line didn't hold.

What's left as a difference isn't something we'd take on its own:

  • s_rfe_b64 as an indirect jump: it returns from a trap handler, and recompiled shaders run without one, so main throws on it (exact-or-throw). A jump measured outside a trap handler doesn't tell us what a real shader would expect.
  • s_sethalt throwing for immediates above 5: the halt state is SIMM16[0] only, so even values are no-ops as main already does.

If you find a title that actually reaches one of these throws, feel free to open a new PR on top of current main with a test that reproduces it.

@adriadam10 adriadam10 closed this Oct 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* build docs needs rebase Conflicts with main, rebase needed shader core/shader

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants