[llvm-branch-commits] [libclc] libclc: Add canonicalize utility functions (PR #187357)

Matt Arsenault via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Mar 19 01:02:35 PDT 2026


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

>From 3665db80697a24bdc825631fd7b34f0410e01354 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Wed, 18 Mar 2026 18:47:02 +0100
Subject: [PATCH] libclc: Add canonicalize utility functions

This is mostly to work around spirv's canonicalize still
being broken.
---
 .../clc/include/clc/math/clc_canonicalize.h   | 21 +++++++++
 .../clc/include/clc/math/clc_flush_if_daz.h   | 21 +++++++++
 libclc/clc/include/clc/math/math.h            | 10 -----
 libclc/clc/lib/clspv/math/clc_sw_fma.cl       |  7 +--
 libclc/clc/lib/generic/CMakeLists.txt         |  2 +
 .../clc/lib/generic/math/clc_canonicalize.cl  | 15 +++++++
 .../clc/lib/generic/math/clc_flush_if_daz.cl  | 15 +++++++
 .../clc/lib/generic/math/clc_flush_if_daz.inc | 43 +++++++++++++++++++
 libclc/clc/lib/generic/math/clc_remquo.cl     |  1 +
 libclc/clc/lib/generic/math/clc_remquo.inc    |  4 +-
 10 files changed, 124 insertions(+), 15 deletions(-)
 create mode 100644 libclc/clc/include/clc/math/clc_canonicalize.h
 create mode 100644 libclc/clc/include/clc/math/clc_flush_if_daz.h
 create mode 100644 libclc/clc/lib/generic/math/clc_canonicalize.cl
 create mode 100644 libclc/clc/lib/generic/math/clc_flush_if_daz.cl
 create mode 100644 libclc/clc/lib/generic/math/clc_flush_if_daz.inc

diff --git a/libclc/clc/include/clc/math/clc_canonicalize.h b/libclc/clc/include/clc/math/clc_canonicalize.h
new file mode 100644
index 0000000000000..527463e5281b1
--- /dev/null
+++ b/libclc/clc/include/clc/math/clc_canonicalize.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __CLC_MATH_CLC_CANONICALIZE_H__
+#define __CLC_MATH_CLC_CANONICALIZE_H__
+
+#include "clc/internal/clc.h"
+
+#define __CLC_BODY "clc/math/unary_decl.inc"
+#define __CLC_FUNCTION __clc_canonicalize
+
+#include "clc/math/gentype.inc"
+
+#undef __CLC_FUNCTION
+
+#endif // __CLC_MATH_CLC_CANONICALIZE_H__
diff --git a/libclc/clc/include/clc/math/clc_flush_if_daz.h b/libclc/clc/include/clc/math/clc_flush_if_daz.h
new file mode 100644
index 0000000000000..9e9bf99d9e4bc
--- /dev/null
+++ b/libclc/clc/include/clc/math/clc_flush_if_daz.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __CLC_MATH_CLC_FLUSH_IF_DAZ_H__
+#define __CLC_MATH_CLC_FLUSH_IF_DAZ_H__
+
+#include "clc/internal/clc.h"
+
+#define __CLC_BODY "clc/math/unary_decl.inc"
+#define __CLC_FUNCTION __clc_flush_if_daz
+
+#include "clc/math/gentype.inc"
+
+#undef __CLC_FUNCTION
+
+#endif // __CLC_MATH_CLC_FLUSH_IF_DAZ_H__
diff --git a/libclc/clc/include/clc/math/math.h b/libclc/clc/include/clc/math/math.h
index 15b1272b37466..a676c357f4633 100644
--- a/libclc/clc/include/clc/math/math.h
+++ b/libclc/clc/include/clc/math/math.h
@@ -58,16 +58,6 @@
 
 #define LOG_MAGIC_NUM_SP32 (1 + NUMEXPBITS_SP32 - EXPBIAS_SP32)
 
-_CLC_OVERLOAD _CLC_INLINE float __clc_flush_denormal_if_not_supported(float x) {
-  int ix = __clc_as_int(x);
-  if (__clc_denormals_are_zero_fp32() && ((ix & EXPBITS_SP32) == 0) &&
-      ((ix & MANTBITS_SP32) != 0)) {
-    ix &= SIGNBIT_SP32;
-    x = __clc_as_float(ix);
-  }
-  return x;
-}
-
 #ifdef cl_khr_fp64
 
 #define SIGNBIT_DP64 0x8000000000000000L
diff --git a/libclc/clc/lib/clspv/math/clc_sw_fma.cl b/libclc/clc/lib/clspv/math/clc_sw_fma.cl
index 306aad5142120..e73f53e6bcd76 100644
--- a/libclc/clc/lib/clspv/math/clc_sw_fma.cl
+++ b/libclc/clc/lib/clspv/math/clc_sw_fma.cl
@@ -17,6 +17,7 @@
 #include "clc/integer/clc_hadd.h"
 #include "clc/integer/clc_mul_hi.h"
 #include "clc/integer/definitions.h"
+#include "clc/math/clc_flush_if_daz.h"
 #include "clc/math/clc_mad.h"
 #include "clc/math/math.h"
 #include "clc/relational/clc_isinf.h"
@@ -127,9 +128,9 @@ _CLC_DEF _CLC_OVERLOAD float __clc_sw_fma(float a, float b, float c) {
     return c;
   }
 
-  a = __clc_flush_denormal_if_not_supported(a);
-  b = __clc_flush_denormal_if_not_supported(b);
-  c = __clc_flush_denormal_if_not_supported(c);
+  a = __clc_flush_if_daz(a);
+  b = __clc_flush_if_daz(b);
+  c = __clc_flush_if_daz(c);
 
   if (a == 0.0f || b == 0.0f) {
     return c;
diff --git a/libclc/clc/lib/generic/CMakeLists.txt b/libclc/clc/lib/generic/CMakeLists.txt
index f9eb15a0aafda..130f396b53bfd 100644
--- a/libclc/clc/lib/generic/CMakeLists.txt
+++ b/libclc/clc/lib/generic/CMakeLists.txt
@@ -66,6 +66,7 @@ libclc_configure_source_list(CLC_GENERIC_SOURCES
   math/clc_atan2pi.cl
   math/clc_atanh.cl
   math/clc_atanpi.cl
+  math/clc_canonicalize.cl
   math/clc_cbrt.cl
   math/clc_ceil.cl
   math/clc_copysign.cl
@@ -87,6 +88,7 @@ libclc_configure_source_list(CLC_GENERIC_SOURCES
   math/clc_fabs.cl
   math/clc_fdim.cl
   math/clc_floor.cl
+  math/clc_flush_if_daz.cl
   math/clc_fma.cl
   math/clc_fmax.cl
   math/clc_fmin.cl
diff --git a/libclc/clc/lib/generic/math/clc_canonicalize.cl b/libclc/clc/lib/generic/math/clc_canonicalize.cl
new file mode 100644
index 0000000000000..5b0ae52a14505
--- /dev/null
+++ b/libclc/clc/lib/generic/math/clc_canonicalize.cl
@@ -0,0 +1,15 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clc/math/clc_canonicalize.h"
+
+#define __CLC_FUNCTION __clc_canonicalize
+#define __CLC_IMPL_FUNCTION(x) __builtin_elementwise_canonicalize
+#define __CLC_BODY "clc/shared/unary_def.inc"
+
+#include "clc/math/gentype.inc"
diff --git a/libclc/clc/lib/generic/math/clc_flush_if_daz.cl b/libclc/clc/lib/generic/math/clc_flush_if_daz.cl
new file mode 100644
index 0000000000000..1abb18336eaa6
--- /dev/null
+++ b/libclc/clc/lib/generic/math/clc_flush_if_daz.cl
@@ -0,0 +1,15 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "clc/clc_convert.h"
+#include "clc/math/clc_canonicalize.h"
+#include "clc/math/clc_flush_if_daz.h"
+#include "clc/math/clc_subnormal_config.h"
+#include "clc/math/math.h"
+
+#define __CLC_BODY "clc_flush_if_daz.inc"
+#include "clc/math/gentype.inc"
diff --git a/libclc/clc/lib/generic/math/clc_flush_if_daz.inc b/libclc/clc/lib/generic/math/clc_flush_if_daz.inc
new file mode 100644
index 0000000000000..5ae1b39d6121f
--- /dev/null
+++ b/libclc/clc/lib/generic/math/clc_flush_if_daz.inc
@@ -0,0 +1,43 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#if __CLC_FPSIZE == 16
+#define __CLC_GENTYPE_EXPBITS (__CLC_S_GENTYPE) EXPBITS_FP16
+#define __CLC_GENTYPE_MANTBITS (__CLC_S_GENTYPE) MANTBITS_FP16
+#define __CLC_GENTYPE_SIGNBIT (__CLC_S_GENTYPE) SIGNBIT_FP16
+#elif __CLC_FPSIZE == 32
+#define __CLC_GENTYPE_EXPBITS (__CLC_S_GENTYPE) EXPBITS_SP32
+#define __CLC_GENTYPE_MANTBITS (__CLC_S_GENTYPE) MANTBITS_SP32
+#define __CLC_GENTYPE_SIGNBIT (__CLC_S_GENTYPE) SIGNBIT_SP32
+#elif __CLC_FPSIZE == 64
+#define __CLC_GENTYPE_EXPBITS (__CLC_S_GENTYPE) EXPBITS_DP64
+#define __CLC_GENTYPE_MANTBITS (__CLC_S_GENTYPE) MANTBITS_DP64
+#define __CLC_GENTYPE_SIGNBIT (__CLC_S_GENTYPE) SIGNBIT_DP64
+#endif
+
+_CLC_DEF _CLC_OVERLOAD __CLC_GENTYPE __clc_flush_if_daz(__CLC_GENTYPE x) {
+  if (!__CLC_GENTYPE_DENORMS_ARE_ZERO)
+    return x;
+
+  // Hack around canonicalize not working on spirv.
+#if defined(CLC_SPIRV) || defined(CLC_CLSPV)
+  __CLC_S_GENTYPE ix = __CLC_AS_S_GENTYPE(x);
+  __CLC_S_GENTYPE should_flush =
+      ((ix & __CLC_GENTYPE_EXPBITS) == (__CLC_S_GENTYPE)0) &&
+      ((ix & __CLC_GENTYPE_MANTBITS) != (__CLC_S_GENTYPE)0);
+  __CLC_S_GENTYPE signbit = ix &= __CLC_GENTYPE_SIGNBIT;
+  __CLC_S_GENTYPE result = should_flush ? signbit : ix;
+  return __CLC_AS_GENTYPE(result);
+#else
+  return __clc_canonicalize(x);
+#endif
+}
+
+#undef __CLC_GENTYPE_EXPBITS
+#undef __CLC_GENTYPE_MANTBITS
+#undef __CLC_GENTYPE_SIGNBIT
diff --git a/libclc/clc/lib/generic/math/clc_remquo.cl b/libclc/clc/lib/generic/math/clc_remquo.cl
index 6f6a7fc6bdcfa..e254093d591d4 100644
--- a/libclc/clc/lib/generic/math/clc_remquo.cl
+++ b/libclc/clc/lib/generic/math/clc_remquo.cl
@@ -10,6 +10,7 @@
 #include "clc/integer/clc_clz.h"
 #include "clc/internal/clc.h"
 #include "clc/math/clc_floor.h"
+#include "clc/math/clc_flush_if_daz.h"
 #include "clc/math/clc_fma.h"
 #include "clc/math/clc_ldexp.h"
 #include "clc/math/clc_subnormal_config.h"
diff --git a/libclc/clc/lib/generic/math/clc_remquo.inc b/libclc/clc/lib/generic/math/clc_remquo.inc
index 3a76ffed7f039..cf8a5ebcea20c 100644
--- a/libclc/clc/lib/generic/math/clc_remquo.inc
+++ b/libclc/clc/lib/generic/math/clc_remquo.inc
@@ -8,8 +8,8 @@
 
 _CLC_DEF _CLC_OVERLOAD float __clc_remquo(float x, float y,
                                           __CLC_ADDRESS_SPACE int *quo) {
-  x = __clc_flush_denormal_if_not_supported(x);
-  y = __clc_flush_denormal_if_not_supported(y);
+  x = __clc_flush_if_daz(x);
+  y = __clc_flush_if_daz(y);
   int ux = __clc_as_int(x);
   int ax = ux & EXSIGNBIT_SP32;
   float xa = __clc_as_float(ax);



More information about the llvm-branch-commits mailing list