Repository navigation
fix(rocke): refuse the fused fp8 scale-and-convert ops off gfx950, and catch them in the arch-domain table - #13954
Conversation
✅ All Checks Passed — Ready for Review
📖 Need help? See the Policy FAQ for details on every check and how to fix failures. |
|
🎉 All checks passed! This PR is ready for review. |
|
Automated review: Model - qwen3.6:35b-a3b-coding-mtp-q4_K_M, effort: max PR #13954 — refuse the fused fp8 scale-and-convert ops off gfx950, and catch them in the arch-domain table — 🟠 First-round: not merge-ready — rebase needed (conflicts with #14040); change itself verified
Utility: 🟢 Positive — turns a silent wrong-encoding build (a gfx950-only instruction in a gfx942 code object) into an actionable lowering error in both engines, and closes the arch-domain table's blind spot with an assembler pass. The fp8 / bf8 no-saturation doc corrections rest on the author's gfx942 / gfx950 measurements (not re-run here). Legend: 🔴 blocking · 🟠 should-fix · 🟡 minor nit · 🟢 info/good · ⚪ retracted First-round review: a local qwen3.6 model made the independent first pass; the orchestrator (Claude Opus 5.5) verified it on hardware — scratch merge with develop, native build + ctest, both-engine tests, and an LLVM 24 clang / llvm-mc reproduction — and owns this merge-worthiness call. It flags whether a closer look is needed; it is not an approval or a rejection. |
CongMa13
left a comment
There was a problem hiding this comment.
No new issues found. I agree with the following existing comments:
- Conflicts with develop in
lower_llvm.py(#14040 rebase required): @cgmillette (#13954 (comment)) - Missing CTest tier categorization in
ROCKE_ENGINE_test_categories_external.yamlforrocke_fp8_scale_conversion_gate: @cgmillette (#13954 (comment))
CongMa13
left a comment
There was a problem hiding this comment.
No new P0 or P1 issues were identified during this review. The changes are approved.
cvt_scalef32_pk_f32_fp8x4 and cvt_scalef32_pk_f32_bf8x4 wrap v_cvt_scalef32_pk_f32_fp8 / _bf8, which only gfx950 has. Both engines lowered them for any target. For gfx942 and gfx90a LLVM then selects the intrinsic and, on the direct object path, writes an encoding the GPU does not have; only the text assembler reports it. The ISA backend now states the capability (has_fp8_scale_conversion, true only for gfx950) and both lowerers refuse the two ops for a target without it, before emitting anything, with the same message: arith.cvt_scalef32_pk_f32_fp8 needs v_cvt_scalef32_pk_f32_fp8, which gfx942 does not have (gfx950 does); convert with cvt_pk_f32_fp8x4 and multiply by the scale instead The builder has no target, so lowering is the first point that can check. gfx950 output is unchanged. Tests pin the refusal text in both engines for every other wired target and check that gfx950 still lowers the ops identically in both. The new native test, rocke_fp8_scale_conversion_gate, is listed in the quick and ffm-quick CTest categories so the tiered test runs select it. Co-Authored-By: Claude <noreply@anthropic.com>
The f32 to fp8 / bf8 builders (scalar and packed) were documented as rounding and saturating. Measured on gfx942 and gfx950, they round to nearest even and do not saturate: a value that rounds past the largest finite fp8 value, and +-inf and NaN, become NaN; bf8 becomes NaN on gfx942 and +-inf on gfx950. The docstrings, the C header and the quantisation notes now say so, name each target's encoding, and point to clamp_f32 for a saturating conversion. Co-Authored-By: Claude <noreply@anthropic.com>
…ding ok The arch-domain generator recorded a key as ok for a target when its probe compiled and linked. A link is not proof: LLVM selects llvm.amdgcn.cvt.scalef32.pk.f32.fp8 / .bf8 for gfx90a and gfx942 and writes the gfx950-only instruction into the object without complaint, so the committed columns said ok there and the emitter's arch-domain check stayed silent. A probe that links is now also compiled to assembly and assembled for its target with the llvm-mc of the same install, which checks every instruction against the target. "instruction not supported on this GPU" records arch_absent with the rejected mnemonic as evidence (no scratch path); any other assembler failure is probe_error, never ok. The generator refuses to run without an llvm-mc beside clang. Re-assembling every ok cell of the llvm20 column found only these two keys on gfx90a and gfx942; the full llvm20 column still reproduces. The four cells are corrected in the llvm20, llvm22 and llvm23 columns, each measured with its own LLVM. Tests pin the path-free evidence and, where a toolchain is present, that the probe is arch_absent on gfx942 and ok on gfx950. Co-Authored-By: Claude <noreply@anthropic.com>
71f383e to
0d0b16c
Compare
|
Thanks for the reviews. Rebased onto current develop; changes, one line per item:
|
|
Automated review: Model - qwen3.6:35b-a3b-coding-mtp-q4_K_M, effort: max PR #13954 — refuse the fused fp8 scale-and-convert ops off gfx950, and catch them in the arch-domain table — 🟢 Follow-up: no closer look needed — both our items fixed; the rebase keeps both methods and covers the new generic targets
Prior reviews resolved; no net-new findings. Utility: 🟢 Positive — turns a silently wrong encoding (a gfx950-only instruction in a gfx942 code object) into a clear lowering error in both engines, and the arch-domain table now assembles its probes before recording a result. Legend: 🔴 blocking · 🟠 should-fix · 🟡 minor nit · 🟢 info/good · ⚪ retracted Follow-up review: a local qwen3.6 model made the independent first pass. The orchestrator (Claude Opus 5.5) verified it with a range-diff against the reviewed head, the native build and both-engine tests on the merge, a table-by-table comparison of the arch-domain data with develop, the golden gate, and scratch merges with #13886 and #13885, and owns this merge-worthiness call. It flags whether a closer look is needed; it is not an approval or a rejection. |
TheRock Submodule Bump ActivityNewest first
|
Motivation
cvt_scalef32_pk_f32_fp8x4andcvt_scalef32_pk_f32_bf8x4wrapv_cvt_scalef32_pk_f32_fp8/_bf8, which only gfx950 has. Both engines lowered them for any target. For gfx942 and gfx90a, LLVM then selects the intrinsic and, through COMGR, builds a code object that contains the gfx950 encoding without reporting anything; only the text assembler rejects it. A kernel using these ops for the wrong target should fail at lowering with a message that says what to do instead.The arch-domain table, which exists to catch intrinsics a target cannot run before link time, missed this case: its probe recorded a key as available whenever the probe linked. This PR closes that gap too.
The fp8 / bf8 conversion builders were also documented as saturating. Measured on gfx942 and gfx950, they do not.
ISSUE ID : AICK-2646
Technical Details
has_fp8_scale_conversion,Trueonly for gfx950 (PythonISABackend/Gfx950Backend; C++ a new last field ofrocke_isa_backend_t, set on the gfx950 row). This is the same home as the existing per-target capability flags.arith.cvt_scalef32_pk_f32_fp8 needs v_cvt_scalef32_pk_f32_fp8, which gfx942 does not have (gfx950 does); convert with cvt_pk_f32_fp8x4 and multiply by the scale insteadtools/gen_arch_domain.py) now also compiles each probe that links to assembly and assembles it for its target with thellvm-mcof the same install, which checks every instruction against the target. "instruction not supported on this GPU" recordsarch_absentwith the rejected mnemonic as evidence; any other assembler failure isprobe_error, neverok.okcell of the llvm20 column found only these two keys on gfx90a and gfx942; the full llvm20 column still regenerates unchanged.clamp_f32.Test Plan
tests/core/test_fp8_scale_conversion_gate.py: refusal text pinned in both engines for every other wired target (read fromwired_arches(): gfx90a, gfx942, gfx1151, gfx1201, gfx11-generic, gfx12-generic, gfx1250); gfx950 lowers both ops, and the two engines' IR is identical.rocke_fp8_scale_conversion_gate: the same text pinned in the C++ engine for the same targets, gfx950 still lowers. It is listed in thequickandffm-quickcategories ofROCKE_ENGINE_test_categories_external.yaml.arch_absenton gfx942 andokon gfx950;--checkregenerates the llvm20 column unchanged.llvm-mcfrom LLVM 20 and LLVM 23: only gfx950 accepts it.Test Result
ROCKE_BACKEND=both ROCKE_CPP_STRICT=1.gen_arch_domain.py --checkat llvm20: every cell reproduces.Submission Checklist
🤖 Generated with Claude Code