https://github.com/rjodinchr created 
https://github.com/llvm/llvm-project/pull/233787

In fp32 `__clc_erfc`, inputs with large magnitude (`|x| >= 2^64` or `inf`) 
overflow `-x * x` to `-inf`, causing `__clc_fma(-x, x, -x2h)` and 
`__clc_erfc_scaled(ax)` to produce `NaN` prior to the `ax > 0x1.41bbf8p+3f ? 
0.0f : ret` clamp. On some target where vector `select(cond, ret, 0.0f)` is 
lowered to `ret * (cond ? 1.0f : 0.0f)`, `NaN * 0.0f` propagates `NaN` instead 
of returning `0.0f` (for `x > 0`) or `2.0f` (for `x < 0`), failing vector erfc 
in OpenCL CTS bruteforce.

Clamp `ax` before evaluating the polynomial so `ret` remains finite for 
out-of-range inputs while preserving `NaN` propagation when `x` is `NaN`.


>From 2cafdc1607ed8ecfb32da12f76cc6b3771cc3138 Mon Sep 17 00:00:00 2001
From: Romaric Jodin <[email protected]>
Date: Tue, 20 Oct 2026 11:13:50 +0200
Subject: [PATCH] [libclc] Avoid intermediate NaN for large inputs in fp32 erfc

In fp32 `__clc_erfc`, inputs with large magnitude (`|x| >= 2^64` or
`inf`) overflow `-x * x` to `-inf`, causing `__clc_fma(-x, x, -x2h)`
and `__clc_erfc_scaled(ax)` to produce `NaN` prior to the
`ax > 0x1.41bbf8p+3f ? 0.0f : ret` clamp. On some target where vector
`select(cond, ret, 0.0f)` is lowered to `ret * (cond ? 1.0f : 0.0f)`,
`NaN * 0.0f` propagates `NaN` instead of returning `0.0f` (for
`x > 0`) or `2.0f` (for `x < 0`), failing vector erfc in OpenCL CTS
bruteforce.

Clamp `ax` before evaluating the polynomial so `ret` remains finite
for out-of-range inputs while preserving `NaN` propagation when `x` is
`NaN`.

Change-Id: I2660139949901c115cca82e87ae91363241bbd8d
---
 libclc/clc/lib/generic/math/clc_erfc.inc | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/libclc/clc/lib/generic/math/clc_erfc.inc 
b/libclc/clc/lib/generic/math/clc_erfc.inc
index 8472a819d36609..796fb27de5dc00 100644
--- a/libclc/clc/lib/generic/math/clc_erfc.inc
+++ b/libclc/clc/lib/generic/math/clc_erfc.inc
@@ -146,11 +146,12 @@ __clc_erfc_scaled(__CLC_FLOATN x) {
 
 _CLC_DEF _CLC_OVERLOAD _CLC_CONST __CLC_FLOATN __clc_erfc(__CLC_FLOATN x) {
   __CLC_FLOATN ax = __clc_fabs(x);
-  __CLC_FLOATN x2h = -x * x;
-  __CLC_FLOATN x2l = __clc_fma(-x, x, -x2h);
+  __CLC_FLOATN cx = ax > 0x1.41bbf8p+3f ? 0x1.41bbfcp+3f : ax;
+  __CLC_FLOATN x2h = -cx * cx;
+  __CLC_FLOATN x2l = __clc_fma(-cx, cx, -x2h);
   __CLC_FLOATN e = __clc_exp(x2h);
   e = __clc_fma(e, x2l, e);
-  __CLC_FLOATN ret = e * __clc_erfc_scaled(ax);
+  __CLC_FLOATN ret = e * __clc_erfc_scaled(cx);
   ret = ax > 0x1.41bbf8p+3f ? 0.0f : ret;
   __CLC_FLOATN nret = 2.0f - ret;
   return x < 0.0f ? nret : ret;

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to