[libclc] [libclc] Move sign to the CLC builtins library (PR #115699)

Fraser Cormack via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 12 07:27:15 PST 2024


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

>From 47512ee4162318160964f1af132be90bed67c90c Mon Sep 17 00:00:00 2001
From: Fraser Cormack <fraser at codeplay.com>
Date: Thu, 7 Nov 2024 12:40:56 +0000
Subject: [PATCH 1/2] [libclc] Move sign to the CLC builtins library

This patch necessitates some changes to how CLSPV and SPIR-V targets are
built. This is the first patch in this series in which an OpenCL
function declaration has been called from the CLC library for these
targets. Since libclc's OpenCL headers aren't being included at this
stage, the OpenCL sign function isn't available. To fix this, these two
libclc targets now have clang declare OpenCL builtins when building the
internal CLC library.

The SPIR-V target also needs an extra inlining step when linking CLC
functions into the OpenCL library in order to minimize changes. Opt just
runs the always-inline pass, as the SPIR-V target has advertised that it
doesn't want to do much optimization. There are still bitcode changes,
and llvm-diff crashes (#38385) but the differences look harmless -
mostly allocas as a result of inlining. The clc_sign function is no
longer publicly available from the SPIR-V libclc builtins libraries.

The __CLC_INTERNAL preprocessor definition has been repurposed (without
the leading underscores) to be passed when building the internal CLC
library. It was only used in one other place to guard an extra maths
preprocessor definition, which we can do unconditionally.

There are no changes (with llvm-diff) to any other libclc target.
---
 libclc/CMakeLists.txt                         | 25 ++++--
 libclc/clc/include/clc/clcfunc.h              |  7 +-
 libclc/clc/include/clc/common/clc_sign.h      | 10 +++
 libclc/clc/include/clc/common/floatn.inc      | 85 +++++++++++++++++++
 libclc/clc/include/clc/common/unary_def.inc   |  7 ++
 libclc/clc/lib/generic/SOURCES                |  1 +
 libclc/clc/lib/generic/common/clc_sign.cl     | 38 +++++++++
 libclc/clc/lib/spirv/SOURCES                  |  1 +
 libclc/clc/lib/spirv64/SOURCES                |  1 +
 libclc/cmake/modules/AddLibclc.cmake          | 28 +++---
 .../generic/include/clc/float/definitions.h   |  4 +-
 libclc/generic/lib/common/sign.cl             | 37 +-------
 12 files changed, 184 insertions(+), 60 deletions(-)
 create mode 100644 libclc/clc/include/clc/common/clc_sign.h
 create mode 100644 libclc/clc/include/clc/common/floatn.inc
 create mode 100644 libclc/clc/include/clc/common/unary_def.inc
 create mode 100644 libclc/clc/lib/generic/common/clc_sign.cl

diff --git a/libclc/CMakeLists.txt b/libclc/CMakeLists.txt
index 2c2c7f16e29442..7c966c8b52677c 100644
--- a/libclc/CMakeLists.txt
+++ b/libclc/CMakeLists.txt
@@ -322,7 +322,9 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
 
     if ( ARCH STREQUAL spirv OR ARCH STREQUAL spirv64 )
       set( build_flags -O0 -finline-hint-functions -DCLC_SPIRV )
-      set( opt_flags )
+      set( clc_opt_flags )
+      # Inline CLC functions into OpenCL builtins
+      set( opencl_opt_flags "--passes=always-inline" )
       set( spvflags --spirv-max-version=1.1 )
       set( MACRO_ARCH SPIRV32 )
       if( ARCH STREQUAL spirv64 )
@@ -330,14 +332,16 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
       endif()
     elseif( ARCH STREQUAL clspv OR ARCH STREQUAL clspv64 )
       set( build_flags "-Wno-unknown-assumption" -DCLC_CLSPV )
-      set( opt_flags -O3 )
+      set( clc_opt_flags -O3 )
+      set( opencl_opt_flags -O3 )
       set( MACRO_ARCH CLSPV32 )
       if( ARCH STREQUAL clspv64 )
         set( MACRO_ARCH CLSPV64 )
       endif()
     else()
       set( build_flags )
-      set( opt_flags -O3 )
+      set( clc_opt_flags -O3 )
+      set( opencl_opt_flags -O3 )
       set( MACRO_ARCH ${ARCH} )
     endif()
 
@@ -347,7 +351,6 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
     string( TOUPPER "CLC_${MACRO_ARCH}" CLC_TARGET_DEFINE )
 
     list( APPEND build_flags
-      -D__CLC_INTERNAL
       -D${CLC_TARGET_DEFINE}
       # All libclc builtin libraries see CLC headers
       -I${CMAKE_CURRENT_SOURCE_DIR}/clc/include
@@ -359,13 +362,21 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
       list( APPEND build_flags -mcpu=${cpu} )
     endif()
 
+    set( clc_build_flags ${build_flags} -DCLC_INTERNAL )
+
+    # clspv and spir-v targets remap some CLC functions to OpenCL builtins.
+    # Automatically provide those declarations to the compiler for CLC builtins.
+    if ( ARCH STREQUAL spirv OR ARCH STREQUAL spirv64 OR ARCH STREQUAL clspv OR ARCH STREQUAL clspv64 )
+      list( APPEND clc_build_flags -Xclang -fdeclare-opencl-builtins )
+    endif()
+
     add_libclc_builtin_set(
       CLC_INTERNAL
       ARCH ${ARCH}
       ARCH_SUFFIX clc-${arch_suffix}
       TRIPLE ${clang_triple}
-      COMPILE_FLAGS ${build_flags}
-      OPT_FLAGS ${opt_flags}
+      COMPILE_FLAGS ${clc_build_flags}
+      OPT_FLAGS ${clc_opt_flags}
       LIB_FILES ${clc_lib_files}
     )
 
@@ -378,7 +389,7 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
       ARCH_SUFFIX ${arch_suffix}
       TRIPLE ${clang_triple}
       COMPILE_FLAGS ${build_flags}
-      OPT_FLAGS ${opt_flags}
+      OPT_FLAGS ${opencl_opt_flags}
       LIB_FILES ${opencl_lib_files}
       GEN_FILES ${opencl_gen_files}
       ALIASES ${${d}_aliases}
diff --git a/libclc/clc/include/clc/clcfunc.h b/libclc/clc/include/clc/clcfunc.h
index 4698f0950d8a8e..825fb4a1bdd7b6 100644
--- a/libclc/clc/include/clc/clcfunc.h
+++ b/libclc/clc/include/clc/clcfunc.h
@@ -5,9 +5,10 @@
 #define _CLC_DECL
 #define _CLC_INLINE __attribute__((always_inline)) inline
 
-// avoid inlines for SPIR-V related targets since we'll optimise later in the
-// chain
-#if defined(CLC_SPIRV)
+// Avoid inlines for user-facing builtins on SPIR-V targets since we'll optimise
+// later in the chain. Functions in the internal CLC library should be inlined,
+// though.
+#if defined(CLC_SPIRV) && !defined(CLC_INTERNAL)
 #define _CLC_DEF
 #elif defined(CLC_CLSPV)
 #define _CLC_DEF __attribute__((noinline)) __attribute__((clspv_libclc_builtin))
diff --git a/libclc/clc/include/clc/common/clc_sign.h b/libclc/clc/include/clc/common/clc_sign.h
new file mode 100644
index 00000000000000..1847fbf69bf60c
--- /dev/null
+++ b/libclc/clc/include/clc/common/clc_sign.h
@@ -0,0 +1,10 @@
+#ifndef __CLC_COMMON_CLC_SIGN_H__
+#define __CLC_COMMON_CLC_SIGN_H__
+
+#define __CLC_FUNCTION __clc_sign
+#define __CLC_BODY <clc/math/unary_decl.inc>
+#include <clc/math/gentype.inc>
+#undef __CLC_FUNCTION
+#undef __CLC_BODY
+
+#endif // __CLC_COMMON_CLC_SIGN_H__
diff --git a/libclc/clc/include/clc/common/floatn.inc b/libclc/clc/include/clc/common/floatn.inc
new file mode 100644
index 00000000000000..2c4285d5bcbc58
--- /dev/null
+++ b/libclc/clc/include/clc/common/floatn.inc
@@ -0,0 +1,85 @@
+#define __CLC_FLOATN float
+#include __CLC_BODY
+#undef __CLC_FLOATN
+
+#define __CLC_FLOATN float2
+#include __CLC_BODY
+#undef __CLC_FLOATN
+
+#define __CLC_FLOATN float3
+#include __CLC_BODY
+#undef __CLC_FLOATN
+
+#define __CLC_FLOATN float4
+#include __CLC_BODY
+#undef __CLC_FLOATN
+
+#define __CLC_FLOATN float8
+#include __CLC_BODY
+#undef __CLC_FLOATN
+
+#define __CLC_FLOATN float16
+#include __CLC_BODY
+#undef __CLC_FLOATN
+
+#undef __CLC_FLOAT
+#undef __CLC_INT
+
+#ifdef cl_khr_fp64
+#pragma OPENCL EXTENSION cl_khr_fp64 : enable
+
+#define __CLC_FLOATN double
+#include __CLC_BODY
+#undef __CLC_FLOATN
+
+#define __CLC_FLOATN double2
+#include __CLC_BODY
+#undef __CLC_FLOATN
+
+#define __CLC_FLOATN double3
+#include __CLC_BODY
+#undef __CLC_FLOATN
+
+#define __CLC_FLOATN double4
+#include __CLC_BODY
+#undef __CLC_FLOATN
+
+#define __CLC_FLOATN double8
+#include __CLC_BODY
+#undef __CLC_FLOATN
+
+#define __CLC_FLOATN double16
+#include __CLC_BODY
+#undef __CLC_FLOATN
+
+#endif
+#ifdef cl_khr_fp16
+#pragma OPENCL EXTENSION cl_khr_fp16 : enable
+
+#define __CLC_FLOATN half
+#include __CLC_BODY
+#undef __CLC_FLOATN
+
+#define __CLC_FLOATN half2
+#include __CLC_BODY
+#undef __CLC_FLOATN
+
+#define __CLC_FLOATN half3
+#include __CLC_BODY
+#undef __CLC_FLOATN
+
+#define __CLC_FLOATN half4
+#include __CLC_BODY
+#undef __CLC_FLOATN
+
+#define __CLC_FLOATN half8
+#include __CLC_BODY
+#undef __CLC_FLOATN
+
+#define __CLC_FLOATN half16
+#include __CLC_BODY
+#undef __CLC_FLOATN
+
+#endif
+
+#undef __CLC_BODY
diff --git a/libclc/clc/include/clc/common/unary_def.inc b/libclc/clc/include/clc/common/unary_def.inc
new file mode 100644
index 00000000000000..d4a3bf80775f0e
--- /dev/null
+++ b/libclc/clc/include/clc/common/unary_def.inc
@@ -0,0 +1,7 @@
+#include <clc/utils.h>
+
+#define __CLC_FUNCTION(x) __CLC_CONCAT(__clc_, x)
+
+_CLC_OVERLOAD _CLC_DEF __CLC_FLOATN FUNCTION(__CLC_FLOATN a) {
+  return __CLC_FUNCTION(FUNCTION)(a);
+}
diff --git a/libclc/clc/lib/generic/SOURCES b/libclc/clc/lib/generic/SOURCES
index d7ffaaf6dc3f42..133705f9c1c96d 100644
--- a/libclc/clc/lib/generic/SOURCES
+++ b/libclc/clc/lib/generic/SOURCES
@@ -1,3 +1,4 @@
+common/clc_sign.cl
 geometric/clc_dot.cl
 integer/clc_abs.cl
 integer/clc_abs_diff.cl
diff --git a/libclc/clc/lib/generic/common/clc_sign.cl b/libclc/clc/lib/generic/common/clc_sign.cl
new file mode 100644
index 00000000000000..6c4db4af3f4c57
--- /dev/null
+++ b/libclc/clc/lib/generic/common/clc_sign.cl
@@ -0,0 +1,38 @@
+#include <clc/clcmacro.h>
+#include <clc/internal/clc.h>
+#include <clc/relational/clc_isnan.h>
+
+#define CLC_SIGN(TYPE, F)                                                      \
+  _CLC_DEF _CLC_OVERLOAD TYPE __clc_sign(TYPE x) {                             \
+    if (__clc_isnan(x)) {                                                      \
+      return 0.0F;                                                             \
+    }                                                                          \
+    if (x > 0.0F) {                                                            \
+      return 1.0F;                                                             \
+    }                                                                          \
+    if (x < 0.0F) {                                                            \
+      return -1.0F;                                                            \
+    }                                                                          \
+    return x; /* -0.0 or +0.0 */                                               \
+  }
+
+CLC_SIGN(float, f)
+_CLC_UNARY_VECTORIZE(_CLC_OVERLOAD _CLC_DEF, float, __clc_sign, float)
+
+#ifdef cl_khr_fp64
+
+#pragma OPENCL EXTENSION cl_khr_fp64 : enable
+
+CLC_SIGN(double, )
+_CLC_UNARY_VECTORIZE(_CLC_OVERLOAD _CLC_DEF, double, __clc_sign, double)
+
+#endif
+
+#ifdef cl_khr_fp16
+
+#pragma OPENCL EXTENSION cl_khr_fp16 : enable
+
+CLC_SIGN(half, )
+_CLC_UNARY_VECTORIZE(_CLC_OVERLOAD _CLC_DEF, half, __clc_sign, half)
+
+#endif
diff --git a/libclc/clc/lib/spirv/SOURCES b/libclc/clc/lib/spirv/SOURCES
index d8effd19613c8b..20e869863e00a2 100644
--- a/libclc/clc/lib/spirv/SOURCES
+++ b/libclc/clc/lib/spirv/SOURCES
@@ -1,2 +1,3 @@
+../generic/common/clc_sign.cl
 ../generic/geometric/clc_dot.cl
 
diff --git a/libclc/clc/lib/spirv64/SOURCES b/libclc/clc/lib/spirv64/SOURCES
index 9200810ace38e7..befbc7052982a1 100644
--- a/libclc/clc/lib/spirv64/SOURCES
+++ b/libclc/clc/lib/spirv64/SOURCES
@@ -1 +1,2 @@
+../generic/common/clc_sign.cl
 ../generic/geometric/clc_dot.cl
diff --git a/libclc/cmake/modules/AddLibclc.cmake b/libclc/cmake/modules/AddLibclc.cmake
index ee7c8500c8359f..f7acd79ad58f50 100644
--- a/libclc/cmake/modules/AddLibclc.cmake
+++ b/libclc/cmake/modules/AddLibclc.cmake
@@ -305,20 +305,6 @@ function(add_libclc_builtin_set)
 
   set( builtins_link_lib $<TARGET_PROPERTY:${builtins_link_lib_tgt},TARGET_FILE> )
 
-  if( ARG_ARCH STREQUAL spirv OR ARG_ARCH STREQUAL spirv64 )
-    set( spv_suffix ${ARG_ARCH_SUFFIX}.spv )
-    add_custom_command( OUTPUT ${spv_suffix}
-      COMMAND ${llvm-spirv_exe} ${spvflags} -o ${spv_suffix} ${builtins_link_lib}
-      DEPENDS ${llvm-spirv_target} ${builtins_link_lib} ${builtins_link_lib_tgt}
-    )
-    add_custom_target( "prepare-${spv_suffix}" ALL DEPENDS "${spv_suffix}" )
-    set_target_properties( "prepare-${spv_suffix}" PROPERTIES FOLDER "libclc/Device IR/Prepare" )
-    install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${spv_suffix}
-       DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" )
-
-    return()
-  endif()
-
   set( builtins_opt_lib_tgt builtins.opt.${ARG_ARCH_SUFFIX} )
 
   # Add opt target
@@ -337,6 +323,20 @@ function(add_libclc_builtin_set)
 
   set( builtins_opt_lib $<TARGET_PROPERTY:${builtins_opt_lib_tgt},TARGET_FILE> )
 
+  if( ARG_ARCH STREQUAL spirv OR ARG_ARCH STREQUAL spirv64 )
+    set( spv_suffix ${ARG_ARCH_SUFFIX}.spv )
+    add_custom_command( OUTPUT ${spv_suffix}
+      COMMAND ${llvm-spirv_exe} ${spvflags} -o ${spv_suffix} ${builtins_opt_lib}
+      DEPENDS ${llvm-spirv_target} ${builtins_opt_lib} ${builtins_opt_lib_tgt}
+    )
+    add_custom_target( "prepare-${spv_suffix}" ALL DEPENDS "${spv_suffix}" )
+    set_target_properties( "prepare-${spv_suffix}" PROPERTIES FOLDER "libclc/Device IR/Prepare" )
+    install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${spv_suffix}
+       DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" )
+
+    return()
+  endif()
+
   # Add prepare target
   set( obj_suffix ${ARG_ARCH_SUFFIX}.bc )
   add_custom_command( OUTPUT ${obj_suffix}
diff --git a/libclc/generic/include/clc/float/definitions.h b/libclc/generic/include/clc/float/definitions.h
index 62501230c92de2..be3d0130f3e614 100644
--- a/libclc/generic/include/clc/float/definitions.h
+++ b/libclc/generic/include/clc/float/definitions.h
@@ -31,9 +31,7 @@
 #define M_SQRT2_F       0x1.6a09e6p+0f
 #define M_SQRT1_2_F     0x1.6a09e6p-1f
 
-#ifdef __CLC_INTERNAL
-#define M_LOG210_F      0x1.a934f0p+1f
-#endif
+#define M_LOG210_F 0x1.a934f0p+1f
 
 #ifdef cl_khr_fp64
 
diff --git a/libclc/generic/lib/common/sign.cl b/libclc/generic/lib/common/sign.cl
index ad8f7405e0cb30..5e70ef73f3f45c 100644
--- a/libclc/generic/lib/common/sign.cl
+++ b/libclc/generic/lib/common/sign.cl
@@ -1,37 +1,8 @@
 #include <clc/clc.h>
 #include <clc/clcmacro.h>
+#include <clc/common/clc_sign.h>
 
-#define SIGN(TYPE, F) \
-_CLC_DEF _CLC_OVERLOAD TYPE sign(TYPE x) { \
-  if (isnan(x)) { \
-    return 0.0F;   \
-  }               \
-  if (x > 0.0F) { \
-    return 1.0F;  \
-  }               \
-  if (x < 0.0F) { \
-    return -1.0F; \
-  }               \
-  return x; /* -0.0 or +0.0 */  \
-}
+#define FUNCTION sign
+#define __CLC_BODY <clc/common/unary_def.inc>
 
-SIGN(float, f)
-_CLC_UNARY_VECTORIZE(_CLC_OVERLOAD _CLC_DEF, float, sign, float)
-
-#ifdef cl_khr_fp64
-
-#pragma OPENCL EXTENSION cl_khr_fp64 : enable
-
-SIGN(double, )
-_CLC_UNARY_VECTORIZE(_CLC_OVERLOAD _CLC_DEF, double, sign, double)
-
-#endif
-
-#ifdef cl_khr_fp16
-
-#pragma OPENCL EXTENSION cl_khr_fp16 : enable
-
-SIGN(half,)
-_CLC_UNARY_VECTORIZE(_CLC_OVERLOAD _CLC_DEF, half, sign, half)
-
-#endif
+#include <clc/common/floatn.inc>

>From 3f5b4d23276c309a84d344c603b03b181a0403e5 Mon Sep 17 00:00:00 2001
From: Fraser Cormack <fraser at codeplay.com>
Date: Tue, 12 Nov 2024 15:27:00 +0000
Subject: [PATCH 2/2] map clc_sign to sign for clspv

---
 libclc/clc/include/clc/common/clc_sign.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/libclc/clc/include/clc/common/clc_sign.h b/libclc/clc/include/clc/common/clc_sign.h
index 1847fbf69bf60c..bda4fa65dfa890 100644
--- a/libclc/clc/include/clc/common/clc_sign.h
+++ b/libclc/clc/include/clc/common/clc_sign.h
@@ -1,10 +1,17 @@
 #ifndef __CLC_COMMON_CLC_SIGN_H__
 #define __CLC_COMMON_CLC_SIGN_H__
 
+#if defined(CLC_CLSPV)
+// clspv targets provide their own OpenCL-compatible sign
+#define __clc_sign sign
+#else
+
 #define __CLC_FUNCTION __clc_sign
 #define __CLC_BODY <clc/math/unary_decl.inc>
 #include <clc/math/gentype.inc>
 #undef __CLC_FUNCTION
 #undef __CLC_BODY
 
+#endif
+
 #endif // __CLC_COMMON_CLC_SIGN_H__



More information about the cfe-commits mailing list