Author: Romaric Jodin Date: 2026-10-26T06:25:27+08:00 New Revision: 13731359fd502d90d6522eb80b9bb422ebaae2b2
URL: https://github.com/llvm/llvm-project/commit/13731359fd502d90d6522eb80b9bb422ebaae2b2 DIFF: https://github.com/llvm/llvm-project/commit/13731359fd502d90d6522eb80b9bb422ebaae2b2.diff LOG: [libclc] Fix exponent overflow and subnormal rounding in __clc_ldexp (#233823) When fp32 subnormals are supported (`!__clc_denormals_are_zero_fp32()`), `__clc_ldexp` previously added `n` to the exponent with plain signed integer addition, overflowing 32-bit `int` when `n` is near `INT_MAX` or `INT_MIN` (e.g. `n = INT_MAX` wrapped around to `< -24` and flushed to zero instead of returning infinity). Additionally, subnormal fp32 results were formed with a truncating right shift instead of round-to-nearest-even, and shift counts were not clamped to valid ranges. Normalize subnormal fp32 inputs before adding `n`, use `__clc_add_sat(exponent, n)` in both fp32 and fp64 `__clc_ldexp` to prevent signed integer overflow, clamp shift counts, and apply round-to-nearest-even when right-shifting into a subnormal fp32 result. Added: Modified: libclc/clc/lib/generic/math/clc_ldexp.cl Removed: ################################################################################ diff --git a/libclc/clc/lib/generic/math/clc_ldexp.cl b/libclc/clc/lib/generic/math/clc_ldexp.cl index 59db94cf047fa8..dcd7ecdf48b6b8 100644 --- a/libclc/clc/lib/generic/math/clc_ldexp.cl +++ b/libclc/clc/lib/generic/math/clc_ldexp.cl @@ -51,32 +51,21 @@ _CLC_DEF _CLC_OVERLOAD float __clc_ldexp(float x, int n) { 127 - (__clc_as_uint((float)(__clc_as_float(val_ui | 0x3f800000) - 1.0f)) >> 23); - int dexponent = 25 - fbh; - uint dval_ui = (((val_ui << fbh) & 0x007fffff) | (dexponent << 23)); - int ex = dexponent + n - multiplier; - dexponent = ex; - uint val = sign | (ex << 23) | (dval_ui & 0x007fffff); - int ex1 = dexponent + multiplier; - ex1 = -ex1 + 25; - dval_ui = (((dval_ui & 0x007fffff) | 0x800000) >> ex1); - dval_ui = dexponent > 0 ? val : dval_ui; - dval_ui = dexponent > 254 ? 0x7f800000 : dval_ui; /*overflow*/ - dval_ui = dexponent < -multiplier ? 0 : dval_ui; /*underflow*/ - dval_ui = dval_ui | sign; - val_f = __clc_as_float(dval_ui); - - exponent += n; - - val = sign | (exponent << 23) | (val_ui & 0x007fffff); - ex1 = exponent + multiplier; - ex1 = -ex1 + 25; - val_ui = (((val_ui & 0x007fffff) | 0x800000) >> ex1); + fbh = dexp == 0 ? __clc_clamp(fbh, 1, 23) : 0; + exponent = dexp == 0 ? 1 - fbh : exponent; + uint mant = (val_ui << fbh) & 0x007fffff; + + exponent = __clc_add_sat(exponent, n); + + uint val = sign | ((uint)exponent << 23) | mant; + int ex1 = __clc_clamp(1 - exponent, 1, 25); + uint full_mant = mant | 0x00800000; + val_ui = + (full_mant + ((1u << (ex1 - 1)) - 1u) + ((full_mant >> ex1) & 1u)) >> ex1; val_ui = exponent > 0 ? val : val_ui; val_ui = exponent > 254 ? 0x7f800000 : val_ui; /*overflow*/ val_ui = exponent < -multiplier ? 0 : val_ui; /*underflow*/ val_ui = val_ui | sign; - - val_ui = dexp == 0 ? dval_ui : val_ui; val_f = __clc_as_float(val_ui); val_f = (__clc_isnan(x) || __clc_isinf(x) || val_x == 0) ? x : val_f; @@ -99,7 +88,7 @@ _CLC_DEF _CLC_OVERLOAD double __clc_ldexp(double x, int n) { ux = c ? ux : l; - int v = e + n; + int v = __clc_add_sat(e, n); v = __clc_clamp(v, -0x7ff, 0x7ff); ux &= ~EXPBITS_DP64; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
