Skip to content

[clang] Add the ability to link libclc OpenCL libraries #146503

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticDriverKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,9 @@ def warn_drv_fraw_string_literals_in_cxx11 : Warning<
"ignoring '-f%select{no-|}0raw-string-literals', which is only valid for C and C++ standards before C++11">,
InGroup<UnusedCommandLineArgument>;

def err_drv_libclc_not_found : Error<
"no libclc library '%0' found in the clang resource directory or in LIBRARY_PATH">;

def err_drv_invalid_malign_branch_EQ : Error<
"invalid argument '%0' to -malign-branch=; each element must be one of: %1">;

Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Driver/CommonArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,9 @@ void addOpenMPDeviceRTL(const Driver &D, const llvm::opt::ArgList &DriverArgs,
StringRef BitcodeSuffix, const llvm::Triple &Triple,
const ToolChain &HostTC);

void addOpenCLBuiltinsLib(const Driver &D, const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args);

void addOutlineAtomicsArgs(const Driver &D, const ToolChain &TC,
const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1421,6 +1421,8 @@ def openacc_macro_override_EQ

// End Clang specific/exclusive options for OpenACC.

def libclc_lib_EQ : Joined<["--"], "libclc-lib=">, Group<opencl_Group>,
HelpText<"Namespec of libclc OpenCL bitcode library to link">;
def libomptarget_amdgpu_bc_path_EQ : Joined<["--"], "libomptarget-amdgpu-bc-path=">, Group<i_Group>,
HelpText<"Path to libomptarget-amdgcn bitcode library">;
def libomptarget_amdgcn_bc_path_EQ : Joined<["--"], "libomptarget-amdgcn-bc-path=">, Group<i_Group>,
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Driver/ToolChains/AMDGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,8 @@ void AMDGPUToolChain::addClangTargetOptions(
CC1Args.push_back("-fvisibility=hidden");
CC1Args.push_back("-fapply-global-visibility-to-externs");
}

addOpenCLBuiltinsLib(getDriver(), DriverArgs, CC1Args);
}

void AMDGPUToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {
Expand Down
59 changes: 59 additions & 0 deletions clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2942,6 +2942,65 @@ void tools::addHIPRuntimeLibArgs(const ToolChain &TC, Compilation &C,
}
}

void tools::addOpenCLBuiltinsLib(const Driver &D,
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) {
// Check whether user specifies a libclc bytecode library
if (const Arg *A = DriverArgs.getLastArg(options::OPT_libclc_lib_EQ)) {
SmallVector<StringRef, 8> LibraryPaths;

// Add user defined library paths from LIBRARY_PATH.
std::optional<std::string> LibPath =
llvm::sys::Process::GetEnv("LIBRARY_PATH");
if (LibPath) {
SmallVector<StringRef, 8> Frags;
const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
llvm::SplitString(*LibPath, Frags, EnvPathSeparatorStr);
for (StringRef Path : Frags)
LibraryPaths.emplace_back(Path.trim());
}

// Find device libraries in <LLVM_DIR>/lib/clang/<ver>/lib/libclc/
SmallString<128> LibclcPath(D.ResourceDir);
llvm::sys::path::append(LibclcPath, "lib", "libclc");
LibraryPaths.emplace_back(LibclcPath);

bool FoundBCLibrary = false;
StringRef LibclcNamespec(A->getValue());

// If the namespec is of the form :filename, search for that file.
bool FilenameSearch = LibclcNamespec.starts_with(":");
SmallString<128> LibclcTargetFile(
LibclcNamespec.drop_front(FilenameSearch ? 1 : 0));

if (FilenameSearch && llvm::sys::fs::exists(LibclcTargetFile)) {
FoundBCLibrary = true;
CC1Args.push_back("-mlink-builtin-bitcode");
CC1Args.push_back(DriverArgs.MakeArgString(LibclcTargetFile));
} else {
// Search the library paths for the file
if (!FilenameSearch)
LibclcTargetFile += ".bc";

for (StringRef LibraryPath : LibraryPaths) {
SmallString<128> LibclcPath(LibraryPath);
llvm::sys::path::append(LibclcPath, LibclcTargetFile);
if (llvm::sys::fs::exists(LibclcPath)) {
FoundBCLibrary = true;
CC1Args.push_back("-mlink-builtin-bitcode");
CC1Args.push_back(DriverArgs.MakeArgString(LibclcPath));
break;
}
}
}

// Since the user requested a library, if we haven't one then report an
// error.
if (!FoundBCLibrary)
D.Diag(diag::err_drv_libclc_not_found) << LibclcTargetFile;
}
}

void tools::addOutlineAtomicsArgs(const Driver &D, const ToolChain &TC,
const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
Expand Down
Empty file.
Empty file.
10 changes: 10 additions & 0 deletions clang/test/Driver/opencl-libclc.cl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// RUN: %clang -### -target amdgcn-amd-amdhsa --no-offloadlib --libclc-lib=:%S/Inputs/libclc/libclc.bc %s 2>&1 | FileCheck %s
// RUN: env LIBRARY_PATH=%S/Inputs/libclc %clang -### -target amdgcn-amd-amdhsa --no-offloadlib --libclc-lib=libclc %s 2>&1 | FileCheck %s
// RUN: env LIBRARY_PATH=%S/Inputs/libclc %clang -### -target amdgcn-amd-amdhsa --no-offloadlib --libclc-lib=:libclc.bc %s 2>&1 | FileCheck %s

// RUN: env LIBRARY_PATH=%S/Inputs/libclc/subdir %clang -### -target amdgcn-amd-amdhsa --no-offloadlib --libclc-lib=libclc %s 2>&1 | FileCheck %s --check-prefix CHECK-SUBDIR
// RUN: env LIBRARY_PATH=%S/Inputs/libclc/subdir %clang -### -target amdgcn-amd-amdhsa --no-offloadlib --libclc-lib=:libclc.bc %s 2>&1 | FileCheck %s --check-prefix CHECK-SUBDIR
// RUN: env LIBRARY_PATH=%S/Inputs/libclc %clang -### -target amdgcn-amd-amdhsa --no-offloadlib --libclc-lib=:subdir/libclc.bc %s 2>&1 | FileCheck %s --check-prefix CHECK-SUBDIR

// CHECK: -mlink-builtin-bitcode{{.*}}Inputs{{/|\\\\}}libclc{{/|\\\\}}libclc.bc
// CHECK-SUBDIR: -mlink-builtin-bitcode{{.*}}Inputs{{/|\\\\}}libclc{{/|\\\\}}subdir{{/|\\\\}}libclc.bc
11 changes: 11 additions & 0 deletions libclc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ if( LIBCLC_STANDALONE_BUILD OR CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DI
set( ${tool}_target )
endforeach()
endif()

# Setup the paths where libclc runtimes should be stored.
set( LIBCLC_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR} )
set( LIBCLC_OUTPUT_LIBRARY_DIR ${LIBCLC_OUTPUT_DIR} )
else()
# In-tree configuration
set( LIBCLC_STANDALONE_BUILD FALSE )
Expand All @@ -82,6 +86,13 @@ else()
get_host_tool_path( llvm-link LLVM_LINK llvm-link_exe llvm-link_target )
get_host_tool_path( opt OPT opt_exe opt_target )
endif()

# Setup the paths where libclc runtimes should be stored. By default, in an
# in-tree build we place the libraries in clang's resource driectory.
get_clang_resource_dir( LIBCLC_OUTPUT_DIR PREFIX ${LLVM_LIBRARY_OUTPUT_INTDIR}/.. )

# Note we do not adhere to LLVM_ENABLE_PER_TARGET_RUNTIME_DIR.
set( LIBCLC_OUTPUT_LIBRARY_DIR ${LIBCLC_OUTPUT_DIR}/lib/libclc )
endif()

if( EXISTS ${LIBCLC_CUSTOM_LLVM_TOOLS_BINARY_DIR} )
Expand Down
49 changes: 28 additions & 21 deletions libclc/cmake/modules/AddLibclc.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,14 @@ function(link_bc)
endif()

add_custom_command(
OUTPUT ${ARG_TARGET}.bc
COMMAND ${llvm-link_exe} ${link_flags} -o ${ARG_TARGET}.bc ${LINK_INPUT_ARG}
OUTPUT ${LIBCLC_ARCH_OBJFILE_DIR}/${ARG_TARGET}.bc
COMMAND ${llvm-link_exe} ${link_flags} -o ${LIBCLC_ARCH_OBJFILE_DIR}/${ARG_TARGET}.bc ${LINK_INPUT_ARG}
DEPENDS ${llvm-link_target} ${ARG_DEPENDENCIES} ${ARG_INPUTS} ${RSP_FILE}
)

add_custom_target( ${ARG_TARGET} ALL DEPENDS ${ARG_TARGET}.bc )
add_custom_target( ${ARG_TARGET} ALL DEPENDS ${LIBCLC_ARCH_OBJFILE_DIR}/${ARG_TARGET}.bc )
set_target_properties( ${ARG_TARGET} PROPERTIES
TARGET_FILE ${CMAKE_CURRENT_BINARY_DIR}/${ARG_TARGET}.bc
TARGET_FILE ${LIBCLC_ARCH_OBJFILE_DIR}/${ARG_TARGET}.bc
FOLDER "libclc/Device IR/Linking"
)
endfunction()
Expand Down Expand Up @@ -358,58 +358,65 @@ function(add_libclc_builtin_set)

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}
add_custom_command( OUTPUT ${LIBCLC_OUTPUT_LIBRARY_DIR}/${spv_suffix}
COMMAND ${llvm-spirv_exe} ${spvflags} -o ${LIBCLC_OUTPUT_LIBRARY_DIR}/${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}" )
add_custom_target( "prepare-${spv_suffix}" ALL DEPENDS "${LIBCLC_OUTPUT_LIBRARY_DIR}/${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" )
install( FILES ${LIBCLC_OUTPUT_LIBRARY_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
add_custom_command( OUTPUT ${LIBCLC_ARCH_OBJFILE_DIR}/${builtins_opt_lib_tgt}.bc
COMMAND ${opt_exe} ${ARG_OPT_FLAGS} -o ${LIBCLC_ARCH_OBJFILE_DIR}/${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
ALL DEPENDS ${LIBCLC_ARCH_OBJFILE_DIR}/${builtins_opt_lib_tgt}.bc
)
set_target_properties( ${builtins_opt_lib_tgt} PROPERTIES
TARGET_FILE ${CMAKE_CURRENT_BINARY_DIR}/${builtins_opt_lib_tgt}.bc
TARGET_FILE ${LIBCLC_ARCH_OBJFILE_DIR}/${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" )
set( libclc_bc_lib ${LIBCLC_OUTPUT_LIBRARY_DIR}/${obj_suffix} )
add_custom_command( OUTPUT ${libclc_bc_lib}
COMMAND ${prepare_builtins_exe} -o ${libclc_bc_lib} ${builtins_opt_lib}
DEPENDS ${builtins_opt_lib} ${builtins_opt_lib_tgt} ${prepare_builtins_target}
WORKING_DIRECTORY ${LIBCLC_OUTPUT_LIBRARY_DIR}
)
add_custom_target( prepare-${obj_suffix} ALL DEPENDS ${libclc_bc_lib} )
set_target_properties( "prepare-${obj_suffix}" PROPERTIES
TARGET_FILE ${libclc_bc_lib}
FOLDER "libclc/Device IR/Prepare"
)

# nvptx-- targets don't include workitem builtins, and clspv targets don't
# include all OpenCL builtins
if( NOT ARG_ARCH MATCHES "^(nvptx|clspv)(64)?$" )
add_test( NAME external-calls-${obj_suffix}
COMMAND ./check_external_calls.sh ${CMAKE_CURRENT_BINARY_DIR}/${obj_suffix} ${LLVM_TOOLS_BINARY_DIR}
COMMAND ./check_external_calls.sh ${libclc_bc_lib} ${LLVM_TOOLS_BINARY_DIR}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
endif()

install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${obj_suffix} DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" )
install( FILES ${libclc_bc_lib} DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" )
foreach( a ${ARG_ALIASES} )
set( alias_suffix "${a}-${ARG_TRIPLE}.bc" )
add_custom_command(
OUTPUT ${alias_suffix}
COMMAND ${CMAKE_COMMAND} -E create_symlink ${obj_suffix} ${alias_suffix}
COMMAND ${CMAKE_COMMAND} -E create_symlink ${libclc_bc_lib} ${alias_suffix}
DEPENDS prepare-${obj_suffix} )
add_custom_target( alias-${alias_suffix} ALL DEPENDS ${alias_suffix} )
set_target_properties( alias-${alias_suffix} PROPERTIES FOLDER "libclc/Device IR/Aliases" )
Expand Down
Loading