https://github.com/fineg74 updated https://github.com/llvm/llvm-project/pull/208129
>From 5c826046993d1ee5589e249b5cd570342f059087 Mon Sep 17 00:00:00 2001 From: "Fine, Gregory" <[email protected]> Date: Tue, 7 Jul 2026 17:59:27 -0700 Subject: [PATCH] Add support to build and run libc tests with spirv backend --- clang/lib/Headers/llvm_libc_wrappers/stdlib.h | 5 +- libc/CMakeLists.txt | 2 +- libc/cmake/modules/LLVMLibCLibraryRules.cmake | 2 +- libc/cmake/modules/LLVMLibCTestRules.cmake | 104 ++++++++++++------ .../modules/prepare_libc_gpu_build.cmake | 6 + libc/config/gpu/spirv/entrypoints.txt | 47 ++++++++ libc/config/gpu/spirv/headers.txt | 2 + libc/src/__support/GPU/utils.h | 7 +- libc/startup/gpu/CMakeLists.txt | 13 ++- libc/test/UnitTest/CMakeLists.txt | 26 +++-- llvm/runtimes/CMakeLists.txt | 2 +- llvm/tools/llvm-gpu-loader/CMakeLists.txt | 1 + .../tools/llvm-gpu-loader/llvm-gpu-loader.cpp | 15 ++- 13 files changed, 180 insertions(+), 52 deletions(-) diff --git a/clang/lib/Headers/llvm_libc_wrappers/stdlib.h b/clang/lib/Headers/llvm_libc_wrappers/stdlib.h index 7af5e2ebe031a..6d4987936b295 100644 --- a/clang/lib/Headers/llvm_libc_wrappers/stdlib.h +++ b/clang/lib/Headers/llvm_libc_wrappers/stdlib.h @@ -9,13 +9,14 @@ #ifndef __CLANG_LLVM_LIBC_WRAPPERS_STDLIB_H__ #define __CLANG_LLVM_LIBC_WRAPPERS_STDLIB_H__ -#if !defined(_OPENMP) && !defined(__HIP__) && !defined(__CUDA__) +#if !defined(_OPENMP) && !defined(__HIP__) && !defined(__CUDA__) && \ + !defined(__SPIRV__) #error "This file is for GPU offloading compilation only" #endif #include_next <stdlib.h> -#if defined(__HIP__) || defined(__CUDA__) +#if defined(__HIP__) || defined(__CUDA__) || defined(__SPIRV__) #define __LIBC_ATTRS __attribute__((device)) #else #define __LIBC_ATTRS diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index 6ddd75a0a3335..efa506d1a461c 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -422,7 +422,7 @@ add_subdirectory(hdr) add_subdirectory(src) add_subdirectory(utils) -if(LLVM_LIBC_FULL_BUILD AND NOT LIBC_TARGET_ARCHITECTURE_IS_SPIRV) +if(LLVM_LIBC_FULL_BUILD) # The startup system can potentially depend on the library components so add # it after the library implementation directories. add_subdirectory(startup) diff --git a/libc/cmake/modules/LLVMLibCLibraryRules.cmake b/libc/cmake/modules/LLVMLibCLibraryRules.cmake index 2df8f49100b99..9db9358a8131c 100644 --- a/libc/cmake/modules/LLVMLibCLibraryRules.cmake +++ b/libc/cmake/modules/LLVMLibCLibraryRules.cmake @@ -111,7 +111,7 @@ function(add_bitcode_entrypoint_library target_name base_target_name) add_executable(${target_name} ${objects}) if(LIBC_TARGET_ARCHITECTURE_IS_SPIRV) target_link_options(${target_name} PRIVATE "${LIBC_COMPILE_OPTIONS_DEFAULT}" - "-nostdlib" "-emit-llvm") + "-nostdlib" "-flto" "-emit-llvm") else() target_link_options(${target_name} PRIVATE "${LIBC_COMPILE_OPTIONS_DEFAULT}" "-r" "-nostdlib" "-flto" "-Wl,--lto-emit-llvm") diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake index d86fb4369a381..b9f3dfbb434e7 100644 --- a/libc/cmake/modules/LLVMLibCTestRules.cmake +++ b/libc/cmake/modules/LLVMLibCTestRules.cmake @@ -110,6 +110,9 @@ function(_get_hermetic_test_compile_options output_var) list(APPEND compile_options -Wno-multi-gpu --cuda-path=${LIBC_CUDA_ROOT} -nogpulib -march=${LIBC_GPU_TARGET_ARCHITECTURE} -fno-use-cxa-atexit) + elseif(LIBC_TARGET_ARCHITECTURE_IS_SPIRV) + list(APPEND compile_options + -nogpulib -flto) endif() set(${output_var} ${compile_options} PARENT_SCOPE) @@ -586,16 +589,18 @@ function(add_integration_test test_name) list(REMOVE_DUPLICATES link_object_files) # Make a library of all deps - add_library( - ${fq_target_name}.__libc__ - STATIC - EXCLUDE_FROM_ALL - ${link_object_files} - ) - set_target_properties(${fq_target_name}.__libc__ - PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - set_target_properties(${fq_target_name}.__libc__ - PROPERTIES ARCHIVE_OUTPUT_NAME ${fq_target_name}.libc) + if(NOT LIBC_TARGET_ARCHITECTURE_IS_SPIRV) + add_library( + ${fq_target_name}.__libc__ + STATIC + EXCLUDE_FROM_ALL + ${link_object_files} + ) + set_target_properties(${fq_target_name}.__libc__ + PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + set_target_properties(${fq_target_name}.__libc__ + PROPERTIES ARCHIVE_OUTPUT_NAME ${fq_target_name}.libc) + endif() set(fq_build_target_name ${fq_target_name}.__build__) add_executable( @@ -627,6 +632,10 @@ function(add_integration_test test_name) "-Wl,-mllvm,-nvptx-emit-init-fini-kernel" -march=${LIBC_GPU_TARGET_ARCHITECTURE} -nostdlib -static "--cuda-path=${LIBC_CUDA_ROOT}") + elseif(LIBC_TARGET_ARCHITECTURE_IS_SPIRV) + target_link_options(${fq_build_target_name} PRIVATE + ${LIBC_COMPILE_OPTIONS_DEFAULT} ${INTEGRATION_TEST_COMPILE_OPTIONS} + -nostdlib -flto -Wno-multi-gpu) elseif(LIBC_CC_SUPPORTS_NOSTDLIBPP) set(link_options -nolibc @@ -650,13 +659,21 @@ function(add_integration_test test_name) target_link_options(${fq_build_target_name} PRIVATE ${link_options}) list(APPEND compiler_runtime ${LIBGCC_S_LOCATION}) endif() - target_link_libraries( - ${fq_build_target_name} - libc.startup.${LIBC_TARGET_OS}.crt1 - libc.test.IntegrationTest.test - ${fq_target_name}.__libc__ - ${compiler_runtime} - ) + if(LIBC_TARGET_ARCHITECTURE_IS_SPIRV) + target_link_libraries( + ${fq_build_target_name} + ${link_object_files} + ${compiler_runtime} + ) + else() + target_link_libraries( + ${fq_build_target_name} + libc.startup.${LIBC_TARGET_OS}.crt1 + libc.test.IntegrationTest.test + ${fq_target_name}.__libc__ + ${compiler_runtime} + ) + endif() add_dependencies(${fq_build_target_name} libc.test.IntegrationTest.test ${INTEGRATION_TEST_DEPENDS}) @@ -804,16 +821,18 @@ function(add_libc_hermetic test_name) list(REMOVE_DUPLICATES link_object_files) # Make a library of all deps - add_library( - ${fq_target_name}.__libc__ - STATIC - EXCLUDE_FROM_ALL - ${link_object_files} - ) - set_target_properties(${fq_target_name}.__libc__ - PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - set_target_properties(${fq_target_name}.__libc__ - PROPERTIES ARCHIVE_OUTPUT_NAME ${fq_target_name}.libc) + if(NOT LIBC_TARGET_ARCHITECTURE_IS_SPIRV) + add_library( + ${fq_target_name}.__libc__ + STATIC + EXCLUDE_FROM_ALL + ${link_object_files} + ) + set_target_properties(${fq_target_name}.__libc__ + PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + set_target_properties(${fq_target_name}.__libc__ + PROPERTIES ARCHIVE_OUTPUT_NAME ${fq_target_name}.libc) + endif() if(HERMETIC_TEST_NO_RUN_POSTBUILD) set(fq_build_target_name ${fq_target_name}) @@ -866,6 +885,10 @@ function(add_libc_hermetic test_name) "-Wl,-mllvm,-nvptx-emit-init-fini-kernel" -march=${LIBC_GPU_TARGET_ARCHITECTURE} -nostdlib -static "--cuda-path=${LIBC_CUDA_ROOT}") + elseif(LIBC_TARGET_ARCHITECTURE_IS_SPIRV) + target_link_options(${fq_build_target_name} PRIVATE + ${LIBC_COMPILE_OPTIONS_DEFAULT} + -nostdlib -flto -Wno-multi-gpu) elseif(LIBC_CC_SUPPORTS_NOSTDLIBPP) set(link_options -nolibc @@ -889,15 +912,26 @@ function(add_libc_hermetic test_name) target_link_options(${fq_build_target_name} PRIVATE ${link_options}) list(APPEND compiler_runtime ${LIBGCC_S_LOCATION}) endif() - target_link_libraries( - ${fq_build_target_name} - PRIVATE - libc.startup.${LIBC_TARGET_OS}.crt1 - ${link_libraries} - LibcHermeticTestSupport.hermetic - ${fq_target_name}.__libc__ - ${compiler_runtime} + if(LIBC_TARGET_ARCHITECTURE_IS_SPIRV) + target_link_libraries( + ${fq_build_target_name} + PRIVATE + ${link_libraries} + LibcHermeticTestSupport.hermetic + ${link_object_files} + ${compiler_runtime} ) + else() + target_link_libraries( + ${fq_build_target_name} + PRIVATE + libc.startup.${LIBC_TARGET_OS}.crt1 + ${link_libraries} + LibcHermeticTestSupport.hermetic + ${fq_target_name}.__libc__ + ${compiler_runtime} + ) + endif() add_dependencies(${fq_build_target_name} LibcTest.hermetic libc.test.UnitTest.ErrnoSetterMatcher diff --git a/libc/cmake/modules/prepare_libc_gpu_build.cmake b/libc/cmake/modules/prepare_libc_gpu_build.cmake index 36ab321e4994c..15426dada3462 100644 --- a/libc/cmake/modules/prepare_libc_gpu_build.cmake +++ b/libc/cmake/modules/prepare_libc_gpu_build.cmake @@ -39,6 +39,8 @@ if(LIBC_TARGET_ARCHITECTURE_IS_AMDGPU) check_cxx_compiler_flag(-mcpu=native PLATFORM_HAS_GPU) elseif(LIBC_TARGET_ARCHITECTURE_IS_NVPTX) check_cxx_compiler_flag(-march=native PLATFORM_HAS_GPU) +elseif(LIBC_TARGET_ARCHITECTURE_IS_SPIRV) + set(PLATFORM_HAS_GPU TRUE) endif() set(gpu_test_architecture "") @@ -50,6 +52,10 @@ elseif(DEFINED LLVM_TARGETS_TO_BUILD AND LIBC_TARGET_ARCHITECTURE_IS_NVPTX AND NOT "NVPTX" IN_LIST LLVM_TARGETS_TO_BUILD) set(LIBC_GPU_TESTS_DISABLED TRUE) message(STATUS "NVPTX backend is not available, tests will not be built") +elseif(DEFINED LLVM_TARGETS_TO_BUILD AND LIBC_TARGET_ARCHITECTURE_IS_SPIRV + AND NOT "SPIRV" IN_LIST LLVM_TARGETS_TO_BUILD) + set(LIBC_GPU_TESTS_DISABLED TRUE) + message(STATUS "SPIRV backend is not available, tests will not be built") elseif(LIBC_GPU_TEST_ARCHITECTURE) set(LIBC_GPU_TESTS_DISABLED FALSE) set(gpu_test_architecture ${LIBC_GPU_TEST_ARCHITECTURE}) diff --git a/libc/config/gpu/spirv/entrypoints.txt b/libc/config/gpu/spirv/entrypoints.txt index 36c98339582cd..b2fe92ac15adc 100644 --- a/libc/config/gpu/spirv/entrypoints.txt +++ b/libc/config/gpu/spirv/entrypoints.txt @@ -85,6 +85,53 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.strings.strcasecmp libc.src.strings.strncasecmp + # stdlib.h entrypoints + libc.src.stdlib._Exit + libc.src.stdlib.abort + libc.src.stdlib.abs + libc.src.stdlib.atexit + libc.src.stdlib.atof + libc.src.stdlib.atoi + libc.src.stdlib.atol + libc.src.stdlib.atoll + libc.src.stdlib.bsearch + libc.src.stdlib.div + libc.src.stdlib.exit + libc.src.stdlib.labs + libc.src.stdlib.ldiv + libc.src.stdlib.llabs + libc.src.stdlib.lldiv + libc.src.stdlib.memalignment + libc.src.stdlib.qsort + libc.src.stdlib.qsort_r + libc.src.stdlib.rand + libc.src.stdlib.srand + libc.src.stdlib.strtod + libc.src.stdlib.strtod_l + libc.src.stdlib.strtof + libc.src.stdlib.strtof_l + libc.src.stdlib.strtol + libc.src.stdlib.strtol_l + libc.src.stdlib.strtold + libc.src.stdlib.strtold_l + libc.src.stdlib.strtoll + libc.src.stdlib.strtoll_l + libc.src.stdlib.strtoul + libc.src.stdlib.strtoul_l + libc.src.stdlib.strtoull + libc.src.stdlib.strtoull_l + libc.src.stdlib.at_quick_exit + libc.src.stdlib.quick_exit + libc.src.stdlib.getenv + libc.src.stdlib.system + + # TODO: Implement these correctly + libc.src.stdlib.aligned_alloc + libc.src.stdlib.calloc + libc.src.stdlib.free + libc.src.stdlib.malloc + libc.src.stdlib.realloc + ) set(TARGET_LIBM_ENTRYPOINTS diff --git a/libc/config/gpu/spirv/headers.txt b/libc/config/gpu/spirv/headers.txt index ae5e0de66c7a2..e81157d349b73 100644 --- a/libc/config/gpu/spirv/headers.txt +++ b/libc/config/gpu/spirv/headers.txt @@ -2,4 +2,6 @@ set(TARGET_PUBLIC_HEADERS libc.include.ctype libc.include.string libc.include.strings + libc.include.errno + libc.include.stdlib ) diff --git a/libc/src/__support/GPU/utils.h b/libc/src/__support/GPU/utils.h index e12684bf25c6a..15d2088c52adb 100644 --- a/libc/src/__support/GPU/utils.h +++ b/libc/src/__support/GPU/utils.h @@ -126,12 +126,17 @@ LIBC_INLINE uint32_t scan(uint64_t lane_mask, uint32_t x) { return __gpu_prefix_scan_add_u32(lane_mask, x); } +#if defined(LIBC_TARGET_ARCH_IS_SPIRV) +LIBC_INLINE uint64_t fixed_frequency_clock() { return 0; } + +LIBC_INLINE uint64_t processor_clock() { return 0; } +#else LIBC_INLINE uint64_t fixed_frequency_clock() { return __builtin_readsteadycounter(); } LIBC_INLINE uint64_t processor_clock() { return __builtin_readcyclecounter(); } - +#endif } // namespace gpu } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/startup/gpu/CMakeLists.txt b/libc/startup/gpu/CMakeLists.txt index 12cb891a687d8..191da218cbed0 100644 --- a/libc/startup/gpu/CMakeLists.txt +++ b/libc/startup/gpu/CMakeLists.txt @@ -33,9 +33,16 @@ function(add_startup_object name) set_target_properties(${fq_target_name}.exe PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${LIBC_LIBRARY_DIR} RUNTIME_OUTPUT_NAME ${name}.o) - target_link_options(${fq_target_name}.exe PRIVATE - ${LIBC_COMPILE_OPTIONS_DEFAULT} - "-r" "-nostdlib" "-flto" "-Wl,--lto-emit-llvm") + if (LIBC_TARGET_ARCHITECTURE_IS_SPIRV) + target_link_options(${fq_target_name}.exe PRIVATE + ${LIBC_COMPILE_OPTIONS_DEFAULT} + "-nostdlib" "-flto" + ) + else() + target_link_options(${fq_target_name}.exe PRIVATE + ${LIBC_COMPILE_OPTIONS_DEFAULT} + "-r" "-nostdlib" "-flto" "-Wl,--lto-emit-llvm") + endif() endif() endfunction() diff --git a/libc/test/UnitTest/CMakeLists.txt b/libc/test/UnitTest/CMakeLists.txt index 02489107efc06..f3311294a0863 100644 --- a/libc/test/UnitTest/CMakeLists.txt +++ b/libc/test/UnitTest/CMakeLists.txt @@ -12,13 +12,25 @@ function(add_unittest_framework_library name) endif() foreach(lib IN ITEMS ${name}.unit ${name}.hermetic) - add_library( - ${lib} - STATIC - EXCLUDE_FROM_ALL - ${TEST_LIB_SRCS} - ${TEST_LIB_HDRS} - ) + if(LIBC_TARGET_ARCHITECTURE_IS_SPIRV) + add_library( + ${lib} + OBJECT + EXCLUDE_FROM_ALL + ${TEST_LIB_SRCS} + ${TEST_LIB_HDRS} + ) + target_link_options(${lib} PRIVATE + "-nostdlib" "-flto") + else() + add_library( + ${lib} + STATIC + EXCLUDE_FROM_ALL + ${TEST_LIB_SRCS} + ${TEST_LIB_HDRS} + ) + endif() target_include_directories(${lib} PRIVATE ${LIBC_SOURCE_DIR}) if(TARGET libc.src.time.clock) target_compile_definitions(${lib} PRIVATE TARGET_SUPPORTS_CLOCK) diff --git a/llvm/runtimes/CMakeLists.txt b/llvm/runtimes/CMakeLists.txt index 501ea55a327c7..5025343e33e02 100644 --- a/llvm/runtimes/CMakeLists.txt +++ b/llvm/runtimes/CMakeLists.txt @@ -632,7 +632,7 @@ if(build_runtimes) if(LLVM_LIBC_GPU_BUILD) set(_gpu_loader "${LLVM_TOOLS_BINARY_DIR}/llvm-gpu-loader${CMAKE_EXECUTABLE_SUFFIX}") foreach(name ${LLVM_RUNTIME_TARGETS}) - if(name MATCHES "^(amdgcn|nvptx)") + if(name MATCHES "^(amdgcn|nvptx|spirv)") set(RUNTIMES_${name}_CMAKE_CROSSCOMPILING_EMULATOR "${_gpu_loader}" CACHE STRING "") endif() endforeach() diff --git a/llvm/tools/llvm-gpu-loader/CMakeLists.txt b/llvm/tools/llvm-gpu-loader/CMakeLists.txt index 37377ddc0506b..96d7b60a83402 100644 --- a/llvm/tools/llvm-gpu-loader/CMakeLists.txt +++ b/llvm/tools/llvm-gpu-loader/CMakeLists.txt @@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS BinaryFormat TargetParser Support + FrontendOffloading ) add_llvm_tool(llvm-gpu-loader diff --git a/llvm/tools/llvm-gpu-loader/llvm-gpu-loader.cpp b/llvm/tools/llvm-gpu-loader/llvm-gpu-loader.cpp index b17403406c43f..e77710232a81c 100644 --- a/llvm/tools/llvm-gpu-loader/llvm-gpu-loader.cpp +++ b/llvm/tools/llvm-gpu-loader/llvm-gpu-loader.cpp @@ -15,6 +15,7 @@ #include "llvm-gpu-loader.h" #include "llvm/BinaryFormat/Magic.h" +#include "llvm/Frontend/Offloading/Utility.h" #include "llvm/Object/ELF.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/CommandLine.h" @@ -207,7 +208,7 @@ int main(int argc, const char **argv, const char **envp) { handleError(errorCodeToError(EC)); MemoryBufferRef Image = **ImageOrErr; - ol_platform_backend_t Backend; + ol_platform_backend_t Backend = OL_PLATFORM_BACKEND_UNKNOWN; ol_init_args_t InitArgs = OL_INIT_ARGS_INIT; file_magic Magic = identify_magic(Image.getBuffer()); @@ -224,12 +225,22 @@ int main(int argc, const char **argv, const char **envp) { case ELF::EM_CUDA: Backend = OL_PLATFORM_BACKEND_CUDA; break; + case ELF::EM_INTELGT: + Backend = OL_PLATFORM_BACKEND_LEVEL_ZERO; + break; default: handleError(createStringError( "unhandled ELF architecture: %s", ELF::convertEMachineToArchName(ElfOrErr->getHeader().e_machine) .data())); } + } else if (Magic == file_magic::spirv_object) { + // SPIR-V objects are assumed to be for Level Zero for now as that is the + // only platform that currently supports them. + Backend = OL_PLATFORM_BACKEND_LEVEL_ZERO; + } + + if (Backend != OL_PLATFORM_BACKEND_UNKNOWN) { InitArgs.NumPlatforms = 1; InitArgs.Platforms = &Backend; } @@ -239,6 +250,8 @@ int main(int argc, const char **argv, const char **envp) { [](const std::string &Arg) { return Arg.c_str(); }); OFFLOAD_ERR(olInit(&InitArgs)); + if (InitArgs.NumPlatforms == 0) + handleError(createStringError("No compatible platforms were found")); ol_device_handle_t Device = findDevice(Image); if (!Device) handleError(createStringError("No compatible device was found")); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
