[llvm-branch-commits] [libclc] libclc: Update hypot implementation (PR #185873)

Matt Arsenault via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Mar 11 06:14:42 PDT 2026


https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/185873

>From b157e09202fe937d1004f15d47eb156bfeda01f8 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Wed, 11 Mar 2026 12:49:59 +0100
Subject: [PATCH] libclc: Update hypot implementation

This avoids bithacking on the values and improves value
tracking.
---
 libclc/clc/lib/generic/math/clc_hypot.cl  |  14 +--
 libclc/clc/lib/generic/math/clc_hypot.inc | 101 +++++++---------------
 2 files changed, 40 insertions(+), 75 deletions(-)

diff --git a/libclc/clc/lib/generic/math/clc_hypot.cl b/libclc/clc/lib/generic/math/clc_hypot.cl
index 8eef0a5a58247..59a4486c00501 100644
--- a/libclc/clc/lib/generic/math/clc_hypot.cl
+++ b/libclc/clc/lib/generic/math/clc_hypot.cl
@@ -7,15 +7,17 @@
 //===----------------------------------------------------------------------===//
 
 #include "clc/clc_convert.h"
-#include "clc/integer/clc_abs.h"
+#include "clc/float/definitions.h"
 #include "clc/internal/clc.h"
-#include "clc/math/clc_fma.h"
+#include "clc/math/clc_fabs.h"
+#include "clc/math/clc_fmax.h"
+#include "clc/math/clc_frexp.h"
+#include "clc/math/clc_ldexp.h"
 #include "clc/math/clc_mad.h"
-#include "clc/math/clc_sqrt.h"
-#include "clc/math/clc_subnormal_config.h"
+#include "clc/math/clc_sqrt_fast.h"
 #include "clc/math/math.h"
-#include "clc/relational/clc_isnan.h"
-#include "clc/shared/clc_clamp.h"
+#include "clc/relational/clc_isinf.h"
+#include "clc/relational/clc_isunordered.h"
 
 #define __CLC_BODY "clc_hypot.inc"
 #include "clc/math/gentype.inc"
diff --git a/libclc/clc/lib/generic/math/clc_hypot.inc b/libclc/clc/lib/generic/math/clc_hypot.inc
index 2fa91620b1fa8..2321fb3dcbeb4 100644
--- a/libclc/clc/lib/generic/math/clc_hypot.inc
+++ b/libclc/clc/lib/generic/math/clc_hypot.inc
@@ -10,85 +10,48 @@
 // warrants it
 
 #if __CLC_FPSIZE == 32
-_CLC_DEF _CLC_OVERLOAD __CLC_GENTYPE __clc_hypot(__CLC_GENTYPE x,
-                                                 __CLC_GENTYPE y) {
-  __CLC_UINTN ux = __CLC_AS_UINTN(x);
-  __CLC_UINTN aux = ux & EXSIGNBIT_SP32;
-  __CLC_UINTN uy = __CLC_AS_UINTN(y);
-  __CLC_UINTN auy = uy & EXSIGNBIT_SP32;
-  __CLC_INTN c = aux > auy;
-  ux = c ? aux : auy;
-  uy = c ? auy : aux;
-
-  __CLC_INTN xexp = __clc_clamp(
-      __CLC_AS_INTN(ux >> EXPSHIFTBITS_SP32) - EXPBIAS_SP32, -126, 126);
-  __CLC_GENTYPE fx_exp =
-      __CLC_AS_GENTYPE((xexp + EXPBIAS_SP32) << EXPSHIFTBITS_SP32);
-  __CLC_GENTYPE fi_exp =
-      __CLC_AS_GENTYPE((-xexp + EXPBIAS_SP32) << EXPSHIFTBITS_SP32);
-  __CLC_GENTYPE fx = __CLC_AS_GENTYPE(ux) * fi_exp;
-  __CLC_GENTYPE fy = __CLC_AS_GENTYPE(uy) * fi_exp;
-
-  __CLC_GENTYPE retval = __clc_sqrt(__clc_mad(fx, fx, fy * fy)) * fx_exp;
-
-  retval = (ux > PINFBITPATT_SP32 || uy == 0) ? __CLC_AS_GENTYPE(ux) : retval;
-  retval = (ux == PINFBITPATT_SP32 || uy == PINFBITPATT_SP32)
-               ? __CLC_AS_GENTYPE((__CLC_UINTN)PINFBITPATT_SP32)
-               : retval;
-  return retval;
+_CLC_OVERLOAD _CLC_DEF _CLC_CONST __CLC_GENTYPE __clc_hypot(__CLC_GENTYPE x,
+                                                            __CLC_GENTYPE y) {
+  __CLC_GENTYPE a = __clc_fabs(x);
+  __CLC_GENTYPE b = __clc_fabs(y);
+  __CLC_GENTYPE t = __clc_fmax(a, b);
+  __CLC_INTN e = __clc_frexp_exp(t);
+
+  a = __clc_ldexp(a, -e);
+  b = __clc_ldexp(b, -e);
+  __CLC_GENTYPE ret = __clc_ldexp(__clc_sqrt_fast(__clc_mad(a, a, b * b)), e);
+
+  return __clc_isinf(t) ? __CLC_GENTYPE_INF : ret;
 }
 
 #elif __CLC_FPSIZE == 64
 
-_CLC_DEF _CLC_OVERLOAD __CLC_GENTYPE __clc_hypot(__CLC_GENTYPE x,
-                                                 __CLC_GENTYPE y) {
-  __CLC_ULONGN ux = __CLC_AS_ULONGN(x) & ~SIGNBIT_DP64;
-  __CLC_INTN xexp = __CLC_CONVERT_INTN(ux >> EXPSHIFTBITS_DP64);
-  x = __CLC_AS_GENTYPE(ux);
-
-  __CLC_ULONGN uy = __CLC_AS_ULONGN(y) & ~SIGNBIT_DP64;
-  __CLC_INTN yexp = __CLC_CONVERT_INTN(uy >> EXPSHIFTBITS_DP64);
-  y = __CLC_AS_GENTYPE(uy);
-
-  __CLC_LONGN c = __CLC_CONVERT_LONGN(xexp > EXPBIAS_DP64 + 500 ||
-                                      yexp > EXPBIAS_DP64 + 500);
-  __CLC_GENTYPE preadjust = c ? 0x1.0p-600 : 1.0;
-  __CLC_GENTYPE postadjust = c ? 0x1.0p+600 : 1.0;
-
-  c = __CLC_CONVERT_LONGN(xexp < EXPBIAS_DP64 - 500 ||
-                          yexp < EXPBIAS_DP64 - 500);
-  preadjust = c ? 0x1.0p+600 : preadjust;
-  postadjust = c ? 0x1.0p-600 : postadjust;
+_CLC_OVERLOAD _CLC_DEF _CLC_CONST __CLC_GENTYPE __clc_hypot(__CLC_GENTYPE x,
+                                                            __CLC_GENTYPE y) {
+  __CLC_GENTYPE a = __clc_fabs(x);
+  __CLC_GENTYPE b = __clc_fabs(y);
+  __CLC_GENTYPE t = __clc_fmax(a, b);
+  __CLC_INTN e = __clc_frexp_exp(t);
 
-  __CLC_GENTYPE ax = x * preadjust;
-  __CLC_GENTYPE ay = y * preadjust;
+  a = __clc_ldexp(a, -e);
+  b = __clc_ldexp(b, -e);
+  __CLC_GENTYPE ret = __clc_ldexp(__clc_sqrt_fast(__clc_mad(a, a, b * b)), e);
 
-  // The post adjust may overflow, but this can't be avoided in any case
-  __CLC_GENTYPE r = __clc_sqrt(__clc_fma(ax, ax, ay * ay)) * postadjust;
-
-  // If the difference in exponents between x and y is large
-  __CLC_GENTYPE s = x + y;
-  c = __CLC_CONVERT_LONGN(__clc_abs(xexp - yexp) > MANTLENGTH_DP64 + 1);
-  r = c ? s : r;
-
-  // Check for NaN
-  c = __clc_isnan(x) || __clc_isnan(y);
-  r = c ? __CLC_AS_GENTYPE((__CLC_ULONGN)QNANBITPATT_DP64) : r;
-
-  // If either is Inf, we must return Inf
-  c = x == __CLC_AS_GENTYPE((__CLC_ULONGN)PINFBITPATT_DP64) ||
-      y == __CLC_AS_GENTYPE((__CLC_ULONGN)PINFBITPATT_DP64);
-  r = c ? __CLC_AS_GENTYPE((__CLC_ULONGN)PINFBITPATT_DP64) : r;
-
-  return r;
+  ret = __clc_isunordered(x, y) ? __CLC_GENTYPE_NAN : ret;
+  return __clc_isinf(x) || __clc_isinf(y) ? __CLC_GENTYPE_INF : ret;
 }
 
 #elif __CLC_FPSIZE == 16
 
-_CLC_DEF _CLC_OVERLOAD __CLC_GENTYPE __clc_hypot(__CLC_GENTYPE x,
-                                                 __CLC_GENTYPE y) {
-  return __CLC_CONVERT_GENTYPE(
-      __clc_hypot(__CLC_CONVERT_FLOATN(x), __CLC_CONVERT_FLOATN(y)));
+_CLC_OVERLOAD _CLC_DEF _CLC_CONST __CLC_GENTYPE __clc_hypot(__CLC_GENTYPE x,
+                                                            __CLC_GENTYPE y) {
+  __CLC_FLOATN fx = __CLC_CONVERT_FLOATN(x);
+  __CLC_FLOATN fy = __CLC_CONVERT_FLOATN(y);
+  __CLC_FLOATN d2 = __clc_mad(fx, fx, fy * fy);
+
+  __CLC_GENTYPE ret = __CLC_CONVERT_HALFN(__clc_sqrt_fast(d2));
+
+  return __clc_isinf(x) || __clc_isinf(y) ? __CLC_GENTYPE_INF : ret;
 }
 
 #endif



More information about the llvm-branch-commits mailing list