# Ensure the compiler is a valid clang when building the GPU target. set(req_ver "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}") if(LLVM_VERSION_MAJOR AND NOT (CMAKE_CXX_COMPILER_ID MATCHES "[Cc]lang" AND ${CMAKE_CXX_COMPILER_VERSION} VERSION_EQUAL "${req_ver}")) message(WARNING "openmp for GPU requires an up-to-date clang. CMake compiler " "'${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}' " " is not 'Clang ${req_ver}'.") endif() option(OFFLOAD_ENABLE_EMISSARY_APIS "Enable build of GPU Emissary APIs" ON) if(OFFLOAD_ENABLE_EMISSARY_APIS) add_definitions(-DOFFLOAD_ENABLE_EMISSARY_APIS) set(emissary_sources src/EmissaryFortrt.cpp src/EmissaryPrint.cpp ) endif() set(src_files ${CMAKE_CURRENT_SOURCE_DIR}/src/Allocator.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Configuration.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Debug.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Kernel.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/LibC.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Mapping.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Misc.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Parallelism.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Reduction.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/State.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Synchronization.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Tasking.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/DeviceUtils.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Workshare.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/ExtraMapping.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Xteamr.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Memory.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Xteams.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/DeviceMemInit.cpp ${emissary_sources} ) # Only link AMD ockl/ocml device libraries when actually building for AMDGCN. # The previous condition checked LLVM_TARGETS_TO_BUILD which includes all backends # (e.g. X86;AMDGPU;NVPTX), causing ockl.bc/ocml.bc to be linked into NVPTX builds # and contaminating the NVPTX DeviceRTL bitcode with AMDGCN intrinsics. if("${LLVM_DEFAULT_TARGET_TRIPLE}" MATCHES "^amdgcn" OR "${CMAKE_CXX_COMPILER_TARGET}" MATCHES "^amdgcn") find_package(AMDDeviceLibs REQUIRED CONFIG HINTS ${CMAKE_BINARY_DIR}/../../tools/rocm-device-libs ${CMAKE_BINARY_DIR}/../rocm-device-libs-prefix/src/rocm-device-libs-build ${CMAKE_INSTALL_PREFIX} ) get_target_property(_ocml_bc ocml IMPORTED_LOCATION) get_target_property(_ockl_bc ockl IMPORTED_LOCATION) get_target_property(_asanrtl_bc asanrtl IMPORTED_LOCATION) if(NOT _ockl_bc) message(FATAL_ERROR "Could not find ockl.bc") endif() if(NOT _ocml_bc) message(FATAL_ERROR "Could not find ocml.bc") endif() if(NOT _asanrtl_bc) message(FATAL_ERROR "Could not find asanrtl.bc") endif() if(SANITIZER_AMDGPU) list(APPEND compile_flags "SHELL: -DSANITIZER_AMDGPU=1") # For ASan: Don't link asanrtl.bc and ockl.bc at compile time of libompdevice.a # They will be linked once in POST_BUILD step to avoid duplicates symbols # Note: Oclc control constants are provided using Platform.h # else() list(APPEND compile_flags "SHELL: -Xclang -mlink-builtin-bitcode -Xclang ${_ockl_bc}") endif() list(APPEND compile_flags "SHELL: -Xclang -mlink-builtin-bitcode -Xclang ${_ocml_bc}") endif() list(APPEND compile_options -flto) list(APPEND compile_options -fvisibility=hidden) list(APPEND compile_options -nogpulib) list(APPEND compile_options -nostdlibinc) list(APPEND compile_options -fno-rtti) list(APPEND compile_options -fno-exceptions) list(APPEND compile_options -fconvergent-functions) list(APPEND compile_options -Wno-unknown-cuda-version) list(APPEND compile_options -fno-sanitize=address) list(APPEND compile_options -O3) if(LLVM_DEFAULT_TARGET_TRIPLE) list(APPEND compile_options --target=${LLVM_DEFAULT_TARGET_TRIPLE}) endif() # We disable the slp vectorizer during the runtime optimization to avoid # vectorized accesses to the shared state. Generally, those are "good" but # the optimizer pipeline (esp. Attributor) does not fully support vectorized # instructions yet and we end up missing out on way more important constant # propagation. That said, we will run the vectorizer again after the runtime # has been linked into the user program. list(APPEND compile_flags "SHELL: -mllvm -vectorize-slp=false") if("${LLVM_DEFAULT_TARGET_TRIPLE}" MATCHES "^amdgcn" OR "${CMAKE_CXX_COMPILER_TARGET}" MATCHES "^amdgcn") set(target_name "amdgpu") list(APPEND compile_flags "SHELL:-Xclang -mcode-object-version=none") elseif("${LLVM_DEFAULT_TARGET_TRIPLE}" MATCHES "^nvptx" OR "${CMAKE_CXX_COMPILER_TARGET}" MATCHES "^nvptx") set(target_name "nvptx") list(APPEND compile_options --cuda-feature=+ptx63) elseif("${LLVM_DEFAULT_TARGET_TRIPLE}" MATCHES "^spirv" OR "${CMAKE_CXX_COMPILER_TARGET}" MATCHES "^spirv") set(target_name "spirv") endif() # Trick to combine these into a bitcode file via the linker's LTO pass. add_executable(libompdevice ${src_files}) set_target_properties(libompdevice PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} LINKER_LANGUAGE CXX BUILD_RPATH "" INSTALL_RPATH "" RUNTIME_OUTPUT_NAME libomptarget-${target_name}.bc) # If the user built with the GPU C library enabled we will use that instead. if(TARGET libc) target_compile_definitions(libompdevice PRIVATE OMPTARGET_HAS_LIBC) endif() target_compile_definitions(libompdevice PRIVATE SHARED_SCRATCHPAD_SIZE=512) target_include_directories(libompdevice PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/../../libc ${CMAKE_CURRENT_SOURCE_DIR}/../../offload/include) target_compile_options(libompdevice PRIVATE ${compile_options} ${compile_flags}) if(NOT "${LLVM_DEFAULT_TARGET_TRIPLE}" MATCHES "^spirv" AND NOT "${CMAKE_CXX_COMPILER_TARGET}" MATCHES "^spirv") target_link_options(libompdevice PRIVATE "-flto" "-r" "-nostdlib" "-Wl,--lto-emit-llvm") else() target_link_options(libompdevice PRIVATE "-nostdlib" "-emit-llvm") endif() if(LLVM_DEFAULT_TARGET_TRIPLE) target_link_options(libompdevice PRIVATE "--target=${LLVM_DEFAULT_TARGET_TRIPLE}") endif() # For SANITIZER_AMDGPU: Use llvm-link POST_BUILD to merge ASAN runtime and OCKL # into the device library bitcode to resolve all and __asan_* __ockl_* symbols if(SANITIZER_AMDGPU) find_program(LLVM_LINK_EXECUTABLE NAMES llvm-link HINTS ${LLVM_TOOLS_BINARY_DIR}) if(NOT LLVM_LINK_EXECUTABLE) message(FATAL_ERROR "llvm-link not found") endif() add_custom_command(TARGET libompdevice POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/libomptarget-${target_name}.bc ${CMAKE_CURRENT_BINARY_DIR}/libomptarget-${target_name}.bc.tmp COMMAND ${LLVM_LINK_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/libomptarget-${target_name}.bc.tmp ${_asanrtl_bc} ${_ockl_bc} --only-needed -o ${CMAKE_CURRENT_BINARY_DIR}/libomptarget-${target_name}.bc COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_CURRENT_BINARY_DIR}/libomptarget-${target_name}.bc.tmp COMMENT "Merging asanrtl.bc and ockl.bc into libomptarget-${target_name}.bc" ) endif() install(TARGETS libompdevice PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ DESTINATION ${OPENMP_INSTALL_LIBDIR} COMPONENT openmp) add_library(ompdevice.all_objs OBJECT IMPORTED) set_property(TARGET ompdevice.all_objs APPEND PROPERTY IMPORTED_OBJECTS ${CMAKE_CURRENT_BINARY_DIR}/libomptarget-${target_name}.bc) # Archive all the object files generated above into a static library add_library(ompdevice STATIC) add_dependencies(ompdevice libompdevice) set_target_properties(ompdevice PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${OPENMP_INSTALL_LIBDIR}" ARCHIVE_OUTPUT_NAME ompdevice LINKER_LANGUAGE CXX ) target_link_libraries(ompdevice PRIVATE ompdevice.all_objs) install(TARGETS ompdevice ARCHIVE DESTINATION "${OPENMP_INSTALL_LIBDIR}" COMPONENT openmp) openmp_register_meta_dep(ompdevice)