https://github.com/frasercrmck updated 
https://github.com/llvm/llvm-project/pull/127469

>From dbe1d8d133a54d0353fdb466cd59f5931d670bbf Mon Sep 17 00:00:00 2001
From: Fraser Cormack <fra...@codeplay.com>
Date: Mon, 17 Feb 2025 10:17:44 +0000
Subject: [PATCH 1/2] [libclc] Improve nextafter behaviour around zero

This commit improves the behaviour of (__clc_)nextafter around zero.
Specifically, the nextafter value of very small negative numbers in the
positive direction is now negative zero. Previously we'd return positive
zero.

This behaviour is not required as far as OpenCL is concerned: at
least, the CTS isn't testing for it. However, this change does bring our
implementation into bit-equivalence with (libstdc++'s implementation of)
std::nextafter, tested on all possible values of 32-bit float towards
both positive and negative INFINITY.

Furthermore, since the implementation of libclc's floating-point 'rtp'
and 'rtz' conversions use __clc_nextafter, the previous behaviour was
resulting in CTS validation issues. For example, when converting float
-0x1.000002p-25 to half, rounding towards zero or positive infinity,
nextafter was returning +0.0, whereas the correct conversion requires
us to return -0.0.

We could work around this issue in the conversion functions, but since
the change to nextafter is small enough and the behaviour around zero
matches libstdc++, the fix feels at home there.

This commit also converts several variables to unsigned types to avoid
undefined behaviour surrounding signed underflow on the subtractions.
---
 libclc/clc/lib/generic/math/clc_nextafter.cl | 28 ++++++++++++--------
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/libclc/clc/lib/generic/math/clc_nextafter.cl 
b/libclc/clc/lib/generic/math/clc_nextafter.cl
index 58125485bf684..eb467a123b66f 100644
--- a/libclc/clc/lib/generic/math/clc_nextafter.cl
+++ b/libclc/clc/lib/generic/math/clc_nextafter.cl
@@ -13,19 +13,25 @@
     const UINT_TYPE sign_bit = (UINT_TYPE)1                                    
\
                                << (sizeof(INT_TYPE_SCALAR) * 8 - 1);           
\
     const UINT_TYPE sign_bit_mask = sign_bit - (UINT_TYPE)1;                   
\
-    INT_TYPE ix = CLC_AS_TYPE(INT_TYPE)(x);                                    
\
-    UINT_TYPE ax = CLC_AS_TYPE(UINT_TYPE)(ix) & sign_bit_mask;                 
\
-    INT_TYPE mx = CLC_AS_TYPE(INT_TYPE)(sign_bit) - ix;                        
\
-    mx = CLC_AS_TYPE(INT_TYPE)(ix) < (INT_TYPE)0 ? mx : ix;                    
\
-    INT_TYPE iy = CLC_AS_TYPE(INT_TYPE)(y);                                    
\
-    UINT_TYPE ay = CLC_AS_TYPE(UINT_TYPE)(iy) & sign_bit_mask;                 
\
-    INT_TYPE my = CLC_AS_TYPE(INT_TYPE)(sign_bit) - iy;                        
\
-    my = iy < (INT_TYPE)0 ? my : iy;                                           
\
+    UINT_TYPE ix = CLC_AS_TYPE(UINT_TYPE)(x);                                  
\
+    UINT_TYPE ax = ix & sign_bit_mask;                                         
\
+    UINT_TYPE mxu = sign_bit - ix;                                             
\
+    INT_TYPE mx = CLC_AS_TYPE(INT_TYPE)(mxu);                                  
\
+    mx = CLC_AS_TYPE(INT_TYPE)(ix) < (INT_TYPE)0 ? mx                          
\
+                                                 : CLC_AS_TYPE(INT_TYPE)(ix);  
\
+    UINT_TYPE iy = CLC_AS_TYPE(UINT_TYPE)(y);                                  
\
+    UINT_TYPE ay = iy & sign_bit_mask;                                         
\
+    UINT_TYPE myu = sign_bit - iy;                                             
\
+    INT_TYPE my = CLC_AS_TYPE(INT_TYPE)(myu);                                  
\
+    my = CLC_AS_TYPE(INT_TYPE)(iy) < (INT_TYPE)0 ? my                          
\
+                                                 : CLC_AS_TYPE(INT_TYPE)(iy);  
\
     INT_TYPE t = mx + (mx < my ? (INT_TYPE)1 : (INT_TYPE)-1);                  
\
-    INT_TYPE r = CLC_AS_TYPE(INT_TYPE)(sign_bit) - t;                          
\
-    r = t < (INT_TYPE)0 ? r : t;                                               
\
+    UINT_TYPE r = sign_bit - CLC_AS_TYPE(UINT_TYPE)(t);                        
\
+    r = (t < (INT_TYPE)0 || (t == (INT_TYPE)0 && mx < my))                     
\
+            ? r                                                                
\
+            : CLC_AS_TYPE(UINT_TYPE)(t);                                       
\
     r = __clc_isnan(x) ? ix : r;                                               
\
-    r = __clc_isnan(y) ? CLC_AS_TYPE(INT_TYPE)(iy) : r;                        
\
+    r = __clc_isnan(y) ? iy : r;                                               
\
     r = ((ax | ay) == (UINT_TYPE)0 || ix == iy) ? iy : r;                      
\
     return CLC_AS_TYPE(FLOAT_TYPE)(r);                                         
\
   }

>From e25ac415b99b5b3c398d67ba708dd8428d152624 Mon Sep 17 00:00:00 2001
From: Fraser Cormack <fra...@codeplay.com>
Date: Wed, 19 Feb 2025 09:54:11 +0000
Subject: [PATCH 2/2] change abs vars to float

---
 libclc/clc/lib/generic/math/clc_nextafter.cl | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/libclc/clc/lib/generic/math/clc_nextafter.cl 
b/libclc/clc/lib/generic/math/clc_nextafter.cl
index eb467a123b66f..f77f3647d5985 100644
--- a/libclc/clc/lib/generic/math/clc_nextafter.cl
+++ b/libclc/clc/lib/generic/math/clc_nextafter.cl
@@ -1,5 +1,6 @@
 #include <clc/clcmacro.h>
 #include <clc/internal/clc.h>
+#include <clc/math/clc_fabs.h>
 #include <clc/relational/clc_isnan.h>
 
 // This file provides OpenCL C implementations of __clc_nextafter for
@@ -12,15 +13,14 @@
                                                     FLOAT_TYPE y) {            
\
     const UINT_TYPE sign_bit = (UINT_TYPE)1                                    
\
                                << (sizeof(INT_TYPE_SCALAR) * 8 - 1);           
\
-    const UINT_TYPE sign_bit_mask = sign_bit - (UINT_TYPE)1;                   
\
     UINT_TYPE ix = CLC_AS_TYPE(UINT_TYPE)(x);                                  
\
-    UINT_TYPE ax = ix & sign_bit_mask;                                         
\
+    FLOAT_TYPE absx = __clc_fabs(x);                                           
\
     UINT_TYPE mxu = sign_bit - ix;                                             
\
     INT_TYPE mx = CLC_AS_TYPE(INT_TYPE)(mxu);                                  
\
     mx = CLC_AS_TYPE(INT_TYPE)(ix) < (INT_TYPE)0 ? mx                          
\
                                                  : CLC_AS_TYPE(INT_TYPE)(ix);  
\
     UINT_TYPE iy = CLC_AS_TYPE(UINT_TYPE)(y);                                  
\
-    UINT_TYPE ay = iy & sign_bit_mask;                                         
\
+    FLOAT_TYPE absy = __clc_fabs(y);                                           
\
     UINT_TYPE myu = sign_bit - iy;                                             
\
     INT_TYPE my = CLC_AS_TYPE(INT_TYPE)(myu);                                  
\
     my = CLC_AS_TYPE(INT_TYPE)(iy) < (INT_TYPE)0 ? my                          
\
@@ -32,7 +32,11 @@
             : CLC_AS_TYPE(UINT_TYPE)(t);                                       
\
     r = __clc_isnan(x) ? ix : r;                                               
\
     r = __clc_isnan(y) ? iy : r;                                               
\
-    r = ((ax | ay) == (UINT_TYPE)0 || ix == iy) ? iy : r;                      
\
+    r = ((CLC_AS_TYPE(UINT_TYPE)(absx) | CLC_AS_TYPE(UINT_TYPE)(absy)) ==      
\
+             (UINT_TYPE)0 ||                                                   
\
+         ix == iy)                                                             
\
+            ? iy                                                               
\
+            : r;                                                               
\
     return CLC_AS_TYPE(FLOAT_TYPE)(r);                                         
\
   }
 

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to