Jonas Hahnfeld | 37bbe1a | 2018-05-16 17:20:21 +0000 | [diff] [blame] | 1 | # |
| 2 | #//===----------------------------------------------------------------------===// |
| 3 | #// |
| 4 | #// The LLVM Compiler Infrastructure |
| 5 | #// |
| 6 | #// This file is dual licensed under the MIT and the University of Illinois Open |
| 7 | #// Source Licenses. See LICENSE.txt for details. |
| 8 | #// |
| 9 | #//===----------------------------------------------------------------------===// |
| 10 | # |
| 11 | |
| 12 | # We use the compiler and linker provided by the user, attempt to use the one |
| 13 | # used to build libomptarget or just fail. |
| 14 | set(LIBOMPTARGET_NVPTX_BCLIB_SUPPORTED FALSE) |
| 15 | |
| 16 | if (NOT LIBOMPTARGET_NVPTX_CUDA_COMPILER STREQUAL "") |
| 17 | set(LIBOMPTARGET_NVPTX_SELECTED_CUDA_COMPILER ${LIBOMPTARGET_NVPTX_CUDA_COMPILER}) |
| 18 | elseif(${CMAKE_C_COMPILER_ID} STREQUAL "Clang") |
| 19 | set(LIBOMPTARGET_NVPTX_SELECTED_CUDA_COMPILER ${CMAKE_C_COMPILER}) |
| 20 | else() |
| 21 | return() |
| 22 | endif() |
| 23 | |
| 24 | # Get compiler directory to try to locate a suitable linker. |
| 25 | get_filename_component(compiler_dir ${LIBOMPTARGET_NVPTX_SELECTED_CUDA_COMPILER} DIRECTORY) |
| 26 | set(llvm_link "${compiler_dir}/llvm-link") |
| 27 | |
| 28 | if (NOT LIBOMPTARGET_NVPTX_BC_LINKER STREQUAL "") |
| 29 | set(LIBOMPTARGET_NVPTX_SELECTED_BC_LINKER ${LIBOMPTARGET_NVPTX_BC_LINKER}) |
| 30 | elseif (EXISTS "${llvm_link}") |
| 31 | # Use llvm-link from the compiler directory. |
| 32 | set(LIBOMPTARGET_NVPTX_SELECTED_BC_LINKER "${llvm_link}") |
| 33 | else() |
| 34 | return() |
| 35 | endif() |
| 36 | |
| 37 | function(try_compile_bitcode output source) |
| 38 | set(srcfile ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/src.cu) |
| 39 | file(WRITE ${srcfile} "${source}\n") |
| 40 | set(bcfile ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/out.bc) |
| 41 | |
| 42 | # The remaining arguments are the flags to be tested. |
| 43 | # FIXME: Don't hardcode GPU version. This is currently required because |
| 44 | # Clang refuses to compile its default of sm_20 with CUDA 9. |
| 45 | execute_process( |
| 46 | COMMAND ${LIBOMPTARGET_NVPTX_SELECTED_CUDA_COMPILER} ${ARGN} |
| 47 | --cuda-gpu-arch=sm_35 -c ${srcfile} -o ${bcfile} |
| 48 | RESULT_VARIABLE result |
| 49 | OUTPUT_QUIET ERROR_QUIET) |
| 50 | if (result EQUAL 0) |
| 51 | set(${output} TRUE PARENT_SCOPE) |
| 52 | else() |
| 53 | set(${output} FALSE PARENT_SCOPE) |
| 54 | endif() |
| 55 | endfunction() |
| 56 | |
| 57 | # Save for which compiler we are going to do the following checks so that we |
| 58 | # can discard cached values if the user specifies a different value. |
| 59 | set(discard_cached FALSE) |
| 60 | if (DEFINED LIBOMPTARGET_NVPTX_CHECKED_CUDA_COMPILER AND |
| 61 | NOT("${LIBOMPTARGET_NVPTX_CHECKED_CUDA_COMPILER}" STREQUAL "${LIBOMPTARGET_NVPTX_SELECTED_CUDA_COMPILER}")) |
| 62 | set(discard_cached TRUE) |
| 63 | endif() |
| 64 | set(LIBOMPTARGET_NVPTX_CHECKED_CUDA_COMPILER "${LIBOMPTARGET_NVPTX_SELECTED_CUDA_COMPILER}" CACHE INTERNAL "" FORCE) |
| 65 | |
| 66 | function(check_bitcode_compilation output source) |
| 67 | if (${discard_cached} OR NOT DEFINED ${output}) |
| 68 | message(STATUS "Performing Test ${output}") |
| 69 | # Forward additional arguments which contain the flags. |
| 70 | try_compile_bitcode(result "${source}" ${ARGN}) |
| 71 | set(${output} ${result} CACHE INTERNAL "" FORCE) |
| 72 | if(${result}) |
| 73 | message(STATUS "Performing Test ${output} - Success") |
| 74 | else() |
| 75 | message(STATUS "Performing Test ${output} - Failed") |
| 76 | endif() |
| 77 | endif() |
| 78 | endfunction() |
| 79 | |
| 80 | # These flags are required to emit LLVM Bitcode. We check them together because |
| 81 | # if any of them are not supported, there is no point in finding out which are. |
Jonas Hahnfeld | 9228f97 | 2018-05-16 17:20:27 +0000 | [diff] [blame] | 82 | set(compiler_flags_required -emit-llvm -O1 --cuda-device-only --cuda-path=${CUDA_TOOLKIT_ROOT_DIR}) |
Jonas Hahnfeld | 37bbe1a | 2018-05-16 17:20:21 +0000 | [diff] [blame] | 83 | set(compiler_flags_required_src "extern \"C\" __device__ int thread() { return threadIdx.x; }") |
| 84 | check_bitcode_compilation(LIBOMPTARGET_NVPTX_CUDA_COMPILER_SUPPORTS_FLAGS_REQUIRED "${compiler_flags_required_src}" ${compiler_flags_required}) |
| 85 | |
| 86 | # It makes no sense to continue given that the compiler doesn't support |
| 87 | # emitting basic LLVM Bitcode |
| 88 | if (NOT LIBOMPTARGET_NVPTX_CUDA_COMPILER_SUPPORTS_FLAGS_REQUIRED) |
| 89 | return() |
| 90 | endif() |
| 91 | |
| 92 | set(LIBOMPTARGET_NVPTX_SELECTED_CUDA_COMPILER_FLAGS ${compiler_flags_required}) |
| 93 | |
| 94 | # Declaring external shared device variables might need an additional flag |
| 95 | # since Clang 7.0 and was entirely unsupported since version 4.0. |
| 96 | set(extern_device_shared_src "extern __device__ __shared__ int test;") |
| 97 | |
| 98 | check_bitcode_compilation(LIBOMPTARGET_NVPTX_CUDA_COMPILER_SUPPORTS_EXTERN_SHARED "${extern_device_shared_src}" ${LIBOMPTARGET_NVPTX_SELECTED_CUDA_COMPILER_FLAGS}) |
| 99 | if (NOT LIBOMPTARGET_NVPTX_CUDA_COMPILER_SUPPORTS_EXTERN_SHARED) |
| 100 | set(compiler_flag_fcuda_rdc -fcuda-rdc) |
| 101 | set(compiler_flag_fcuda_rdc_full ${LIBOMPTARGET_NVPTX_SELECTED_CUDA_COMPILER_FLAGS} ${compiler_flag_fcuda_rdc}) |
| 102 | check_bitcode_compilation(LIBOMPTARGET_NVPTX_CUDA_COMPILER_SUPPORTS_FCUDA_RDC "${extern_device_shared_src}" ${compiler_flag_fcuda_rdc_full}) |
| 103 | |
| 104 | if (NOT LIBOMPTARGET_NVPTX_CUDA_COMPILER_SUPPORTS_FCUDA_RDC) |
| 105 | return() |
| 106 | endif() |
| 107 | |
| 108 | set(LIBOMPTARGET_NVPTX_SELECTED_CUDA_COMPILER_FLAGS "${compiler_flag_fcuda_rdc_full}") |
| 109 | endif() |
| 110 | |
| 111 | # We can compile LLVM Bitcode from CUDA source code! |
| 112 | set(LIBOMPTARGET_NVPTX_BCLIB_SUPPORTED TRUE) |