Files
TheRock/rocm-systems/projects/rocshmem/cmake/DeviceBitcode.cmake
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

265 lines
10 KiB
CMake

###############################################################################
# Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
#
# SPDX-License-Identifier: MIT
###############################################################################
# Device bitcode for JIT linking: librocshmem_device_{arch}.bc
find_program(LLVM_CLANG clang++
PATHS
${ROCM_PATH}/llvm/bin
${THEROCK_TOOLCHAIN_ROOT}/lib/llvm/bin
NO_DEFAULT_PATH QUIET)
find_program(LLVM_LINK llvm-link
PATHS
${ROCM_PATH}/llvm/bin
${THEROCK_TOOLCHAIN_ROOT}/lib/llvm/bin
NO_DEFAULT_PATH QUIET)
find_program(LLVM_OPT opt
PATHS
${ROCM_PATH}/llvm/bin
${THEROCK_TOOLCHAIN_ROOT}/lib/llvm/bin
NO_DEFAULT_PATH QUIET)
if(NOT LLVM_CLANG OR NOT LLVM_LINK OR NOT LLVM_OPT)
message(WARNING "ROCm LLVM tools (clang++, llvm-link, opt) not found under "
"${ROCM_PATH}/llvm/bin; skipping device bitcode targets.")
return()
endif()
# Strip feature suffixes (gfx942:sramecc+:xnack- → gfx942) and deduplicate.
function(strip_arch_features targets_list out_var)
set(_result "")
foreach(_t ${targets_list})
string(REGEX REPLACE ":.*" "" _base "${_t}")
list(APPEND _result "${_base}")
endforeach()
list(REMOVE_DUPLICATES _result)
set(${out_var} "${_result}" PARENT_SCOPE)
endfunction()
# Convert arch feature suffix to clang -Xclang -target-feature flags.
# gfx950:sramecc+:xnack- -> "-Xclang;-target-feature;-Xclang;+sramecc;-Xclang;-target-feature;-Xclang;-xnack"
# Caller passes the list directly to add_custom_command COMMAND.
function(arch_features_to_target_feature_flags full_arch out_var)
string(REPLACE ":" ";" _all_tokens "${full_arch}")
list(LENGTH _all_tokens _ntokens)
set(_flags "")
if(_ntokens GREATER 1)
list(SUBLIST _all_tokens 1 -1 _feat_tokens)
foreach(_tok ${_feat_tokens})
if(_tok STREQUAL "")
continue()
endif()
# "sramecc+" -> "+sramecc", "xnack-" -> "-xnack"
string(REGEX REPLACE "([a-zA-Z0-9_]+)([+-])$" "\\2\\1" _feat "${_tok}")
list(APPEND _flags -Xclang -target-feature -Xclang ${_feat})
endforeach()
endif()
set(${out_var} "${_flags}" PARENT_SCOPE)
endfunction()
# Resolve the target arch list: GPU_TARGETS CMake var -> auto-detect local GPUs.
# Both accept comma- or semicolon-separated lists.
if(GPU_TARGETS)
# Convert comma-separated string to CMake list (semicolon-separated)
# This handles both -DGPU_TARGETS=gfx942,gfx950 and -DGPU_TARGETS="gfx942;gfx950"
string(REPLACE "," ";" _GPU_TARGETS_LIST "${GPU_TARGETS}")
strip_arch_features("${_GPU_TARGETS_LIST}" _BITCODE_DEFAULT_ARCHS)
elseif(COMMAND rocm_local_targets)
rocm_local_targets(_LOCAL_GPUS)
if(_LOCAL_GPUS)
strip_arch_features("${_LOCAL_GPUS}" _BITCODE_DEFAULT_ARCHS)
message(STATUS "GPU_TARGETS not set; auto-detected local GPU(s) for device bitcode: ${_BITCODE_DEFAULT_ARCHS}")
else()
message(WARNING "GPU_TARGETS not set and no local GPU detected. "
"Device bitcode will not be built. Set -DGPU_TARGETS=<arch> to enable.")
endif()
endif()
set(BITCODE_GPU_ARCHS "${_BITCODE_DEFAULT_ARCHS}" CACHE STRING "GPU architectures for device bitcode (semicolon-separated)")
# BITCODE_GPU_ARCHS_FULL: full arch strings with feature suffixes (e.g.
# gfx950:sramecc+:xnack-), used by CMakeDeviceBitcodeTester to pass the correct
# -target-feature flags to clang. These are embedded in the HSACO amdhsa.target
# metadata string, which HIP validates when loading the module — a mismatch causes error 209.
#
# GPU_TARGETS_FULL is set by the main CMakeLists.txt from the user-supplied
# GPU_TARGETS value before rocm_check_target_ids strips feature suffixes.
# When available, use it as the source of truth for per-arch feature strings.
# Fall back to bare arch names when building with auto-detected GPUs (where
# no suffix information is available without querying the hardware directly).
if(GPU_TARGETS_FULL)
string(REPLACE "," ";" _GPU_TARGETS_FULL_LIST "${GPU_TARGETS_FULL}")
set(_BITCODE_FULL_LIST ${_GPU_TARGETS_FULL_LIST})
else()
set(_BITCODE_FULL_LIST ${_BITCODE_DEFAULT_ARCHS})
endif()
set(BITCODE_GPU_ARCHS_FULL "${_BITCODE_FULL_LIST}" CACHE STRING
"Full GPU arch strings with feature suffixes for device bitcode (e.g. gfx950:sramecc+:xnack-)")
# -fvisibility=default ensures extern "C" device API symbols remain
# externally visible after llvm-link and clang backend compilation.
set(BITCODE_COMPILE_FLAGS_BASE
-Wall
-Wextra
-x hip
--cuda-device-only
-std=c++17
-emit-llvm
-fvisibility=default
-O3
-Xclang -mcode-object-version=none
-I${CMAKE_CURRENT_SOURCE_DIR}/include/rocshmem
-I${CMAKE_CURRENT_SOURCE_DIR}/include
-I${CMAKE_CURRENT_SOURCE_DIR}/src
-I${CMAKE_BINARY_DIR}/include
-I${CMAKE_BINARY_DIR}/include/rocshmem
)
if(${ROCM_MAJOR_VERSION} LESS 7)
# ROCm 6.x requires us to explicitly enable warp sync builtins
list(APPEND BITCODE_COMPILE_FLAGS_BASE -DHIP_ENABLE_WARP_SYNC_BUILTINS=1)
endif()
# Add MPI include directories — rocshmem_config.h defines HAVE_EXTERNAL_MPI
# when MPI is found, causing rocshmem_mpi.hpp to #include <mpi.h> transitively.
if(MPI_CXX_FOUND)
foreach(mpi_include_dir ${MPI_CXX_INCLUDE_DIRS})
list(APPEND BITCODE_COMPILE_FLAGS_BASE -I${mpi_include_dir})
endforeach()
endif()
# Core device sources (backend_bc.cpp is host-only; backend_bc_device.cpp provides
# the device-side create_ctx/destroy_ctx dispatchers)
set(BITCODE_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/rocshmem_gpu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/rocshmem_tile_gpu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ipc_policy.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/team.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/sync/abql_block_mutex.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/util.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/context_device.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/backend_bc_device.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/device/rocshmem_wrapper.cc
)
# Backend-specific device sources. The bitcode MUST match the host library's
# backend selection because:
# 1. DISPATCH macros in backend_type.hpp produce different code (switch vs
# direct static_cast) depending on which USE_* defines are active.
# 2. Context struct layouts differ per backend — static_cast reinterprets the
# same pointer as different derived types, so ABI must match.
# A "universal" bitcode with all backends forced on would crash when paired
# with a host library compiled for a single backend (layout/ABI mismatch).
# TODO: refactor DISPATCH to remove this hard limitation
if(USE_RO)
list(APPEND BITCODE_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/reverse_offload/backend_ro.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/reverse_offload/context_ro_device.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/reverse_offload/queue.cpp
)
endif()
if(USE_IPC)
list(APPEND BITCODE_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/ipc/backend_ipc.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ipc/context_ipc_device.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ipc/context_ipc_device_coll.cpp
)
endif()
# GDA queue_pair implementations are guarded by GDA_MLX5/GDA_IONIC/GDA_BNXT in
# queue_pair.hpp. Only compile the backend(s) enabled for this build so that
# declarations and definitions match.
if(USE_GDA)
list(APPEND BITCODE_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/gda/context_gda_device.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/gda/context_gda_device_coll.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/gda/backend_gda.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/gda/queue_pair.cpp
)
if(GDA_MLX5)
list(APPEND BITCODE_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/gda/mlx5/queue_pair_mlx5.cpp
)
endif()
if(GDA_IONIC)
list(APPEND BITCODE_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/gda/ionic/queue_pair_ionic.cpp
)
endif()
if(GDA_BNXT)
list(APPEND BITCODE_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/gda/bnxt/queue_pair_bnxt.cpp
)
endif()
endif()
# Build bitcode for each GPU architecture
#
# __device__ API functions (rocshmem_quiet, rocshmem_barrier_wg, etc.) are DCE'd
# by LLVM's -O3 passes when compiled per-TU: no amdgpu_kernel in the same TU
# calls them, so the optimizer treats them as dead. Fix: compile each source
# with -Xclang -disable-llvm-passes (frontend runs at -O3, LLVM DCE is skipped,
# all __device__ bodies are retained), then run opt -O3 over the merged BC where
# all callers exist. This mirrors the approach in CMakeDeviceBitcodeTester.cmake.
set(ALL_BITCODE_OUTPUTS)
foreach(gpu_arch ${BITCODE_GPU_ARCHS})
# Per-source flags: -Xclang -disable-llvm-passes suppresses DCE.
set(_COMPILE_FLAGS ${BITCODE_COMPILE_FLAGS_BASE} --offload-arch=${gpu_arch}
-Xclang -disable-llvm-passes)
set(BITCODE_OBJECTS_${gpu_arch})
foreach(src_file ${BITCODE_SOURCES})
get_filename_component(src_name ${src_file} NAME_WE)
set(bc_file ${CMAKE_CURRENT_BINARY_DIR}/bitcode/${gpu_arch}/${src_name}.bc)
list(APPEND BITCODE_OBJECTS_${gpu_arch} ${bc_file})
add_custom_command(
OUTPUT ${bc_file}
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/bitcode/${gpu_arch}
COMMAND ${LLVM_CLANG} ${_COMPILE_FLAGS} -c ${src_file} -o ${bc_file}
DEPENDS ${src_file}
COMMENT "Compiling ${src_name} to bitcode for ${gpu_arch}"
VERBATIM
)
endforeach()
set(_UNOPT_BC ${CMAKE_CURRENT_BINARY_DIR}/bitcode/${gpu_arch}/librocshmem_device_${gpu_arch}_unopt.bc)
set(BITCODE_OUTPUT_${gpu_arch} ${CMAKE_CURRENT_BINARY_DIR}/librocshmem_device_${gpu_arch}.bc)
list(APPEND ALL_BITCODE_OUTPUTS ${BITCODE_OUTPUT_${gpu_arch}})
add_custom_command(
OUTPUT ${_UNOPT_BC}
COMMAND ${LLVM_LINK} ${BITCODE_OBJECTS_${gpu_arch}} -o ${_UNOPT_BC}
DEPENDS ${BITCODE_OBJECTS_${gpu_arch}}
COMMENT "Linking device bitcode for ${gpu_arch}"
VERBATIM
)
add_custom_command(
OUTPUT ${BITCODE_OUTPUT_${gpu_arch}}
COMMAND ${LLVM_OPT} -O3 -mtriple=amdgcn-amd-amdhsa -mcpu=${gpu_arch}
${_UNOPT_BC} -o ${BITCODE_OUTPUT_${gpu_arch}}
DEPENDS ${_UNOPT_BC}
COMMENT "Optimizing device bitcode for ${gpu_arch}"
VERBATIM
)
install(
FILES ${BITCODE_OUTPUT_${gpu_arch}}
DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT runtime
)
message(STATUS "Device bitcode for ${gpu_arch}: ${BITCODE_OUTPUT_${gpu_arch}}")
endforeach()
add_custom_target(rocshmem_device_bitcode ALL
DEPENDS ${ALL_BITCODE_OUTPUTS}
)
message(STATUS "Device bitcode will be built for architectures: ${BITCODE_GPU_ARCHS}")