https://github.com/Lurie97 updated 
https://github.com/llvm/llvm-project/pull/225351

>From 880a250ac09c6528837b1f2169b2b83e61391ecc Mon Sep 17 00:00:00 2001
From: jiajia Qian <[email protected]>
Date: Thu, 24 Sep 2026 14:24:50 +0800
Subject: [PATCH] [libclc] Implement isnan/isinf/isfinite without is_fpclass

#124145 changed these functions to use __builtin_isfpclass for better
vectorization. However, some targets mislower isfpclass for subnormals
when denormals are enabled, causing isfinite(subnormal) to return false.

This breaks fmod (#222369), whose |x| < |y| path can return NaN instead
of the subnormal input.

Replace is_fpclass with simple comparisons:

isnan(x) -> x != x
isinf(x) -> fabs(x) == INFINITY
isfinite(x) -> fabs(x) < INFINITY

These forms still vectorize while avoiding the isfpclass issue.
isnormal/issubnormal continue to use isfpclass because they need to
distinguish subnormal values.

Signed-off-by: jiajia Qian <[email protected]>
---
 .../clc/include/clc/relational/relational.h   | 25 +++++++++++++++++++
 .../lib/generic/relational/clc_isfinite.cl    | 11 +++++---
 .../clc/lib/generic/relational/clc_isinf.cl   | 11 +++++---
 .../clc/lib/generic/relational/clc_isnan.cl   |  7 +++---
 4 files changed, 45 insertions(+), 9 deletions(-)

diff --git a/libclc/clc/include/clc/relational/relational.h 
b/libclc/clc/include/clc/relational/relational.h
index 32ed9f431ddbdf..74c91147cfa1c1 100644
--- a/libclc/clc/include/clc/relational/relational.h
+++ b/libclc/clc/include/clc/relational/relational.h
@@ -40,8 +40,33 @@
     return _CLC_RELATIONAL_OP(x, y);                                           
\
   }
 
+// Define a unary relational builtin from an ordinary expression in terms of x.
+// The scalar version returns 1/0 and the vector versions return -1/0, matching
+// the OpenCL relational convention that ordinary comparison operators already
+// produce, so EXPR should be a plain comparison rather than 
__builtin_isfpclass
+// (which some targets mislower for subnormals when denormals are supported).
+#define _CLC_DEFINE_RELATIONAL_UNARY(RET_TYPE, VEC_RET_TYPE, __CLC_FUNCTION,   
\
+                                     EXPR, ARG_TYPE)                           
\
+  _CLC_DEF _CLC_OVERLOAD RET_TYPE __CLC_FUNCTION(ARG_TYPE x) { return EXPR; }  
\
+  _CLC_DEF _CLC_OVERLOAD VEC_RET_TYPE##2 __CLC_FUNCTION(ARG_TYPE##2 x) {       
\
+    return EXPR;                                                              \
+  }                                                                           \
+  _CLC_DEF _CLC_OVERLOAD VEC_RET_TYPE##3 __CLC_FUNCTION(ARG_TYPE##3 x) {       
\
+    return EXPR;                                                              \
+  }                                                                           \
+  _CLC_DEF _CLC_OVERLOAD VEC_RET_TYPE##4 __CLC_FUNCTION(ARG_TYPE##4 x) {       
\
+    return EXPR;                                                              \
+  }                                                                           \
+  _CLC_DEF _CLC_OVERLOAD VEC_RET_TYPE##8 __CLC_FUNCTION(ARG_TYPE##8 x) {       
\
+    return EXPR;                                                              \
+  }                                                                           \
+  _CLC_DEF _CLC_OVERLOAD VEC_RET_TYPE##16 __CLC_FUNCTION(ARG_TYPE##16 x) {     
\
+    return EXPR;                                                              \
+  }
+
 #define fcNan (__FPCLASS_SNAN | __FPCLASS_QNAN)
 #define fcInf (__FPCLASS_POSINF | __FPCLASS_NEGINF)
+
 #define fcNormal (__FPCLASS_POSNORMAL | __FPCLASS_NEGNORMAL)
 #define fcSubnormal (__FPCLASS_POSSUBNORMAL | __FPCLASS_NEGSUBNORMAL)
 #define fcPosFinite                                                            
\
diff --git a/libclc/clc/lib/generic/relational/clc_isfinite.cl 
b/libclc/clc/lib/generic/relational/clc_isfinite.cl
index dbd181e29aa172..3b9577b1029887 100644
--- a/libclc/clc/lib/generic/relational/clc_isfinite.cl
+++ b/libclc/clc/lib/generic/relational/clc_isfinite.cl
@@ -6,10 +6,13 @@
 //
 
//===----------------------------------------------------------------------===//
 
+#include "clc/float/definitions.h"
 #include "clc/internal/clc.h"
+#include "clc/math/clc_fabs.h"
 #include "clc/relational/relational.h"
 
-_CLC_DEFINE_ISFPCLASS(int, int, __clc_isfinite, fcFinite, float)
+_CLC_DEFINE_RELATIONAL_UNARY(int, int, __clc_isfinite,
+                             (__clc_fabs(x) < (float)INFINITY), float)
 
 #ifdef cl_khr_fp64
 
@@ -17,7 +20,8 @@ _CLC_DEFINE_ISFPCLASS(int, int, __clc_isfinite, fcFinite, 
float)
 
 // The scalar version of __clc_isfinite(double) returns an int, but the vector
 // versions return long.
-_CLC_DEFINE_ISFPCLASS(int, long, __clc_isfinite, fcFinite, double)
+_CLC_DEFINE_RELATIONAL_UNARY(int, long, __clc_isfinite,
+                             (__clc_fabs(x) < (double)INFINITY), double)
 
 #endif
 
@@ -27,6 +31,7 @@ _CLC_DEFINE_ISFPCLASS(int, long, __clc_isfinite, fcFinite, 
double)
 
 // The scalar version of __clc_isfinite(half) returns an int, but the vector
 // versions return short.
-_CLC_DEFINE_ISFPCLASS(int, short, __clc_isfinite, fcFinite, half)
+_CLC_DEFINE_RELATIONAL_UNARY(int, short, __clc_isfinite,
+                             (__clc_fabs(x) < (half)INFINITY), half)
 
 #endif
diff --git a/libclc/clc/lib/generic/relational/clc_isinf.cl 
b/libclc/clc/lib/generic/relational/clc_isinf.cl
index 62bb8ed063459f..5aa88c88b4cc8d 100644
--- a/libclc/clc/lib/generic/relational/clc_isinf.cl
+++ b/libclc/clc/lib/generic/relational/clc_isinf.cl
@@ -6,10 +6,13 @@
 //
 
//===----------------------------------------------------------------------===//
 
+#include "clc/float/definitions.h"
 #include "clc/internal/clc.h"
+#include "clc/math/clc_fabs.h"
 #include "clc/relational/relational.h"
 
-_CLC_DEFINE_ISFPCLASS(int, int, __clc_isinf, fcInf, float)
+_CLC_DEFINE_RELATIONAL_UNARY(int, int, __clc_isinf,
+                             (__clc_fabs(x) == (float)INFINITY), float)
 
 #ifdef cl_khr_fp64
 
@@ -17,7 +20,8 @@ _CLC_DEFINE_ISFPCLASS(int, int, __clc_isinf, fcInf, float)
 
 // The scalar version of __clc_isinf(double) returns an int, but the vector
 // versions return long.
-_CLC_DEFINE_ISFPCLASS(int, long, __clc_isinf, fcInf, double)
+_CLC_DEFINE_RELATIONAL_UNARY(int, long, __clc_isinf,
+                             (__clc_fabs(x) == (double)INFINITY), double)
 
 #endif
 
@@ -27,6 +31,7 @@ _CLC_DEFINE_ISFPCLASS(int, long, __clc_isinf, fcInf, double)
 
 // The scalar version of __clc_isinf(half) returns an int, but the vector
 // versions return short.
-_CLC_DEFINE_ISFPCLASS(int, short, __clc_isinf, fcInf, half)
+_CLC_DEFINE_RELATIONAL_UNARY(int, short, __clc_isinf,
+                             (__clc_fabs(x) == (half)INFINITY), half)
 
 #endif
diff --git a/libclc/clc/lib/generic/relational/clc_isnan.cl 
b/libclc/clc/lib/generic/relational/clc_isnan.cl
index ba97f88ce76f7b..dc7d691a050d0b 100644
--- a/libclc/clc/lib/generic/relational/clc_isnan.cl
+++ b/libclc/clc/lib/generic/relational/clc_isnan.cl
@@ -9,7 +9,7 @@
 #include "clc/internal/clc.h"
 #include "clc/relational/relational.h"
 
-_CLC_DEFINE_ISFPCLASS(int, int, __clc_isnan, fcNan, float)
+_CLC_DEFINE_RELATIONAL_UNARY(int, int, __clc_isnan, (x != x), float)
 
 #ifdef cl_khr_fp64
 
@@ -17,7 +17,7 @@ _CLC_DEFINE_ISFPCLASS(int, int, __clc_isnan, fcNan, float)
 
 // The scalar version of __clc_isnan(double) returns an int, but the vector
 // versions return a long.
-_CLC_DEFINE_ISFPCLASS(int, long, __clc_isnan, fcNan, double)
+_CLC_DEFINE_RELATIONAL_UNARY(int, long, __clc_isnan, (x != x), double)
 
 #endif
 
@@ -27,6 +27,7 @@ _CLC_DEFINE_ISFPCLASS(int, long, __clc_isnan, fcNan, double)
 
 // The scalar version of __clc_isnan(half) returns an int, but the vector
 // versions return a short.
-_CLC_DEFINE_ISFPCLASS(int, short, __clc_isnan, fcNan, half)
+_CLC_DEFINE_RELATIONAL_UNARY(int, short, __clc_isnan, (x != x), half)
 
 #endif
+

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

Reply via email to