[libclc] [libclc] Create an internal 'clc' builtins library (PR #109985)
Fraser Cormack via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 25 06:59:12 PDT 2024
https://github.com/frasercrmck created https://github.com/llvm/llvm-project/pull/109985
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.
>From b01eadcda29e2df283c978901ea9616ebebd44aa Mon Sep 17 00:00:00 2001
From: Fraser Cormack <fraser at codeplay.com>
Date: Mon, 23 Sep 2024 12:54:02 +0100
Subject: [PATCH 1/2] [libclc] Split off library build system into helpers
This splits off several key parts of the build system into utility
methods. This will be used in upcoming patches to help provide
additional sets of target-specific builtin libraries.
Running llvm-diff on the resulting LLVM bytecode binaries, and regular
diff on SPIR-V binaries, shows no differences before and after this
patch.
---
libclc/CMakeLists.txt | 172 ++++------------------
libclc/cmake/modules/AddLibclc.cmake | 205 +++++++++++++++++++++++++++
2 files changed, 230 insertions(+), 147 deletions(-)
diff --git a/libclc/CMakeLists.txt b/libclc/CMakeLists.txt
index 1bf7eb2ca7ed7e..5344b8d0282c54 100644
--- a/libclc/CMakeLists.txt
+++ b/libclc/CMakeLists.txt
@@ -269,49 +269,22 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
set( DARCH ${ARCH} )
endif()
- # Enumerate SOURCES* files
- set( source_list )
- foreach( l ${dirs} ${DARCH} ${DARCH}-${OS} ${DARCH}-${VENDOR}-${OS} )
- foreach( s "SOURCES" "SOURCES_${LLVM_MAJOR}.${LLVM_MINOR}" )
- file( TO_CMAKE_PATH ${l}/lib/${s} file_loc )
- file( TO_CMAKE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${file_loc} loc )
- # Prepend the location to give higher priority to
- # specialized implementation
- if( EXISTS ${loc} )
- set( source_list ${file_loc} ${source_list} )
- endif()
- endforeach()
- endforeach()
-
- # Add the generated convert.cl here to prevent adding the one listed in
- # SOURCES
- set( objects ) # A "set" of already-added input files
- set( rel_files ) # Source directory input files, relative to the root dir
- set( gen_files ) # Generated binary input files, relative to the binary dir
- if( NOT ${ARCH} STREQUAL "spirv" AND NOT ${ARCH} STREQUAL "spirv64" )
- if( NOT ENABLE_RUNTIME_SUBNORMAL AND NOT ${ARCH} STREQUAL "clspv" AND
- NOT ${ARCH} STREQUAL "clspv64" )
- list( APPEND gen_files convert.cl )
- list( APPEND objects convert.cl )
- list( APPEND rel_files generic/lib/subnormal_use_default.ll )
- elseif(${ARCH} STREQUAL "clspv" OR ${ARCH} STREQUAL "clspv64")
- list( APPEND gen_files clspv-convert.cl )
- list( APPEND objects clspv-convert.cl )
+ set( opencl_lib_files )
+ set( opencl_gen_files )
+
+ if( NOT ARCH STREQUAL spirv AND NOT ARCH STREQUAL spirv64 )
+ if( ARCH STREQUAL clspv OR ARCH STREQUAL clspv64 )
+ list( APPEND opencl_gen_files clspv-convert.cl )
+ elseif ( NOT ENABLE_RUNTIME_SUBNORMAL )
+ list( APPEND opencl_gen_files convert.cl )
+ list( APPEND opencl_lib_files generic/lib/subnormal_use_default.ll )
endif()
endif()
- foreach( l ${source_list} )
- file( READ ${l} file_list )
- string( REPLACE "\n" ";" file_list ${file_list} )
- get_filename_component( dir ${l} DIRECTORY )
- foreach( f ${file_list} )
- # Only add each file once, so that targets can 'specialize' builtins
- if( NOT ${f} IN_LIST objects )
- list( APPEND objects ${f} )
- list( APPEND rel_files ${dir}/${f} )
- endif()
- endforeach()
- endforeach()
+ libclc_configure_lib_source(
+ opencl_lib_files
+ DIRS ${dirs} ${DARCH} ${DARCH}-${OS} ${DARCH}-${VENDOR}-${OS}
+ )
foreach( d ${${t}_devices} )
get_libclc_device_info(
@@ -322,11 +295,6 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
CLANG_TRIPLE clang_triple
)
- set( mcpu )
- if( NOT "${cpu}" STREQUAL "" )
- set( mcpu "-mcpu=${cpu}" )
- endif()
-
message( STATUS " device: ${d} ( ${${d}_aliases} )" )
if ( ARCH STREQUAL spirv OR ARCH STREQUAL spirv64 )
@@ -354,109 +322,19 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
-Wno-bitwise-conditional-parentheses
)
- set( bytecode_files "" )
- foreach( file IN LISTS gen_files rel_files )
- # We need to take each file and produce an absolute input file, as well
- # as a unique architecture-specific output file. We deal with a mix of
- # different input files, which makes this trickier.
- if( ${file} IN_LIST gen_files )
- # Generated files are given just as file names, which we must make
- # absolute to the binary directory.
- set( input_file ${CMAKE_CURRENT_BINARY_DIR}/${file} )
- set( output_file "${LIBCLC_ARCH_OBJFILE_DIR}/${file}.bc" )
- else()
- # Other files are originally relative to each SOURCE file, which are
- # then make relative to the libclc root directory. We must normalize
- # the path (e.g., ironing out any ".."), then make it relative to the
- # root directory again, and use that relative path component for the
- # binary path.
- get_filename_component( abs_path ${file} ABSOLUTE BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR} )
- file( RELATIVE_PATH root_rel_path ${CMAKE_CURRENT_SOURCE_DIR} ${abs_path} )
- set( input_file ${CMAKE_CURRENT_SOURCE_DIR}/${file} )
- set( output_file "${LIBCLC_ARCH_OBJFILE_DIR}/${root_rel_path}.bc" )
- endif()
-
- get_filename_component( file_dir ${file} DIRECTORY )
-
- compile_to_bc(
- TRIPLE ${clang_triple}
- INPUT ${input_file}
- OUTPUT ${output_file}
- EXTRA_OPTS "${mcpu}" -fno-builtin -nostdlib
- "${build_flags}" -I${CMAKE_CURRENT_SOURCE_DIR}/${file_dir}
- DEPENDENCIES generate_convert.cl clspv-generate_convert.cl
- )
- list( APPEND bytecode_files ${output_file} )
- endforeach()
-
- set( builtins_comp_lib_tgt builtins.comp.${arch_suffix} )
- add_custom_target( ${builtins_comp_lib_tgt}
- DEPENDS ${bytecode_files}
- )
- set_target_properties( ${builtins_comp_lib_tgt} PROPERTIES FOLDER "libclc/Device IR/Comp" )
+ if( NOT "${cpu}" STREQUAL "" )
+ list( APPEND build_flags -mcpu=${cpu} )
+ endif()
- set( builtins_link_lib_tgt builtins.link.${arch_suffix} )
- link_bc(
- TARGET ${builtins_link_lib_tgt}
- INPUTS ${bytecode_files}
- DEPENDENCIES ${builtins_comp_lib_tgt}
+ add_libclc_builtin_set(
+ ARCH ${ARCH}
+ ARCH_SUFFIX ${arch_suffix}
+ TRIPLE ${clang_triple}
+ COMPILE_FLAGS ${build_flags}
+ OPT_FLAGS ${opt_flags}
+ LIB_FILES ${opencl_lib_files}
+ GEN_FILES ${opencl_gen_files}
+ ALIASES ${${d}_aliases}
)
-
- set( builtins_link_lib $<TARGET_PROPERTY:${builtins_link_lib_tgt},TARGET_FILE> )
-
- if( ARCH STREQUAL spirv OR ARCH STREQUAL spirv64 )
- set( spv_suffix ${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" )
- else()
- set( builtins_opt_lib_tgt builtins.opt.${arch_suffix} )
-
- # Add opt target
- add_custom_command( OUTPUT ${builtins_opt_lib_tgt}.bc
- COMMAND ${opt_exe} ${opt_flags} -o ${builtins_opt_lib_tgt}.bc
- ${builtins_link_lib}
- DEPENDS ${opt_target} ${builtins_link_lib} ${builtins_link_lib_tgt}
- )
- add_custom_target( ${builtins_opt_lib_tgt}
- ALL DEPENDS ${builtins_opt_lib_tgt}.bc
- )
- set_target_properties( ${builtins_opt_lib_tgt}
- PROPERTIES TARGET_FILE ${builtins_opt_lib_tgt}.bc
- FOLDER "libclc/Device IR/Opt"
- )
-
- set( builtins_opt_lib $<TARGET_PROPERTY:${builtins_opt_lib_tgt},TARGET_FILE> )
-
- # Add prepare target
- set( obj_suffix ${arch_suffix}.bc )
- add_custom_command( OUTPUT ${obj_suffix}
- COMMAND ${prepare_builtins_exe} -o ${obj_suffix} ${builtins_opt_lib}
- DEPENDS ${builtins_opt_lib} ${builtins_opt_lib_tgt} ${prepare_builtins_target} )
- add_custom_target( prepare-${obj_suffix} ALL DEPENDS ${obj_suffix} )
- set_target_properties( "prepare-${obj_suffix}" PROPERTIES FOLDER "libclc/Device IR/Prepare" )
-
- # nvptx-- targets don't include workitem builtins
- if( NOT clang_triple MATCHES ".*ptx.*--$" )
- add_test( NAME external-calls-${obj_suffix}
- COMMAND ./check_external_calls.sh ${CMAKE_CURRENT_BINARY_DIR}/${obj_suffix} ${LLVM_TOOLS_BINARY_DIR}
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
- endif()
-
- install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${obj_suffix} DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" )
- foreach( a ${${d}_aliases} )
- set( alias_suffix "${a}-${clang_triple}.bc" )
- add_custom_target( ${alias_suffix} ALL
- COMMAND ${CMAKE_COMMAND} -E create_symlink ${obj_suffix} ${alias_suffix}
- DEPENDS prepare-${obj_suffix} )
- set_target_properties( "${alias_suffix}" PROPERTIES FOLDER "libclc/Device IR/Aliases" )
- install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${alias_suffix} DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" )
- endforeach( a )
- endif()
endforeach( d )
endforeach( t )
diff --git a/libclc/cmake/modules/AddLibclc.cmake b/libclc/cmake/modules/AddLibclc.cmake
index 839815d8cc6fff..dcd9a87dbe1108 100644
--- a/libclc/cmake/modules/AddLibclc.cmake
+++ b/libclc/cmake/modules/AddLibclc.cmake
@@ -178,3 +178,208 @@ function(get_libclc_device_info)
set( ${ARG_CLANG_TRIPLE} ${ARG_TRIPLE} PARENT_SCOPE )
endif()
endfunction()
+
+# Compiles a list of library source files (provided by LIB_FILES/GEN_FILES) and
+# compiles them to LLVM bytecode (or SPIR-V), links them together and optimizes
+# them.
+#
+# For bytecode libraries, a list of ALIASES may optionally be provided to
+# produce additional symlinks.
+#
+# Arguments:
+# * ARCH <string>
+# libclc architecture being built
+# * ARCH_SUFFIX <string>
+# libclc architecture/triple suffix
+# * TRIPLE <string>
+# Triple used to compile
+#
+# Optional Arguments:
+# * LIB_FILES <string> ...
+# List of files that should be built for this library
+# * GEN_FILES <string> ...
+# List of generated files (in build dir) that should be built for this library
+# * COMPILE_FLAGS <string> ...
+# Compilation options (for clang)
+# * OPT_FLAGS <string> ...
+# Optimization options (for opt)
+# * ALIASES <string> ...
+# List of aliases
+function(add_libclc_builtin_set)
+ cmake_parse_arguments(ARG
+ ""
+ "ARCH;TRIPLE;ARCH_SUFFIX"
+ "LIB_FILES;GEN_FILES;COMPILE_FLAGS;OPT_FLAGS;ALIASES"
+ ${ARGN}
+ )
+
+ if( NOT ARG_ARCH OR NOT ARG_ARCH_SUFFIX OR NOT ARG_TRIPLE )
+ message( FATAL_ERROR "Must provide ARCH, ARCH_SUFFIX, and TRIPLE" )
+ endif()
+
+ set( bytecode_files "" )
+ foreach( file IN LISTS ARG_GEN_FILES ARG_LIB_FILES )
+ # We need to take each file and produce an absolute input file, as well
+ # as a unique architecture-specific output file. We deal with a mix of
+ # different input files, which makes this trickier.
+ if( ${file} IN_LIST ARG_GEN_FILES )
+ # Generated files are given just as file names, which we must make
+ # absolute to the binary directory.
+ set( input_file ${CMAKE_CURRENT_BINARY_DIR}/${file} )
+ set( output_file "${LIBCLC_ARCH_OBJFILE_DIR}/${file}.bc" )
+ else()
+ # Other files are originally relative to each SOURCE file, which are
+ # then make relative to the libclc root directory. We must normalize
+ # the path (e.g., ironing out any ".."), then make it relative to the
+ # root directory again, and use that relative path component for the
+ # binary path.
+ get_filename_component( abs_path ${file} ABSOLUTE BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR} )
+ file( RELATIVE_PATH root_rel_path ${CMAKE_CURRENT_SOURCE_DIR} ${abs_path} )
+ set( input_file ${CMAKE_CURRENT_SOURCE_DIR}/${file} )
+ set( output_file "${LIBCLC_ARCH_OBJFILE_DIR}/${root_rel_path}.bc" )
+ endif()
+
+ get_filename_component( file_dir ${file} DIRECTORY )
+
+ compile_to_bc(
+ TRIPLE ${ARG_TRIPLE}
+ INPUT ${input_file}
+ OUTPUT ${output_file}
+ EXTRA_OPTS -fno-builtin -nostdlib
+ "${ARG_COMPILE_FLAGS}" -I${CMAKE_CURRENT_SOURCE_DIR}/${file_dir}
+ DEPENDENCIES generate_convert.cl clspv-generate_convert.cl
+ )
+ list( APPEND bytecode_files ${output_file} )
+ endforeach()
+
+ set( builtins_comp_lib_tgt builtins.comp.${ARG_ARCH_SUFFIX} )
+ add_custom_target( ${builtins_comp_lib_tgt}
+ DEPENDS ${bytecode_files}
+ )
+ set_target_properties( ${builtins_comp_lib_tgt} PROPERTIES FOLDER "libclc/Device IR/Comp" )
+
+ set( builtins_link_lib_tgt builtins.link.${ARG_ARCH_SUFFIX} )
+ link_bc(
+ TARGET ${builtins_link_lib_tgt}
+ INPUTS ${bytecode_files}
+ DEPENDENCIES ${builtins_comp_lib_tgt}
+ )
+
+ 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
+ add_custom_command( OUTPUT ${builtins_opt_lib_tgt}.bc
+ COMMAND ${opt_exe} ${ARG_OPT_FLAGS} -o ${builtins_opt_lib_tgt}.bc
+ ${builtins_link_lib}
+ DEPENDS ${opt_target} ${builtins_link_lib} ${builtins_link_lib_tgt}
+ )
+ add_custom_target( ${builtins_opt_lib_tgt}
+ ALL DEPENDS ${builtins_opt_lib_tgt}.bc
+ )
+ set_target_properties( ${builtins_opt_lib_tgt}
+ PROPERTIES TARGET_FILE ${builtins_opt_lib_tgt}.bc
+ FOLDER "libclc/Device IR/Opt"
+ )
+
+ set( builtins_opt_lib $<TARGET_PROPERTY:${builtins_opt_lib_tgt},TARGET_FILE> )
+
+ # Add prepare target
+ set( obj_suffix ${ARG_ARCH_SUFFIX}.bc )
+ add_custom_command( OUTPUT ${obj_suffix}
+ COMMAND ${prepare_builtins_exe} -o ${obj_suffix} ${builtins_opt_lib}
+ DEPENDS ${builtins_opt_lib} ${builtins_opt_lib_tgt} ${prepare_builtins_target} )
+ add_custom_target( prepare-${obj_suffix} ALL DEPENDS ${obj_suffix} )
+ set_target_properties( "prepare-${obj_suffix}" PROPERTIES FOLDER "libclc/Device IR/Prepare" )
+
+ # nvptx-- targets don't include workitem builtins
+ if( NOT ARG_TRIPLE MATCHES ".*ptx.*--$" )
+ add_test( NAME external-calls-${obj_suffix}
+ COMMAND ./check_external_calls.sh ${CMAKE_CURRENT_BINARY_DIR}/${obj_suffix} ${LLVM_TOOLS_BINARY_DIR}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
+ endif()
+
+ install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${obj_suffix} DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" )
+ foreach( a ${ARG_ALIASES} )
+ set( alias_suffix "${a}-${ARG_TRIPLE}.bc" )
+ add_custom_target( ${alias_suffix} ALL
+ COMMAND ${CMAKE_COMMAND} -E create_symlink ${obj_suffix} ${alias_suffix}
+ DEPENDS prepare-${obj_suffix} )
+ set_target_properties( "${alias_suffix}" PROPERTIES FOLDER "libclc/Device IR/Aliases" )
+ install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${alias_suffix} DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" )
+ endforeach( a )
+endfunction(add_libclc_builtin_set)
+
+# Produces a list of libclc source files by walking over SOURCES files in a
+# given directory. Outputs the list of files in LIB_FILE_LIST.
+#
+# LIB_FILE_LIST may be pre-populated and is appended to.
+#
+# Arguments:
+# * LIB_ROOT_DIR <string>
+# Root directory containing target's lib files, relative to libclc root
+# directory. If not provided, is set to '.'.
+# * DIRS <string> ...
+# List of directories under LIB_ROOT_DIR to walk over searching for SOURCES
+# files
+function(libclc_configure_lib_source LIB_FILE_LIST)
+ cmake_parse_arguments(ARG
+ ""
+ "LIB_ROOT_DIR"
+ "DIRS"
+ ${ARGN}
+ )
+
+ if( NOT ARG_LIB_ROOT_DIR )
+ set(ARG_LIB_ROOT_DIR ".")
+ endif()
+
+ # Enumerate SOURCES* files
+ set( source_list )
+ foreach( l ${ARG_DIRS} )
+ foreach( s "SOURCES" "SOURCES_${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}" )
+ file( TO_CMAKE_PATH ${ARG_LIB_ROOT_DIR}/${l}/lib/${s} file_loc )
+ file( TO_CMAKE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${file_loc} loc )
+ # Prepend the location to give higher priority to
+ # specialized implementation
+ if( EXISTS ${loc} )
+ set( source_list ${file_loc} ${source_list} )
+ endif()
+ endforeach()
+ endforeach()
+
+ ## Add the generated convert files here to prevent adding the ones listed in
+ ## SOURCES
+ set( rel_files ${${LIB_FILE_LIST}} ) # Source directory input files, relative to the root dir
+ set( objects ${${LIB_FILE_LIST}} ) # A "set" of already-added input files
+
+ foreach( l ${source_list} )
+ file( READ ${l} file_list )
+ string( REPLACE "\n" ";" file_list ${file_list} )
+ get_filename_component( dir ${l} DIRECTORY )
+ foreach( f ${file_list} )
+ # Only add each file once, so that targets can 'specialize' builtins
+ if( NOT ${f} IN_LIST objects )
+ list( APPEND objects ${f} )
+ list( APPEND rel_files ${dir}/${f} )
+ endif()
+ endforeach()
+ endforeach()
+
+ set( ${LIB_FILE_LIST} ${rel_files} PARENT_SCOPE )
+endfunction(libclc_configure_lib_source LIB_FILE_LIST)
>From e7a70c3ad35da7a36a68e7351a8424a21ce7b1ed Mon Sep 17 00:00:00 2001
From: Fraser Cormack <fraser at codeplay.com>
Date: Tue, 24 Sep 2024 17:34:50 +0100
Subject: [PATCH 2/2] [libclc] Create an internal 'clc' builtins library
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.
---
libclc/CMakeLists.txt | 35 +++++++++-
libclc/{generic => clc}/include/clc/clcfunc.h | 5 ++
.../{generic => clc}/include/clc/clctypes.h | 5 ++
libclc/clc/include/clc/geometric/clc_dot.h | 2 +
libclc/clc/include/clc/geometric/clc_dot.inc | 1 +
libclc/clc/include/clc/internal/clc.h | 26 +++++++
libclc/clc/lib/clspv/SOURCES | 1 +
libclc/clc/lib/clspv/dummy.cl | 1 +
libclc/clc/lib/clspv64 | 1 +
libclc/clc/lib/generic/SOURCES | 1 +
libclc/clc/lib/generic/geometric/clc_dot.cl | 57 ++++++++++++++++
libclc/clc/lib/spirv/SOURCES | 2 +
libclc/clc/lib/spirv64/SOURCES | 1 +
libclc/cmake/modules/AddLibclc.cmake | 67 ++++++++++++++++---
libclc/generic/lib/geometric/dot.cl | 27 ++++----
15 files changed, 205 insertions(+), 27 deletions(-)
rename libclc/{generic => clc}/include/clc/clcfunc.h (85%)
rename libclc/{generic => clc}/include/clc/clctypes.h (97%)
create mode 100644 libclc/clc/include/clc/geometric/clc_dot.h
create mode 100644 libclc/clc/include/clc/geometric/clc_dot.inc
create mode 100644 libclc/clc/include/clc/internal/clc.h
create mode 100644 libclc/clc/lib/clspv/SOURCES
create mode 100644 libclc/clc/lib/clspv/dummy.cl
create mode 120000 libclc/clc/lib/clspv64
create mode 100644 libclc/clc/lib/generic/SOURCES
create mode 100644 libclc/clc/lib/generic/geometric/clc_dot.cl
create mode 100644 libclc/clc/lib/spirv/SOURCES
create mode 100644 libclc/clc/lib/spirv64/SOURCES
diff --git a/libclc/CMakeLists.txt b/libclc/CMakeLists.txt
index 5344b8d0282c54..2d5f3f4d321115 100644
--- a/libclc/CMakeLists.txt
+++ b/libclc/CMakeLists.txt
@@ -29,7 +29,13 @@ set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
ptx-nvidiacl/lib/SOURCES;
r600/lib/SOURCES;
spirv/lib/SOURCES;
- spirv64/lib/SOURCES
+ spirv64/lib/SOURCES;
+ # CLC internal libraries
+ clc/lib/generic/SOURCES;
+ clc/lib/clspv/SOURCES;
+ clc/lib/clspv64/SOURCES;
+ clc/lib/spirv/SOURCES;
+ clc/lib/spirv64/SOURCES;
)
set( LIBCLC_MIN_LLVM 3.9.0 )
@@ -269,6 +275,14 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
set( DARCH ${ARCH} )
endif()
+ set( clc_lib_files )
+ libclc_configure_lib_source(
+ clc_lib_files
+ CLC_INTERNAL
+ LIB_ROOT_DIR clc
+ DIRS ${dirs} ${DARCH} ${DARCH}-${OS} ${DARCH}-${VENDOR}-${OS}
+ )
+
set( opencl_lib_files )
set( opencl_gen_files )
@@ -317,7 +331,8 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
list( APPEND build_flags
-D__CLC_INTERNAL
-D${CLC_TARGET_DEFINE}
- -I${CMAKE_CURRENT_SOURCE_DIR}/generic/include
+ # All libclc builtin libraries see CLC headers
+ -I${CMAKE_CURRENT_SOURCE_DIR}/clc/include
# FIXME: Fix libclc to not require disabling this noisy warning
-Wno-bitwise-conditional-parentheses
)
@@ -326,6 +341,20 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
list( APPEND build_flags -mcpu=${cpu} )
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}
+ LIB_FILES ${clc_lib_files}
+ )
+
+ list( APPEND build_flags
+ -I${CMAKE_CURRENT_SOURCE_DIR}/generic/include
+ )
+
add_libclc_builtin_set(
ARCH ${ARCH}
ARCH_SUFFIX ${arch_suffix}
@@ -335,6 +364,8 @@ foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
LIB_FILES ${opencl_lib_files}
GEN_FILES ${opencl_gen_files}
ALIASES ${${d}_aliases}
+ # Link in the CLC builtins and internalize their symbols
+ INTERNAL_LINK_DEPENDENCIES $<TARGET_PROPERTY:builtins.link.clc-${arch_suffix},TARGET_FILE>
)
endforeach( d )
endforeach( t )
diff --git a/libclc/generic/include/clc/clcfunc.h b/libclc/clc/include/clc/clcfunc.h
similarity index 85%
rename from libclc/generic/include/clc/clcfunc.h
rename to libclc/clc/include/clc/clcfunc.h
index 086d780b970859..fe3406f64fecb8 100644
--- a/libclc/generic/include/clc/clcfunc.h
+++ b/libclc/clc/include/clc/clcfunc.h
@@ -1,3 +1,6 @@
+#ifndef __CLC_CLCFUNC_H_
+#define __CLC_CLCFUNC_H_
+
#define _CLC_OVERLOAD __attribute__((overloadable))
#define _CLC_DECL
#define _CLC_INLINE __attribute__((always_inline)) inline
@@ -11,3 +14,5 @@
#else
#define _CLC_DEF __attribute__((always_inline))
#endif
+
+#endif // __CLC_CLCFUNC_H_
diff --git a/libclc/generic/include/clc/clctypes.h b/libclc/clc/include/clc/clctypes.h
similarity index 97%
rename from libclc/generic/include/clc/clctypes.h
rename to libclc/clc/include/clc/clctypes.h
index 76b816d395c288..bc0936dd314637 100644
--- a/libclc/generic/include/clc/clctypes.h
+++ b/libclc/clc/include/clc/clctypes.h
@@ -1,3 +1,6 @@
+#ifndef __CLC_CLCTYPES_H_
+#define __CLC_CLCTYPES_H_
+
/* 6.1.1 Built-in Scalar Data Types */
typedef unsigned char uchar;
@@ -93,3 +96,5 @@ typedef __attribute__((ext_vector_type(4))) half half4;
typedef __attribute__((ext_vector_type(8))) half half8;
typedef __attribute__((ext_vector_type(16))) half half16;
#endif
+
+#endif // __CLC_CLCTYPES_H_
diff --git a/libclc/clc/include/clc/geometric/clc_dot.h b/libclc/clc/include/clc/geometric/clc_dot.h
new file mode 100644
index 00000000000000..e0e47ab2093efd
--- /dev/null
+++ b/libclc/clc/include/clc/geometric/clc_dot.h
@@ -0,0 +1,2 @@
+#define __CLC_BODY <clc/geometric/clc_dot.inc>
+#include <clc/geometric/floatn.inc>
diff --git a/libclc/clc/include/clc/geometric/clc_dot.inc b/libclc/clc/include/clc/geometric/clc_dot.inc
new file mode 100644
index 00000000000000..016b564df362d2
--- /dev/null
+++ b/libclc/clc/include/clc/geometric/clc_dot.inc
@@ -0,0 +1 @@
+_CLC_OVERLOAD _CLC_DECL __CLC_FLOAT __clc_dot(__CLC_FLOATN p0, __CLC_FLOATN p1);
diff --git a/libclc/clc/include/clc/internal/clc.h b/libclc/clc/include/clc/internal/clc.h
new file mode 100644
index 00000000000000..c3bdfd754105f7
--- /dev/null
+++ b/libclc/clc/include/clc/internal/clc.h
@@ -0,0 +1,26 @@
+#ifndef __CLC_INTERNAL_CLC_H_
+#define __CLC_INTERNAL_CLC_H_
+
+#ifndef cl_clang_storage_class_specifiers
+#error Implementation requires cl_clang_storage_class_specifiers extension!
+#endif
+
+#pragma OPENCL EXTENSION cl_clang_storage_class_specifiers : enable
+
+#ifdef cl_khr_fp64
+#pragma OPENCL EXTENSION cl_khr_fp64 : enable
+#endif
+
+#ifdef cl_khr_fp16
+#pragma OPENCL EXTENSION cl_khr_fp16 : enable
+#endif
+
+/* Function Attributes */
+#include <clc/clcfunc.h>
+
+/* 6.1 Supported Data Types */
+#include <clc/clctypes.h>
+
+#pragma OPENCL EXTENSION all : disable
+
+#endif // __CLC_INTERNAL_CLC_H_
diff --git a/libclc/clc/lib/clspv/SOURCES b/libclc/clc/lib/clspv/SOURCES
new file mode 100644
index 00000000000000..75a3130357c345
--- /dev/null
+++ b/libclc/clc/lib/clspv/SOURCES
@@ -0,0 +1 @@
+dummy.cl
diff --git a/libclc/clc/lib/clspv/dummy.cl b/libclc/clc/lib/clspv/dummy.cl
new file mode 100644
index 00000000000000..fab17ac780e375
--- /dev/null
+++ b/libclc/clc/lib/clspv/dummy.cl
@@ -0,0 +1 @@
+// Empty file
diff --git a/libclc/clc/lib/clspv64 b/libclc/clc/lib/clspv64
new file mode 120000
index 00000000000000..ea01ba94bc6368
--- /dev/null
+++ b/libclc/clc/lib/clspv64
@@ -0,0 +1 @@
+clspv
\ No newline at end of file
diff --git a/libclc/clc/lib/generic/SOURCES b/libclc/clc/lib/generic/SOURCES
new file mode 100644
index 00000000000000..fa2e4f50b99cd7
--- /dev/null
+++ b/libclc/clc/lib/generic/SOURCES
@@ -0,0 +1 @@
+geometric/clc_dot.cl
diff --git a/libclc/clc/lib/generic/geometric/clc_dot.cl b/libclc/clc/lib/generic/geometric/clc_dot.cl
new file mode 100644
index 00000000000000..bf0f19b51bc05e
--- /dev/null
+++ b/libclc/clc/lib/generic/geometric/clc_dot.cl
@@ -0,0 +1,57 @@
+#include <clc/internal/clc.h>
+
+_CLC_OVERLOAD _CLC_DEF float __clc_dot(float p0, float p1) { return p0 * p1; }
+
+_CLC_OVERLOAD _CLC_DEF float __clc_dot(float2 p0, float2 p1) {
+ return p0.x * p1.x + p0.y * p1.y;
+}
+
+_CLC_OVERLOAD _CLC_DEF float __clc_dot(float3 p0, float3 p1) {
+ return p0.x * p1.x + p0.y * p1.y + p0.z * p1.z;
+}
+
+_CLC_OVERLOAD _CLC_DEF float __clc_dot(float4 p0, float4 p1) {
+ return p0.x * p1.x + p0.y * p1.y + p0.z * p1.z + p0.w * p1.w;
+}
+
+#ifdef cl_khr_fp64
+
+#pragma OPENCL EXTENSION cl_khr_fp64 : enable
+
+_CLC_OVERLOAD _CLC_DEF double __clc_dot(double p0, double p1) {
+ return p0 * p1;
+}
+
+_CLC_OVERLOAD _CLC_DEF double __clc_dot(double2 p0, double2 p1) {
+ return p0.x * p1.x + p0.y * p1.y;
+}
+
+_CLC_OVERLOAD _CLC_DEF double __clc_dot(double3 p0, double3 p1) {
+ return p0.x * p1.x + p0.y * p1.y + p0.z * p1.z;
+}
+
+_CLC_OVERLOAD _CLC_DEF double __clc_dot(double4 p0, double4 p1) {
+ return p0.x * p1.x + p0.y * p1.y + p0.z * p1.z + p0.w * p1.w;
+}
+
+#endif
+
+#ifdef cl_khr_fp16
+
+#pragma OPENCL EXTENSION cl_khr_fp16 : enable
+
+_CLC_OVERLOAD _CLC_DEF half __clc_dot(half p0, half p1) { return p0 * p1; }
+
+_CLC_OVERLOAD _CLC_DEF half __clc_dot(half2 p0, half2 p1) {
+ return p0.x * p1.x + p0.y * p1.y;
+}
+
+_CLC_OVERLOAD _CLC_DEF half __clc_dot(half3 p0, half3 p1) {
+ return p0.x * p1.x + p0.y * p1.y + p0.z * p1.z;
+}
+
+_CLC_OVERLOAD _CLC_DEF half __clc_dot(half4 p0, half4 p1) {
+ return p0.x * p1.x + p0.y * p1.y + p0.z * p1.z + p0.w * p1.w;
+}
+
+#endif
diff --git a/libclc/clc/lib/spirv/SOURCES b/libclc/clc/lib/spirv/SOURCES
new file mode 100644
index 00000000000000..d8effd19613c8b
--- /dev/null
+++ b/libclc/clc/lib/spirv/SOURCES
@@ -0,0 +1,2 @@
+../generic/geometric/clc_dot.cl
+
diff --git a/libclc/clc/lib/spirv64/SOURCES b/libclc/clc/lib/spirv64/SOURCES
new file mode 100644
index 00000000000000..9200810ace38e7
--- /dev/null
+++ b/libclc/clc/lib/spirv64/SOURCES
@@ -0,0 +1 @@
+../generic/geometric/clc_dot.cl
diff --git a/libclc/cmake/modules/AddLibclc.cmake b/libclc/cmake/modules/AddLibclc.cmake
index dcd9a87dbe1108..955817124790eb 100644
--- a/libclc/cmake/modules/AddLibclc.cmake
+++ b/libclc/cmake/modules/AddLibclc.cmake
@@ -76,6 +76,8 @@ endfunction()
# Links together one or more bytecode files
#
# Arguments:
+# * INTERNALIZE
+# Set if --internalize flag should be passed when linking
# * TARGET <string>
# Custom target to create
# * INPUT <string> ...
@@ -84,7 +86,7 @@ endfunction()
# List of extra dependencies to inject
function(link_bc)
cmake_parse_arguments(ARG
- ""
+ "INTERNALIZE"
"TARGET"
"INPUTS;DEPENDENCIES"
${ARGN}
@@ -107,7 +109,7 @@ function(link_bc)
add_custom_command(
OUTPUT ${ARG_TARGET}.bc
- COMMAND ${llvm-link_exe} -o ${ARG_TARGET}.bc ${LINK_INPUT_ARG}
+ COMMAND ${llvm-link_exe} $<$<BOOL:${ARG_INTERNALIZE}>:--internalize> -o ${ARG_TARGET}.bc ${LINK_INPUT_ARG}
DEPENDS ${llvm-link_target} ${ARG_DEPENDENCIES} ${ARG_INPUTS} ${RSP_FILE}
)
@@ -195,6 +197,9 @@ endfunction()
# Triple used to compile
#
# Optional Arguments:
+# * CLC_INTERNAL
+# Pass if compiling the internal CLC builtin libraries, which are not
+# optimized and do not have aliases created.
# * LIB_FILES <string> ...
# List of files that should be built for this library
# * GEN_FILES <string> ...
@@ -205,11 +210,14 @@ endfunction()
# Optimization options (for opt)
# * ALIASES <string> ...
# List of aliases
+# * INTERNAL_LINK_DEPENDENCIES <string> ...
+# A list of extra bytecode files to link into the builtin library. Symbols
+# from these link dependencies will be internalized during linking.
function(add_libclc_builtin_set)
cmake_parse_arguments(ARG
- ""
+ "CLC_INTERNAL"
"ARCH;TRIPLE;ARCH_SUFFIX"
- "LIB_FILES;GEN_FILES;COMPILE_FLAGS;OPT_FLAGS;ALIASES"
+ "LIB_FILES;GEN_FILES;COMPILE_FLAGS;OPT_FLAGS;ALIASES;INTERNAL_LINK_DEPENDENCIES"
${ARGN}
)
@@ -258,12 +266,42 @@ function(add_libclc_builtin_set)
)
set_target_properties( ${builtins_comp_lib_tgt} PROPERTIES FOLDER "libclc/Device IR/Comp" )
+ if( NOT bytecode_files )
+ message(FATAL_ERROR "Cannot create an empty builtins library")
+ endif()
+
set( builtins_link_lib_tgt builtins.link.${ARG_ARCH_SUFFIX} )
- link_bc(
- TARGET ${builtins_link_lib_tgt}
- INPUTS ${bytecode_files}
- DEPENDENCIES ${builtins_comp_lib_tgt}
- )
+
+ if( NOT ARG_INTERNAL_LINK_DEPENDENCIES )
+ link_bc(
+ TARGET ${builtins_link_lib_tgt}
+ INPUTS ${bytecode_files}
+ DEPENDENCIES ${builtins_comp_lib_tgt}
+ )
+ else()
+ # If we have libraries to link while internalizing their symbols, we need
+ # two separate link steps; the --internalize flag applies to all link
+ # inputs but the first.
+ set( builtins_link_lib_tmp_tgt builtins.link.pre-deps.${ARG_ARCH_SUFFIX} )
+ link_bc(
+ TARGET ${builtins_link_lib_tmp_tgt}
+ INPUTS ${bytecode_files}
+ DEPENDENCIES ${builtins_comp_lib_tgt}
+ )
+ link_bc(
+ INTERNALIZE
+ TARGET ${builtins_link_lib_tgt}
+ INPUTS $<TARGET_PROPERTY:${builtins_link_lib_tmp_tgt},TARGET_FILE>
+ ${ARG_INTERNAL_LINK_DEPENDENCIES}
+ DEPENDENCIES ${builtins_link_lib_tmp_tgt}
+ )
+ endif()
+
+ # For the CLC internal builtins, exit here - we only optimize the targets'
+ # entry points once we've linked the CLC buitins into them
+ if( ARG_CLC_INTERNAL )
+ return()
+ endif()
set( builtins_link_lib $<TARGET_PROPERTY:${builtins_link_lib_tgt},TARGET_FILE> )
@@ -331,6 +369,9 @@ endfunction(add_libclc_builtin_set)
# LIB_FILE_LIST may be pre-populated and is appended to.
#
# Arguments:
+# * CLC_INTERNAL
+# Pass if compiling the internal CLC builtin libraries, which have a
+# different directory structure.
# * LIB_ROOT_DIR <string>
# Root directory containing target's lib files, relative to libclc root
# directory. If not provided, is set to '.'.
@@ -339,7 +380,7 @@ endfunction(add_libclc_builtin_set)
# files
function(libclc_configure_lib_source LIB_FILE_LIST)
cmake_parse_arguments(ARG
- ""
+ "CLC_INTERNAL"
"LIB_ROOT_DIR"
"DIRS"
${ARGN}
@@ -353,7 +394,11 @@ function(libclc_configure_lib_source LIB_FILE_LIST)
set( source_list )
foreach( l ${ARG_DIRS} )
foreach( s "SOURCES" "SOURCES_${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}" )
- file( TO_CMAKE_PATH ${ARG_LIB_ROOT_DIR}/${l}/lib/${s} file_loc )
+ if( ARG_CLC_INTERNAL )
+ file( TO_CMAKE_PATH ${ARG_LIB_ROOT_DIR}/lib/${l}/${s} file_loc )
+ else()
+ file( TO_CMAKE_PATH ${ARG_LIB_ROOT_DIR}/${l}/lib/${s} file_loc )
+ endif()
file( TO_CMAKE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${file_loc} loc )
# Prepend the location to give higher priority to
# specialized implementation
diff --git a/libclc/generic/lib/geometric/dot.cl b/libclc/generic/lib/geometric/dot.cl
index e58bc26f4333a7..e790d02636563c 100644
--- a/libclc/generic/lib/geometric/dot.cl
+++ b/libclc/generic/lib/geometric/dot.cl
@@ -1,19 +1,20 @@
#include <clc/clc.h>
+#include <clc/geometric/clc_dot.h>
_CLC_OVERLOAD _CLC_DEF float dot(float p0, float p1) {
- return p0*p1;
+ return __clc_dot(p0, p1);
}
_CLC_OVERLOAD _CLC_DEF float dot(float2 p0, float2 p1) {
- return p0.x*p1.x + p0.y*p1.y;
+ return __clc_dot(p0, p1);
}
_CLC_OVERLOAD _CLC_DEF float dot(float3 p0, float3 p1) {
- return p0.x*p1.x + p0.y*p1.y + p0.z*p1.z;
+ return __clc_dot(p0, p1);
}
_CLC_OVERLOAD _CLC_DEF float dot(float4 p0, float4 p1) {
- return p0.x*p1.x + p0.y*p1.y + p0.z*p1.z + p0.w*p1.w;
+ return __clc_dot(p0, p1);
}
#ifdef cl_khr_fp64
@@ -21,19 +22,19 @@ _CLC_OVERLOAD _CLC_DEF float dot(float4 p0, float4 p1) {
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
_CLC_OVERLOAD _CLC_DEF double dot(double p0, double p1) {
- return p0*p1;
+ return __clc_dot(p0, p1);
}
_CLC_OVERLOAD _CLC_DEF double dot(double2 p0, double2 p1) {
- return p0.x*p1.x + p0.y*p1.y;
+ return __clc_dot(p0, p1);
}
_CLC_OVERLOAD _CLC_DEF double dot(double3 p0, double3 p1) {
- return p0.x*p1.x + p0.y*p1.y + p0.z*p1.z;
+ return __clc_dot(p0, p1);
}
_CLC_OVERLOAD _CLC_DEF double dot(double4 p0, double4 p1) {
- return p0.x*p1.x + p0.y*p1.y + p0.z*p1.z + p0.w*p1.w;
+ return __clc_dot(p0, p1);
}
#endif
@@ -42,20 +43,18 @@ _CLC_OVERLOAD _CLC_DEF double dot(double4 p0, double4 p1) {
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
-_CLC_OVERLOAD _CLC_DEF half dot(half p0, half p1) {
- return p0*p1;
-}
+_CLC_OVERLOAD _CLC_DEF half dot(half p0, half p1) { return __clc_dot(p0, p1); }
_CLC_OVERLOAD _CLC_DEF half dot(half2 p0, half2 p1) {
- return p0.x*p1.x + p0.y*p1.y;
+ return __clc_dot(p0, p1);
}
_CLC_OVERLOAD _CLC_DEF half dot(half3 p0, half3 p1) {
- return p0.x*p1.x + p0.y*p1.y + p0.z*p1.z;
+ return __clc_dot(p0, p1);
}
_CLC_OVERLOAD _CLC_DEF half dot(half4 p0, half4 p1) {
- return p0.x*p1.x + p0.y*p1.y + p0.z*p1.z + p0.w*p1.w;
+ return __clc_dot(p0, p1);
}
#endif
More information about the cfe-commits
mailing list