From fa34b9e03206b04814dae58f830d883b5f99cb30 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Thu, 2 Feb 2023 15:05:54 -0600 Subject: [PATCH] [libc] Add startup code implementation for GPU targets This patch introduces startup code for executing `main` on a device compiled for the GPU. We will primarily use this to run standalone integration tests on the GPU. The actual execution of this routine will need to be provided by a `loader` utility to bootstrap execution on the GPU. Reviewed By: sivachandra Differential Revision: https://reviews.llvm.org/D143212 --- libc/startup/gpu/CMakeLists.txt | 63 ++++++++++++++++++++++++++++++++++ libc/startup/gpu/amdgpu/CMakeLists.txt | 17 +++++++++ libc/startup/gpu/amdgpu/start.cpp | 14 ++++++++ libc/startup/gpu/nvptx/CMakeLists.txt | 17 +++++++++ libc/startup/gpu/nvptx/start.cpp | 15 ++++++++ 5 files changed, 126 insertions(+) create mode 100644 libc/startup/gpu/CMakeLists.txt create mode 100644 libc/startup/gpu/amdgpu/CMakeLists.txt create mode 100644 libc/startup/gpu/amdgpu/start.cpp create mode 100644 libc/startup/gpu/nvptx/CMakeLists.txt create mode 100644 libc/startup/gpu/nvptx/start.cpp diff --git a/libc/startup/gpu/CMakeLists.txt b/libc/startup/gpu/CMakeLists.txt new file mode 100644 index 0000000..33afe1e --- /dev/null +++ b/libc/startup/gpu/CMakeLists.txt @@ -0,0 +1,63 @@ +function(add_startup_object name) + cmake_parse_arguments( + "ADD_STARTUP_OBJECT" + "ALIAS" # Option argument + "SRC" # Single value arguments + "DEPENDS;COMPILE_OPTIONS" # Multi value arguments + ${ARGN} + ) + + get_fq_target_name(${name} fq_target_name) + if(ADD_STARTUP_OBJECT_ALIAS) + get_fq_deps_list(fq_dep_list ${ADD_STARTUP_OBJECT_DEPENDS}) + add_library(${fq_target_name} ALIAS ${fq_dep_list}) + return() + endif() + + add_object_library( + ${name} + SRCS ${ADD_STARTUP_OBJECT_SRC} + DEPENDS ${ADD_STARTUP_OBJECT_DEPENDS} + COMPILE_OPTIONS ${ADD_STARTUP_OBJECT_COMPILE_OPTIONS} + ) + set_target_properties( + ${fq_target_name} + PROPERTIES + OUTPUT_NAME ${name}.o + ) +endfunction() + +if(LIBC_GPU_TARGET_ARCHITECTURE_IS_AMDGPU) + add_subdirectory(amdgpu) + + add_startup_object( + crt1 + ALIAS + DEPENDS + .amdgpu.crt1 + ) +elseif(LIBC_GPU_TARGET_ARCHITECTURE_IS_NVPTX) + add_subdirectory(nvptx) + + add_startup_object( + crt1 + ALIAS + DEPENDS + .nvptx.crt1 + ) +else() + # Skip building the startup code if there are no supported GPUs. + message(STATUS "Skipping startup for gpu target, no GPUs were detected") + return() +endif() + +add_custom_target(libc-startup) +set(startup_components crt1) +foreach(target IN LISTS startup_components) + set(fq_target_name libc.startup.gpu.${target}) + add_dependencies(libc-startup ${fq_target_name}) + install(FILES $ + DESTINATION ${CMAKE_INSTALL_LIBDIR} + RENAME $ + COMPONENT libc) +endforeach() diff --git a/libc/startup/gpu/amdgpu/CMakeLists.txt b/libc/startup/gpu/amdgpu/CMakeLists.txt new file mode 100644 index 0000000..8de0955 --- /dev/null +++ b/libc/startup/gpu/amdgpu/CMakeLists.txt @@ -0,0 +1,17 @@ +add_startup_object( + crt1 + SRC + start.cpp + COMPILE_OPTIONS + -ffreestanding # To avoid compiler warnings about calling the main function. + -fno-builtin + -nogpulib # Do not include any GPU vendor libraries. + -nostdinc + -mcpu=${LIBC_GPU_TARGET_ARCHITECTURE} + -emit-llvm # AMDGPU's intermediate object file format is bitcode. + --target=${LIBC_GPU_TARGET_TRIPLE} +) +get_fq_target_name(crt1 fq_name) + +# Ensure that clang uses the correct linker for this object type. +target_link_libraries(${fq_name} PUBLIC "--target=${LIBC_GPU_TARGET_TRIPLE}") diff --git a/libc/startup/gpu/amdgpu/start.cpp b/libc/startup/gpu/amdgpu/start.cpp new file mode 100644 index 0000000..3be3745 --- /dev/null +++ b/libc/startup/gpu/amdgpu/start.cpp @@ -0,0 +1,14 @@ +//===-- Implementation of crt for amdgpu ----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +extern "C" int main(int argc, char **argv); + +extern "C" [[gnu::visibility("protected"), clang::amdgpu_kernel]] void +_start(int argc, char **argv, int *ret) { + __atomic_fetch_or(ret, main(argc, argv), __ATOMIC_RELAXED); +} diff --git a/libc/startup/gpu/nvptx/CMakeLists.txt b/libc/startup/gpu/nvptx/CMakeLists.txt new file mode 100644 index 0000000..2057fcf --- /dev/null +++ b/libc/startup/gpu/nvptx/CMakeLists.txt @@ -0,0 +1,17 @@ +add_startup_object( + crt1 + SRC + start.cpp + COMPILE_OPTIONS + -ffreestanding # To avoid compiler warnings about calling the main function. + -fno-builtin + -nogpulib # Do not include any GPU vendor libraries. + -nostdinc + -x cuda # Use the CUDA toolchain to emit the `_start` kernel. + --offload-device-only + --offload-arch=${LIBC_GPU_TARGET_ARCHITECTURE} +) +get_fq_target_name(crt1 fq_name) + +# Ensure that clang uses the correct linker for this object type. +target_link_libraries(${fq_name} PUBLIC "--target=${LIBC_GPU_TARGET_TRIPLE}") diff --git a/libc/startup/gpu/nvptx/start.cpp b/libc/startup/gpu/nvptx/start.cpp new file mode 100644 index 0000000..6156942 --- /dev/null +++ b/libc/startup/gpu/nvptx/start.cpp @@ -0,0 +1,15 @@ +//===-- Implementation of crt for amdgpu ----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +extern "C" __attribute__((device)) int main(int argc, char **argv); + +// TODO: We shouldn't need to use the CUDA language to emit a kernel for NVPTX. +extern "C" [[gnu::visibility("protected")]] __attribute__((global)) void +_start(int argc, char **argv, int *ret) { + __atomic_fetch_or(ret, main(argc, argv), __ATOMIC_RELAXED); +} -- 2.7.4