Repository navigation
fix(shader): quiet signaling NaNs only in IEEE mode - #1867
Conversation
Co-Authored-By: Claude <noreply@anthropic.com>
|
Rebased on |
afaa52d to
ef4dca9
Compare
…boykopovar#1878 rows (2026-10-09) 28 kernels of 26 tests through the recompiler of ef4dca9 on RTX 3080 and RADV in five float modes, compared bit for bit with the gfx1036 oracle; MixPrecision rerun after boykopovar#1878; the comment text as posted on boykopovar#1867. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012GLfKH7Sqe51wX254k1XsV
|
Cross-check of this PR together with #1866 against the hardware, continuing the audit on #981. The kernels of the 26 execution tests the audit found sensitive to
The 28-kernel run predates the #1878 merge; #1878 changes only AI-assisted: yes (Claude Code). |
The f64 unary instructions, v_ldexp_f64, v_div_fixup_f64 and v_cvt_f64_f32 always quieted a signaling NaN. The hardware does that only with IEEE_MODE=1, as boykopovar#1867 measured for the f32 and f16 forms; with IEEE=0 the NaN comes out unchanged, measured on gfx1036. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
With IEEE_MODE=1 the hardware quiets each signaling NaN half that v_pack_b32_f16 packs, after neg and abs; with IEEE=0 it copies the bits. The recompiler always copied them. Same rule as boykopovar#1867, measured on gfx1036 in both modes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
With IEEE_MODE=1 the hardware quiets a signaling NaN that v_cubesc, v_cubetc or v_cubema_f32 returns, keeping the sign the instruction gives it; with IEEE=0 the bits pass through. Same rule as boykopovar#1867, measured on gfx1036 in both modes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
With IEEE_MODE=1 the hardware quiets each signaling NaN half that v_pack_b32_f16 packs, after neg and abs; with IEEE=0 it copies the bits. The recompiler always copied them. Same rule as boykopovar#1867, measured on gfx1036 in both modes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The f64 unary instructions, v_ldexp_f64, v_div_fixup_f64 and v_cvt_f64_f32 always quieted a signaling NaN. The hardware does that only with IEEE_MODE=1, as boykopovar#1867 measured for the f32 and f16 forms; with IEEE=0 the NaN comes out unchanged, measured on gfx1036. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
With IEEE_MODE=1 the hardware quiets a signaling NaN that v_cubesc, v_cubetc or v_cubema_f32 returns, keeping the sign the instruction gives it; with IEEE=0 the bits pass through. Same rule as boykopovar#1867, measured on gfx1036 in both modes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
With IEEE_MODE=1 the hardware quiets a signaling NaN that v_cubesc, v_cubetc or v_cubema_f32 returns, keeping the sign the instruction gives it; with IEEE=0 the bits pass through. Same rule as boykopovar#1867, measured on gfx1036 in both modes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The f64 unary instructions, v_ldexp_f64, v_div_fixup_f64 and v_cvt_f64_f32 always quieted a signaling NaN. The hardware does that only with IEEE_MODE=1, as boykopovar#1867 measured for the f32 and f16 forms; with IEEE=0 the NaN comes out unchanged, measured on gfx1036. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The f64 unary instructions, v_ldexp_f64, v_div_fixup_f64 and v_cvt_f64_f32 always quieted a signaling NaN. The hardware does that only with IEEE_MODE=1, as boykopovar#1867 measured for the f32 and f16 forms; with IEEE=0 the NaN comes out unchanged, measured on gfx1036. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The f64 unary instructions, v_ldexp_f64, v_div_fixup_f64 and v_cvt_f64_f32 always quieted a signaling NaN. The hardware does that only with IEEE_MODE=1, as boykopovar#1867 measured for the f32 and f16 forms; with IEEE=0 the NaN comes out unchanged, measured on gfx1036. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
With IEEE_MODE=1 the hardware quiets a signaling NaN that v_cubesc, v_cubetc or v_cubema_f32 returns, keeping the sign the instruction gives it; with IEEE=0 the bits pass through. Same rule as boykopovar#1867, measured on gfx1036 in both modes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
With IEEE_MODE=1 the hardware quiets each signaling NaN half that v_pack_b32_f16 packs, after neg and abs; with IEEE=0 it copies the bits. The recompiler always copied them. Same rule as boykopovar#1867, measured on gfx1036 in both modes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
With IEEE_MODE=1 the hardware quiets a signaling NaN that v_cubesc, v_cubetc or v_cubema_f32 returns, keeping the sign the instruction gives it; with IEEE=0 the bits pass through. Same rule as boykopovar#1867, measured on gfx1036 in both modes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
What
Part of #981. Several instructions always set the quiet bit on a signaling NaN input. The hardware does that only with
IEEE_MODE=1; with IEEE=0, the mode titles use, the NaN comes out unchanged.v_ldexp_f32had the opposite problem and never quieted. Translation now followsGuestContext::floatMode.ieeeMode(#1816) through two helpers,quietNan32andquietNan16.Measured on RDNA2 (gfx1035) with the HW oracle at IEEE=0 and IEEE=1, with signaling and quiet NaNs of both signs and with payloads in every operand position:
v_sqrt/rcp/rsq/log/exp/sin/cos/fract/floor/ceil/trunc/rndne/rcp_iflag/frexp_mant_f32v_sqrt/rcp/rsq/log/exp/sin/cos/fract/floor/trunc/rndne/frexp_mant_f16v_ldexp_f32/f16,v_div_fixup_f32/f16andv_mullit_f32floatUnary,float16Unary,vFrexpMantF32,vFrexpF16,vLdexpF16,vDivFixupF32/F16andvMullitF32quiet only at IEEE=1, andvLdexpF32now quiets a NaN at IEEE=1. A shader without a known float mode follows IEEE=0.v_add/mul/fma_f32/f16,v_mul_legacy,v_fma_mix,v_cubema) follows the same rule on hardware, but its NaN bits are still left to the driver.v_cvt_f16_f32andv_dot2_f32_f16always quiet, andv_div_scale_f32never does, as the code already does.TechnicalDebt: new line for the rule, the
v_mullit_f32line updated, and the float mode line now says only the binary and ternary arithmetic is left.Tested
Linux (CachyOS, GCC), RADV (gfx1035) and CI's lavapipe (Mesa 25.2.8).
agc_driver_nan_quieting: 16 instructions × 32 rows captured on hardware at IEEE=0 and IEEE=1. 105 of the 512 cells differ between the two modes. The test runs with no mode and IEEE=0 (checked against the IEEE=0 table) and with IEEE=1, bit for bit. Forv_sqrtandv_rcp, only the NaN cells are compared, because their finite results are the driver's approximation (TechnicalDebt).agc_driver_div_fixup_f16,agc_driver_division,agc_driver_sdwa_ldexp_f16andagc_driver_vop1_float_unaryhad tables captured with the oracle's old implicit mode (IEEE=1, denormals kept), so they expected quieted NaNs. They now pin that mode (FLOAT_MODE0xf0, IEEE=1), asInterpolationF16does since feat(shader): implement v_interp_p1ll_f16, v_interp_p1lv_f16 and v_interp_p2_f16 #697. The tables are unchanged.v_ldexp_f32not quieting.mainafter feat(shader): flush f32 denormals in the float modes that flush them #1850.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt.mdfiles or images added to the repository (attach them to this PR)