[clang] [libclc] [libclc] Rework libclc naming convention to use the triple (PR #177465)
Joseph Huber via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 22 12:48:45 PST 2026
https://github.com/jhuber6 created https://github.com/llvm/llvm-project/pull/177465
Summary:
Right now all these libraries are installed in the `libclc/` directory
in the compiler's resource directory. We should instead follow the
per-target approach and install it according to the triple. The
sub-architectures will be put in a subdirectory as well.
I will do refactorings on this later to remove all the redundant targets
and pull this into common handling.
Also we should accept `--libclc-lib` without an argument to just find it
by default. I don't know what the plan here is since AMDGCN is the only
triple that uses this flag.
>From 1be9b63ec4d4b0f3479132cd05d41f60e34f3294 Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Thu, 22 Jan 2026 14:39:10 -0600
Subject: [PATCH] [libclc] Rework libclc naming convention to use the triple
Summary:
Right now all these libraries are installed in the `libclc/` directory
in the compiler's resource directory. We should instead follow the
per-target approach and install it according to the triple. The
sub-architectures will be put in a subdirectory as well.
I will do refactorings on this later to remove all the redundant targets
and pull this into common handling.
Also we should accept `--libclc-lib` without an argument to just find it
by default. I don't know what the plan here is since AMDGCN is the only
triple that uses this flag.
---
clang/lib/Driver/ToolChains/CommonArgs.cpp | 56 ++++++++++++++
.../lib/amdgcn-amd-amdhsa/gfx90a/libclc.bc | 0
.../lib/amdgcn-amd-amdhsa/libclc.bc | 0
clang/test/Driver/opencl-libclc.cl | 12 +++
libclc/CMakeLists.txt | 3 +-
libclc/cmake/modules/AddLibclc.cmake | 74 ++++++++-----------
6 files changed, 98 insertions(+), 47 deletions(-)
create mode 100644 clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/amdgcn-amd-amdhsa/gfx90a/libclc.bc
create mode 100644 clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/amdgcn-amd-amdhsa/libclc.bc
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 10a1a412eea08..15270570ae34e 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -3061,6 +3061,61 @@ void tools::addHIPRuntimeLibArgs(const ToolChain &TC, Compilation &C,
}
}
+void tools::addOpenCLBuiltinsLib(const Driver &D,
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) {
+ const Arg *A = DriverArgs.getLastArg(options::OPT_libclc_lib_EQ);
+ if (!A)
+ return;
+
+ // If the namespec is of the form :filename we use it exactly.
+ StringRef LibclcNamespec(A->getValue());
+ bool FilenameSearch = LibclcNamespec.consume_front(":");
+ if (FilenameSearch) {
+ SmallString<128> LibclcFile(LibclcNamespec);
+ if (llvm::sys::fs::exists(LibclcFile)) {
+ CC1Args.push_back("-mlink-builtin-bitcode");
+ CC1Args.push_back(DriverArgs.MakeArgString(LibclcFile));
+ return;
+ }
+ D.Diag(diag::err_drv_libclc_not_found) << LibclcFile;
+ return;
+ }
+
+ // The OpenCL libraries are stored in <ResourceDir>/lib/<triple>.
+ SmallString<128> BasePath(D.ResourceDir);
+ llvm::sys::path::append(BasePath, "lib");
+ llvm::sys::path::append(BasePath, D.getTargetTriple());
+
+ // First check for a CPU-specific library in <ResourceDir>/lib/<triple>/<CPU>.
+ // TODO: Factor this into common logic that checks for valid subtargets.
+ if (const Arg *CPUArg =
+ DriverArgs.getLastArg(options::OPT_mcpu_EQ, options::OPT_march_EQ)) {
+ StringRef CPU = CPUArg->getValue();
+ if (!CPU.empty()) {
+ SmallString<128> CPUPath(BasePath);
+ llvm::sys::path::append(CPUPath, CPU, "libclc.bc");
+ if (llvm::sys::fs::exists(CPUPath)) {
+ CC1Args.push_back("-mlink-builtin-bitcode");
+ CC1Args.push_back(DriverArgs.MakeArgString(CPUPath));
+ return;
+ }
+ }
+ }
+
+ // Fall back to the generic library for the triple.
+ SmallString<128> GenericPath(BasePath);
+ llvm::sys::path::append(GenericPath, "libclc.bc");
+ if (llvm::sys::fs::exists(GenericPath)) {
+ CC1Args.push_back("-mlink-builtin-bitcode");
+ CC1Args.push_back(DriverArgs.MakeArgString(GenericPath));
+ return;
+ }
+
+ D.Diag(diag::err_drv_libclc_not_found) << "libclc.bc";
+}
+
+#if 0
void tools::addOpenCLBuiltinsLib(const Driver &D,
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) {
@@ -3097,6 +3152,7 @@ void tools::addOpenCLBuiltinsLib(const Driver &D,
}
}
}
+#endif
void tools::addOutlineAtomicsArgs(const Driver &D, const ToolChain &TC,
const llvm::opt::ArgList &Args,
diff --git a/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/amdgcn-amd-amdhsa/gfx90a/libclc.bc b/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/amdgcn-amd-amdhsa/gfx90a/libclc.bc
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/amdgcn-amd-amdhsa/libclc.bc b/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/amdgcn-amd-amdhsa/libclc.bc
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/opencl-libclc.cl b/clang/test/Driver/opencl-libclc.cl
index 185690768c75b..f7428aeb9f922 100644
--- a/clang/test/Driver/opencl-libclc.cl
+++ b/clang/test/Driver/opencl-libclc.cl
@@ -7,3 +7,15 @@
// CHECK-SUBDIR: -mlink-builtin-bitcode{{.*}}Inputs{{/|\\\\}}libclc{{/|\\\\}}subdir{{/|\\\\}}libclc.bc
// CHECK-ERROR: no libclc library{{.*}}not-here.bc' found in the clang resource directory
+
+// RUN: %clang -### -target amdgcn-amd-amdhsa --no-offloadlib \
+// RUN: --libclc-lib= \
+// RUN: -resource-dir %S/Inputs/resource_dir_with_per_target_subdir \
+// RUN: -march=gfx90a %s 2>&1 | FileCheck %s --check-prefix=CHECK-GFX90A
+// CHECK-GFX90A: -mlink-builtin-bitcode{{.*}}resource_dir_with_per_target_subdir{{/|\\\\}}lib{{/|\\\\}}amdgcn-amd-amdhsa{{/|\\\\}}gfx90a{{/|\\\\}}libclc.bc
+
+// RUN: %clang -### -target amdgcn-amd-amdhsa --no-offloadlib \
+// RUN: --libclc-lib= \
+// RUN: -resource-dir %S/Inputs/resource_dir_with_per_target_subdir \
+// RUN: %s 2>&1 | FileCheck %s --check-prefix=CHECK-GENERIC
+// CHECK-GENERIC: -mlink-builtin-bitcode{{.*}}resource_dir_with_per_target_subdir{{/|\\\\}}lib{{/|\\\\}}amdgcn-amd-amdhsa{{/|\\\\}}libclc.bc
diff --git a/libclc/CMakeLists.txt b/libclc/CMakeLists.txt
index d060b71f3db11..a092d73db4eb4 100644
--- a/libclc/CMakeLists.txt
+++ b/libclc/CMakeLists.txt
@@ -110,9 +110,8 @@ else()
# in-tree build we place the libraries in clang's resource driectory.
include(GetClangResourceDir)
get_clang_resource_dir( LIBCLC_INSTALL_DIR )
- cmake_path( APPEND LIBCLC_INSTALL_DIR "lib" "libclc" )
+ cmake_path( APPEND LIBCLC_INSTALL_DIR "lib" )
- # Note we do not adhere to LLVM_ENABLE_PER_TARGET_RUNTIME_DIR.
cmake_path( GET LLVM_LIBRARY_OUTPUT_INTDIR PARENT_PATH LIBCLC_OUTPUT_LIBRARY_DIR )
cmake_path( APPEND LIBCLC_OUTPUT_LIBRARY_DIR ${LIBCLC_INSTALL_DIR} )
file( MAKE_DIRECTORY ${LIBCLC_OUTPUT_LIBRARY_DIR} )
diff --git a/libclc/cmake/modules/AddLibclc.cmake b/libclc/cmake/modules/AddLibclc.cmake
index 1ba53a9528f82..f5aceafad8ef5 100644
--- a/libclc/cmake/modules/AddLibclc.cmake
+++ b/libclc/cmake/modules/AddLibclc.cmake
@@ -226,33 +226,6 @@ function(get_libclc_device_info)
endif()
endfunction()
-# Install libclc artifacts.
-#
-# Arguments:
-# * FILES <string> ...
-# List of libclc artifact files to be installed.
-function(libclc_install)
- cmake_parse_arguments(ARG "" "" "FILES" ${ARGN})
-
- if( NOT ARG_FILES )
- message( FATAL_ERROR "Must provide FILES" )
- endif()
-
- if( NOT CMAKE_CFG_INTDIR STREQUAL "." )
- # Replace CMAKE_CFG_INTDIR with CMAKE_INSTALL_CONFIG_NAME for multiple-
- # configuration generators.
- string( REPLACE ${CMAKE_CFG_INTDIR} "\$\{CMAKE_INSTALL_CONFIG_NAME\}"
- files ${ARG_FILES} )
- else()
- set( files ${ARG_FILES} )
- endif()
-
- install(
- FILES ${files}
- DESTINATION ${LIBCLC_INSTALL_DIR}
- )
-endfunction()
-
# Compiles a list of library source files (provided by LIB_FILES) and compiles
# them to LLVM bytecode (or SPIR-V), links them together and optimizes them.
#
@@ -399,13 +372,14 @@ function(add_libclc_builtin_set)
return()
endif()
+ set( LIBCLC_OUTPUT_FILENAME libclc.bc )
set( builtins_link_lib $<TARGET_PROPERTY:${builtins_link_lib_tgt},TARGET_FILE> )
# For SPIR-V targets we diverage at this point and generate SPIR-V using the
# llvm-spirv tool.
if( ARG_ARCH STREQUAL spirv OR ARG_ARCH STREQUAL spirv64 )
- set( obj_suffix ${ARG_ARCH_SUFFIX}.spv )
- set( libclc_builtins_lib ${LIBCLC_OUTPUT_LIBRARY_DIR}/${obj_suffix} )
+ file( MAKE_DIRECTORY ${LIBCLC_OUTPUT_LIBRARY_DIR}/${ARG_TRIPLE} )
+ set( libclc_builtins_lib ${LIBCLC_OUTPUT_LIBRARY_DIR}/${ARG_TRIPLE}/libclc.spv )
if ( LIBCLC_USE_SPIRV_BACKEND )
add_custom_command( OUTPUT ${libclc_builtins_lib}
COMMAND ${clang_exe} -c --target=${ARG_TRIPLE} -x ir -o ${libclc_builtins_lib} ${builtins_link_lib}
@@ -419,8 +393,8 @@ function(add_libclc_builtin_set)
endif()
else()
# Non-SPIR-V targets add an extra step to optimize the bytecode
- set( obj_suffix ${ARG_ARCH_SUFFIX}.bc )
- set( libclc_builtins_lib ${LIBCLC_OUTPUT_LIBRARY_DIR}/${obj_suffix} )
+ file( MAKE_DIRECTORY ${LIBCLC_OUTPUT_LIBRARY_DIR}/${ARG_TRIPLE} )
+ set( libclc_builtins_lib ${LIBCLC_OUTPUT_LIBRARY_DIR}/${ARG_TRIPLE}/libclc.bc )
add_custom_command( OUTPUT ${libclc_builtins_lib}
COMMAND ${opt_exe} ${ARG_OPT_FLAGS} -o ${libclc_builtins_lib}
@@ -430,8 +404,8 @@ function(add_libclc_builtin_set)
endif()
# Add a 'library' target
- add_custom_target( library-${obj_suffix} ALL DEPENDS ${libclc_builtins_lib} )
- set_target_properties( "library-${obj_suffix}" PROPERTIES
+ add_custom_target( library-${ARG_ARCH_SUFFIX} ALL DEPENDS ${libclc_builtins_lib} )
+ set_target_properties( "library-${ARG_ARCH_SUFFIX}" PROPERTIES
TARGET_FILE ${libclc_builtins_lib}
FOLDER "libclc/Device IR/Library"
)
@@ -442,12 +416,16 @@ function(add_libclc_builtin_set)
if( NOT TARGET library-${ARG_TRIPLE} )
add_custom_target( library-${ARG_TRIPLE} ALL )
endif()
- add_dependencies( library-${ARG_TRIPLE} library-${obj_suffix} )
+ add_dependencies( library-${ARG_TRIPLE} library-${ARG_ARCH_SUFFIX} )
# Add dependency to top-level pseudo target to ease making other
# targets dependent on libclc.
add_dependencies( ${ARG_PARENT_TARGET} library-${ARG_TRIPLE} )
- libclc_install(FILES ${libclc_builtins_lib})
+ # Install the created library.
+ install(
+ FILES ${libclc_builtins_lib}
+ DESTINATION ${LIBCLC_INSTALL_DIR}/${ARG_TRIPLE}
+ )
# SPIR-V targets can exit early here
if( ARG_ARCH STREQUAL spirv OR ARG_ARCH STREQUAL spirv64 )
@@ -460,7 +438,7 @@ function(add_libclc_builtin_set)
# * nvptx64-- targets don't include workitem builtins
# * clspv targets don't include all OpenCL builtins
if( NOT ARG_ARCH MATCHES "^(nvptx|clspv)(64)?$" )
- add_test( NAME external-funcs-${obj_suffix}
+ add_test( NAME external-funcs-${ARG_ARCH_SUFFIX}
COMMAND ./check_external_funcs.sh ${libclc_builtins_lib} ${LLVM_TOOLS_BINARY_DIR}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
endif()
@@ -476,20 +454,26 @@ function(add_libclc_builtin_set)
set(LIBCLC_LINK_OR_COPY copy)
endif()
- set( alias_suffix "${a}-${ARG_TRIPLE}.bc" )
+ file( MAKE_DIRECTORY ${LIBCLC_OUTPUT_LIBRARY_DIR}/${ARG_TRIPLE}/${a} )
+ set( libclc_alias_lib ${LIBCLC_OUTPUT_LIBRARY_DIR}/${ARG_TRIPLE}/${a}/libclc.bc )
add_custom_command(
- OUTPUT ${LIBCLC_OUTPUT_LIBRARY_DIR}/${alias_suffix}
- COMMAND ${CMAKE_COMMAND} -E ${LIBCLC_LINK_OR_COPY} ${LIBCLC_LINK_OR_COPY_SOURCE} ${LIBCLC_OUTPUT_LIBRARY_DIR}/${alias_suffix}
- DEPENDS library-${obj_suffix}
+ OUTPUT ${libclc_alias_lib}
+ COMMAND ${CMAKE_COMMAND} -E ${LIBCLC_LINK_OR_COPY} ${LIBCLC_LINK_OR_COPY_SOURCE} ${libclc_alias_lib}
+ DEPENDS library-${ARG_ARCH_SUFFIX}
)
- add_custom_target( alias-${alias_suffix} ALL
- DEPENDS ${LIBCLC_OUTPUT_LIBRARY_DIR}/${alias_suffix}
+ add_custom_target( alias-${a}-${ARG_TRIPLE} ALL
+ DEPENDS ${libclc_alias_lib}
)
- add_dependencies( ${ARG_PARENT_TARGET} alias-${alias_suffix} )
- set_target_properties( alias-${alias_suffix}
+ add_dependencies( ${ARG_PARENT_TARGET} alias-${a}-${ARG_TRIPLE} )
+ set_target_properties( alias-${a}-${ARG_TRIPLE}
PROPERTIES FOLDER "libclc/Device IR/Aliases"
)
- libclc_install(FILES ${LIBCLC_OUTPUT_LIBRARY_DIR}/${alias_suffix})
+
+ # Install the library
+ install(
+ FILES ${libclc_alias_lib}
+ DESTINATION ${LIBCLC_INSTALL_DIR}/${ARG_TRIPLE}/${a}
+ )
endforeach( a )
endfunction(add_libclc_builtin_set)
More information about the cfe-commits
mailing list