https://github.com/rjodinchr updated https://github.com/llvm/llvm-project/pull/233823
>From 0474d7b184987d0881c8e74bbece75265b468603 Mon Sep 17 00:00:00 2001 From: Romaric Jodin <[email protected]> Date: Tue, 20 Oct 2026 14:32:45 +0200 Subject: [PATCH 1/2] [libclc] Fix exponent overflow and subnormal rounding in __clc_ldexp 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. Change-Id: I98b3412d6fd383e292aacb6a63028319fe3fda53 --- libclc/clc/lib/generic/math/clc_ldexp.cl | 37 +++++++++--------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/libclc/clc/lib/generic/math/clc_ldexp.cl b/libclc/clc/lib/generic/math/clc_ldexp.cl index 59db94cf047fa8..d5b181445300f9 100644 --- a/libclc/clc/lib/generic/math/clc_ldexp.cl +++ b/libclc/clc/lib/generic/math/clc_ldexp.cl @@ -51,32 +51,23 @@ _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 >> ex1; + uint guard = (full_mant >> (ex1 - 1)) & 1u; + uint sticky = (full_mant & ((1u << (ex1 - 1)) - 1u)) != 0u; + val_ui += guard & (sticky | (val_ui & 1u)); 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 +90,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; >From b5cf0a22dcb1a97e773d9340974a7da9bce9911b Mon Sep 17 00:00:00 2001 From: Romaric Jodin <[email protected]> Date: Fri, 23 Oct 2026 11:45:31 +0200 Subject: [PATCH 2/2] applying wenju-he feedback --- libclc/clc/lib/generic/math/clc_ldexp.cl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libclc/clc/lib/generic/math/clc_ldexp.cl b/libclc/clc/lib/generic/math/clc_ldexp.cl index d5b181445300f9..dcd7ecdf48b6b8 100644 --- a/libclc/clc/lib/generic/math/clc_ldexp.cl +++ b/libclc/clc/lib/generic/math/clc_ldexp.cl @@ -60,10 +60,8 @@ _CLC_DEF _CLC_OVERLOAD float __clc_ldexp(float x, int 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 >> ex1; - uint guard = (full_mant >> (ex1 - 1)) & 1u; - uint sticky = (full_mant & ((1u << (ex1 - 1)) - 1u)) != 0u; - val_ui += guard & (sticky | (val_ui & 1u)); + 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*/ _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
