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
