Skip to content

Commit 4602c16

Browse files
authored
[libclc] Create an internal 'clc' builtins library (#15921)
Some libclc builtins currently use internal builtins prefixed with '__clc_' for various reasons, e.g., to avoid naming clashes. This commit formalizes this concept by starting to isolate the definitions of these internal clc builtins into a separate self-contained bytecode library, which is linked into each target's libclc OpenCL builtins before optimization takes place. The goal of this step is to allow additional libraries of builtins that provide entry points (or bindings) that are not written in OpenCL C but still wish to expose OpenCL-compatible builtins. By moving the implementations into a separate self-contained library, entry points can share as much code as possible without going through OpenCL C. The overall structure of the internal clc library is similar to the current OpenCL structure, with SOURCES files and targets being able to override the definitions of builtins as needed. The idea is that the OpenCL builtins will begin to need fewer target-specific overrides, as those will slowly move over to the clc builtins instead. Another advantage of having a separate bytecode library with the CLC implementations is that we can internalize the symbols when linking it (separately), whereas currently the CLC symbols make it into the final builtins library (and perhaps even the final compiled binary). This patch starts of with 'dot' as it's relatively self-contained, as opposed to most of the maths builtins which tend to pull in other builtins. We can also start to clang-format the builtins as we go, which should help to modernize the codebase. ----- This is a cherry-pick of upstream commit b2bdd8b. CC @jsji
1 parent 19608d6 commit 4602c16

File tree

25 files changed

+230
-59
lines changed

25 files changed

+230
-59
lines changed

libclc/CMakeLists.txt

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,14 @@ set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
3434
r600/lib/SOURCES;
3535
r600/libspirv/SOURCES;
3636
spirv/lib/SOURCES;
37-
spirv64/lib/SOURCES
38-
native_cpu-unknown-linux/libspirv/SOURCES
37+
spirv64/lib/SOURCES;
38+
native_cpu-unknown-linux/libspirv/SOURCES;
39+
# CLC internal libraries
40+
clc/lib/generic/SOURCES;
41+
clc/lib/clspv/SOURCES;
42+
clc/lib/clspv64/SOURCES;
43+
clc/lib/spirv/SOURCES;
44+
clc/lib/spirv64/SOURCES;
3945
)
4046

4147
set( LIBCLC_MIN_LLVM 3.9.0 )
@@ -329,6 +335,14 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
329335
" configuration, some SYCL programs may fail to build.")
330336
endif()
331337

338+
set( clc_lib_files )
339+
libclc_configure_lib_source(
340+
clc_lib_files
341+
CLC_INTERNAL
342+
LIB_ROOT_DIR clc
343+
DIRS ${dirs} ${DARCH} ${DARCH}-${OS} ${DARCH}-${VENDOR}-${OS}
344+
)
345+
332346
set( opencl_lib_files )
333347
set( opencl_gen_files )
334348

@@ -474,7 +488,8 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
474488
list( APPEND build_flags
475489
-D__CLC_INTERNAL
476490
-D${CLC_TARGET_DEFINE}
477-
-I${CMAKE_CURRENT_SOURCE_DIR}/generic/include
491+
# All libclc builtin libraries see CLC headers
492+
-I${CMAKE_CURRENT_SOURCE_DIR}/clc/include
478493
# FIXME: Fix libclc to not require disabling this noisy warning
479494
-Wno-bitwise-conditional-parentheses
480495
)
@@ -483,6 +498,20 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
483498
list( APPEND build_flags -mcpu=${cpu} )
484499
endif()
485500

501+
add_libclc_builtin_set(
502+
CLC_INTERNAL
503+
ARCH ${ARCH}
504+
ARCH_SUFFIX clc-${arch_suffix}
505+
TRIPLE ${clang_triple}
506+
COMPILE_FLAGS ${build_flags}
507+
OPT_FLAGS ${opt_flags}
508+
LIB_FILES ${clc_lib_files}
509+
)
510+
511+
list( APPEND build_flags
512+
-I${CMAKE_CURRENT_SOURCE_DIR}/generic/include
513+
)
514+
486515
add_libclc_builtin_set(
487516
ARCH ${ARCH}
488517
ARCH_SUFFIX libspirv-${arch_suffix}
@@ -493,8 +522,9 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
493522
LIB_FILES ${libspirv_lib_files}
494523
GEN_FILES ${libspirv_gen_files}
495524
ALIASES ${${d}_aliases}
496-
GENERATE_TARGET "generate_convert_spirv.cl" "generate_convert_core.cl"
497525
PARENT_TARGET libspirv-builtins
526+
# Link in the CLC builtins and internalize their symbols
527+
INTERNAL_LINK_DEPENDENCIES $<TARGET_PROPERTY:builtins.link.clc-${arch_suffix},TARGET_FILE>
498528
)
499529

500530
add_libclc_builtin_set(
@@ -506,8 +536,9 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
506536
LIB_FILES ${opencl_lib_files}
507537
GEN_FILES ${opencl_gen_files}
508538
ALIASES ${${d}_aliases}
509-
GENERATE_TARGET "generate_convert_clc.cl"
510539
PARENT_TARGET libopencl-builtins
540+
# Link in the CLC builtins and internalize their symbols
541+
INTERNAL_LINK_DEPENDENCIES $<TARGET_PROPERTY:builtins.link.clc-${arch_suffix},TARGET_FILE>
511542
)
512543
endforeach( d )
513544
endforeach( t )
Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
#ifndef CLC_FUNC
2-
#define CLC_FUNC
1+
#ifndef __CLC_CLCFUNC_H_
2+
#define __CLC_CLCFUNC_H_
33

44
#define _CLC_OVERLOAD __attribute__((overloadable))
55
#define _CLC_DECL
6+
#define _CLC_INLINE __attribute__((always_inline)) inline
7+
#define _CLC_CONVERGENT __attribute__((convergent))
8+
#define _CLC_PURE __attribute__((pure))
9+
#define _CLC_CONSTFN __attribute__((const))
10+
611
// avoid inlines for SPIR-V related targets since we'll optimise later in the
712
// chain
813
#if defined(CLC_SPIRV) || defined(CLC_SPIRV64)
@@ -12,9 +17,5 @@
1217
#else
1318
#define _CLC_DEF __attribute__((always_inline))
1419
#endif
15-
#define _CLC_INLINE __attribute__((always_inline)) inline
16-
#define _CLC_CONVERGENT __attribute__((convergent))
17-
#define _CLC_PURE __attribute__((pure))
18-
#define _CLC_CONSTFN __attribute__((const))
1920

20-
#endif // CLC_FUNC
21+
#endif // __CLC_CLCFUNC_H_

libclc/generic/include/types.h renamed to libclc/clc/include/clc/clctypes.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#ifndef CLC_TYPES
2-
#define CLC_TYPES
1+
#ifndef __CLC_CLCTYPES_H_
2+
#define __CLC_CLCTYPES_H_
33

44
/* 6.1.1 Built-in Scalar Data Types */
55

@@ -12,12 +12,12 @@ typedef unsigned long ulong;
1212
typedef __SIZE_TYPE__ size_t;
1313
typedef __PTRDIFF_TYPE__ ptrdiff_t;
1414

15-
#define __stdint_join3(a,b,c) a ## b ## c
15+
#define __stdint_join3(a, b, c) a##b##c
1616

17-
#define __intn_t(n) __stdint_join3(__INT, n, _TYPE__)
17+
#define __intn_t(n) __stdint_join3(__INT, n, _TYPE__)
1818
#define __uintn_t(n) __stdint_join3(unsigned __INT, n, _TYPE__)
1919

20-
typedef __intn_t(__INTPTR_WIDTH__) intptr_t;
20+
typedef __intn_t(__INTPTR_WIDTH__) intptr_t;
2121
typedef __uintn_t(__INTPTR_WIDTH__) uintptr_t;
2222

2323
#undef __uintn_t
@@ -104,4 +104,4 @@ typedef __attribute__((ext_vector_type(8))) half half8;
104104
typedef __attribute__((ext_vector_type(16))) half half16;
105105
#endif
106106

107-
#endif // CLC_TYPES
107+
#endif // __CLC_CLCTYPES_H_
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#define __CLC_BODY <clc/geometric/clc_dot.inc>
2+
#include <clc/geometric/floatn.inc>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
_CLC_OVERLOAD _CLC_DECL __CLC_FLOAT __clc_dot(__CLC_FLOATN p0, __CLC_FLOATN p1);

libclc/clc/include/clc/internal/clc.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#ifndef __CLC_INTERNAL_CLC_H_
2+
#define __CLC_INTERNAL_CLC_H_
3+
4+
#ifndef cl_clang_storage_class_specifiers
5+
#error Implementation requires cl_clang_storage_class_specifiers extension!
6+
#endif
7+
8+
#pragma OPENCL EXTENSION cl_clang_storage_class_specifiers : enable
9+
10+
#ifdef cl_khr_fp64
11+
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
12+
#endif
13+
14+
#ifdef cl_khr_fp16
15+
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
16+
#endif
17+
18+
/* Function Attributes */
19+
#include <clc/clcfunc.h>
20+
21+
/* 6.1 Supported Data Types */
22+
#include <clc/clctypes.h>
23+
24+
#pragma OPENCL EXTENSION all : disable
25+
26+
#endif // __CLC_INTERNAL_CLC_H_

libclc/clc/lib/clspv/SOURCES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dummy.cl

libclc/clc/lib/clspv/dummy.cl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// Empty file

libclc/clc/lib/clspv64

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
clspv

libclc/clc/lib/generic/SOURCES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
geometric/clc_dot.cl
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#include <clc/internal/clc.h>
2+
3+
_CLC_OVERLOAD _CLC_DEF float __clc_dot(float p0, float p1) { return p0 * p1; }
4+
5+
_CLC_OVERLOAD _CLC_DEF float __clc_dot(float2 p0, float2 p1) {
6+
return p0.x * p1.x + p0.y * p1.y;
7+
}
8+
9+
_CLC_OVERLOAD _CLC_DEF float __clc_dot(float3 p0, float3 p1) {
10+
return p0.x * p1.x + p0.y * p1.y + p0.z * p1.z;
11+
}
12+
13+
_CLC_OVERLOAD _CLC_DEF float __clc_dot(float4 p0, float4 p1) {
14+
return p0.x * p1.x + p0.y * p1.y + p0.z * p1.z + p0.w * p1.w;
15+
}
16+
17+
#ifdef cl_khr_fp64
18+
19+
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
20+
21+
_CLC_OVERLOAD _CLC_DEF double __clc_dot(double p0, double p1) {
22+
return p0 * p1;
23+
}
24+
25+
_CLC_OVERLOAD _CLC_DEF double __clc_dot(double2 p0, double2 p1) {
26+
return p0.x * p1.x + p0.y * p1.y;
27+
}
28+
29+
_CLC_OVERLOAD _CLC_DEF double __clc_dot(double3 p0, double3 p1) {
30+
return p0.x * p1.x + p0.y * p1.y + p0.z * p1.z;
31+
}
32+
33+
_CLC_OVERLOAD _CLC_DEF double __clc_dot(double4 p0, double4 p1) {
34+
return p0.x * p1.x + p0.y * p1.y + p0.z * p1.z + p0.w * p1.w;
35+
}
36+
37+
#endif
38+
39+
#ifdef cl_khr_fp16
40+
41+
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
42+
43+
_CLC_OVERLOAD _CLC_DEF half __clc_dot(half p0, half p1) { return p0 * p1; }
44+
45+
_CLC_OVERLOAD _CLC_DEF half __clc_dot(half2 p0, half2 p1) {
46+
return p0.x * p1.x + p0.y * p1.y;
47+
}
48+
49+
_CLC_OVERLOAD _CLC_DEF half __clc_dot(half3 p0, half3 p1) {
50+
return p0.x * p1.x + p0.y * p1.y + p0.z * p1.z;
51+
}
52+
53+
_CLC_OVERLOAD _CLC_DEF half __clc_dot(half4 p0, half4 p1) {
54+
return p0.x * p1.x + p0.y * p1.y + p0.z * p1.z + p0.w * p1.w;
55+
}
56+
57+
#endif

libclc/clc/lib/spirv/SOURCES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
../generic/geometric/clc_dot.cl
2+

libclc/clc/lib/spirv64/SOURCES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../generic/geometric/clc_dot.cl

libclc/cmake/modules/AddLibclc.cmake

Lines changed: 60 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ endfunction()
8282
# Links together one or more bytecode files
8383
#
8484
# Arguments:
85+
# * INTERNALIZE
86+
# Set if -internalize flag should be passed when linking
8587
# * TARGET <string>
8688
# Custom target to create
8789
# * INPUT <string> ...
@@ -93,7 +95,7 @@ endfunction()
9395
# List of extra dependencies to inject
9496
function(link_bc)
9597
cmake_parse_arguments(ARG
96-
""
98+
"INTERNALIZE"
9799
"TARGET;RSP_DIR"
98100
"INPUTS;DEPENDENCIES"
99101
${ARGN}
@@ -106,7 +108,7 @@ function(link_bc)
106108
file( TO_CMAKE_PATH ${ARG_RSP_DIR}/${ARG_TARGET}.rsp RSP_FILE )
107109
# Turn it into a space-separate list of input files
108110
list( JOIN ARG_INPUTS " " RSP_INPUT )
109-
file( WRITE ${RSP_FILE} ${RSP_INPUT} )
111+
file( GENERATE OUTPUT ${RSP_FILE} CONTENT ${RSP_INPUT} )
110112
# Ensure that if this file is removed, we re-run CMake
111113
set_property( DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
112114
${RSP_FILE}
@@ -116,7 +118,7 @@ function(link_bc)
116118

117119
add_custom_command(
118120
OUTPUT ${ARG_TARGET}.bc
119-
COMMAND ${llvm-link_exe} -o ${ARG_TARGET}.bc ${LINK_INPUT_ARG}
121+
COMMAND ${llvm-link_exe} $<$<BOOL:${ARG_INTERNALIZE}>:--internalize> -o ${ARG_TARGET}.bc ${LINK_INPUT_ARG}
120122
DEPENDS ${llvm-link_target} ${ARG_DEPENDENCIES} ${ARG_INPUTS} ${RSP_FILE}
121123
)
122124

@@ -282,6 +284,9 @@ endfunction()
282284
# Triple used to compile
283285
#
284286
# Optional Arguments:
287+
# * CLC_INTERNAL
288+
# Pass if compiling the internal CLC builtin libraries, which are not
289+
# optimized and do not have aliases created.
285290
# * LIB_FILES <string> ...
286291
# List of files that should be built for this library
287292
# * GEN_FILES <string> ...
@@ -294,11 +299,14 @@ endfunction()
294299
# Prefix to give the final builtin library aliases
295300
# * ALIASES <string> ...
296301
# List of aliases
302+
# * INTERNAL_LINK_DEPENDENCIES <string> ...
303+
# A list of extra bytecode files to link into the builtin library. Symbols
304+
# from these link dependencies will be internalized during linking.
297305
function(add_libclc_builtin_set)
298306
cmake_parse_arguments(ARG
299-
""
307+
"CLC_INTERNAL"
300308
"ARCH;TRIPLE;ARCH_SUFFIX;TARGET_ENV;PARENT_TARGET"
301-
"LIB_FILES;GEN_FILES;COMPILE_FLAGS;OPT_FLAGS;ALIASES"
309+
"LIB_FILES;GEN_FILES;COMPILE_FLAGS;OPT_FLAGS;ALIASES;INTERNAL_LINK_DEPENDENCIES"
302310
${ARGN}
303311
)
304312

@@ -347,13 +355,45 @@ function(add_libclc_builtin_set)
347355
)
348356
set_target_properties( ${builtins_comp_lib_tgt} PROPERTIES FOLDER "libclc/Device IR/Comp" )
349357

358+
if( NOT bytecode_files )
359+
message(FATAL_ERROR "Cannot create an empty builtins library")
360+
endif()
361+
350362
set( builtins_link_lib_tgt builtins.link.${ARG_ARCH_SUFFIX} )
351-
link_bc(
352-
TARGET ${builtins_link_lib_tgt}
353-
INPUTS ${bytecode_files}
354-
RSP_DIR ${LIBCLC_ARCH_OBJFILE_DIR}
355-
DEPENDENCIES ${builtins_comp_lib_tgt}
356-
)
363+
364+
if( NOT ARG_INTERNAL_LINK_DEPENDENCIES )
365+
link_bc(
366+
TARGET ${builtins_link_lib_tgt}
367+
INPUTS ${bytecode_files}
368+
RSP_DIR ${LIBCLC_ARCH_OBJFILE_DIR}
369+
DEPENDENCIES ${builtins_comp_lib_tgt}
370+
)
371+
else()
372+
# If we have libraries to link while internalizing their symbols, we need
373+
# two separate link steps; the --internalize flag applies to all link
374+
# inputs but the first.
375+
set( builtins_link_lib_tmp_tgt builtins.link.pre-deps.${ARG_ARCH_SUFFIX} )
376+
link_bc(
377+
TARGET ${builtins_link_lib_tmp_tgt}
378+
INPUTS ${bytecode_files}
379+
RSP_DIR ${LIBCLC_ARCH_OBJFILE_DIR}
380+
DEPENDENCIES ${builtins_comp_lib_tgt}
381+
)
382+
link_bc(
383+
INTERNALIZE
384+
TARGET ${builtins_link_lib_tgt}
385+
INPUTS $<TARGET_PROPERTY:${builtins_link_lib_tmp_tgt},TARGET_FILE>
386+
${ARG_INTERNAL_LINK_DEPENDENCIES}
387+
RSP_DIR ${LIBCLC_ARCH_OBJFILE_DIR}
388+
DEPENDENCIES ${builtins_link_lib_tmp_tgt}
389+
)
390+
endif()
391+
392+
# For the CLC internal builtins, exit here - we only optimize the targets'
393+
# entry points once we've linked the CLC buitins into them
394+
if( ARG_CLC_INTERNAL )
395+
return()
396+
endif()
357397

358398
set( builtins_link_lib $<TARGET_PROPERTY:${builtins_link_lib_tgt},TARGET_FILE> )
359399

@@ -483,6 +523,9 @@ endfunction(add_libclc_builtin_set)
483523
# LIB_FILE_LIST may be pre-populated and is appended to.
484524
#
485525
# Arguments:
526+
# * CLC_INTERNAL
527+
# Pass if compiling the internal CLC builtin libraries, which have a
528+
# different directory structure.
486529
# * LIB_ROOT_DIR <string>
487530
# Root directory containing target's lib files, relative to libclc root
488531
# directory. If not provided, is set to '.'.
@@ -494,7 +537,7 @@ endfunction(add_libclc_builtin_set)
494537
# files
495538
function(libclc_configure_lib_source LIB_FILE_LIST)
496539
cmake_parse_arguments(ARG
497-
""
540+
"CLC_INTERNAL"
498541
"LIB_DIR;LIB_ROOT_DIR"
499542
"DIRS"
500543
${ARGN}
@@ -512,7 +555,11 @@ function(libclc_configure_lib_source LIB_FILE_LIST)
512555
set( source_list )
513556
foreach( l ${ARG_DIRS} )
514557
foreach( s "SOURCES" "SOURCES_${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}" )
515-
file( TO_CMAKE_PATH ${ARG_LIB_ROOT_DIR}/${l}/${ARG_LIB_DIR}/${s} file_loc )
558+
if( ARG_CLC_INTERNAL )
559+
file( TO_CMAKE_PATH ${ARG_LIB_ROOT_DIR}/${ARG_LIB_DIR}/${l}/${s} file_loc )
560+
else()
561+
file( TO_CMAKE_PATH ${ARG_LIB_ROOT_DIR}/${l}/${ARG_LIB_DIR}/${s} file_loc )
562+
endif()
516563
file( TO_CMAKE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${file_loc} loc )
517564
# Prepend the location to give higher priority to
518565
# specialized implementation

0 commit comments

Comments
 (0)