blob: 5c6934011dbbfc02a2a8d699487472d201fce736 [file] [log] [blame]
Jonas Hahnfeld37bbe1a2018-05-16 17:20:21 +00001#
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.
14set(LIBOMPTARGET_NVPTX_BCLIB_SUPPORTED FALSE)
15
16if (NOT LIBOMPTARGET_NVPTX_CUDA_COMPILER STREQUAL "")
17 set(LIBOMPTARGET_NVPTX_SELECTED_CUDA_COMPILER ${LIBOMPTARGET_NVPTX_CUDA_COMPILER})
18elseif(${CMAKE_C_COMPILER_ID} STREQUAL "Clang")
19 set(LIBOMPTARGET_NVPTX_SELECTED_CUDA_COMPILER ${CMAKE_C_COMPILER})
20else()
21 return()
22endif()
23
24# Get compiler directory to try to locate a suitable linker.
25get_filename_component(compiler_dir ${LIBOMPTARGET_NVPTX_SELECTED_CUDA_COMPILER} DIRECTORY)
26set(llvm_link "${compiler_dir}/llvm-link")
27
28if (NOT LIBOMPTARGET_NVPTX_BC_LINKER STREQUAL "")
29 set(LIBOMPTARGET_NVPTX_SELECTED_BC_LINKER ${LIBOMPTARGET_NVPTX_BC_LINKER})
30elseif (EXISTS "${llvm_link}")
31 # Use llvm-link from the compiler directory.
32 set(LIBOMPTARGET_NVPTX_SELECTED_BC_LINKER "${llvm_link}")
33else()
34 return()
35endif()
36
37function(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()
55endfunction()
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.
59set(discard_cached FALSE)
60if (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)
63endif()
64set(LIBOMPTARGET_NVPTX_CHECKED_CUDA_COMPILER "${LIBOMPTARGET_NVPTX_SELECTED_CUDA_COMPILER}" CACHE INTERNAL "" FORCE)
65
66function(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()
78endfunction()
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 Hahnfeld9228f972018-05-16 17:20:27 +000082set(compiler_flags_required -emit-llvm -O1 --cuda-device-only --cuda-path=${CUDA_TOOLKIT_ROOT_DIR})
Jonas Hahnfeld37bbe1a2018-05-16 17:20:21 +000083set(compiler_flags_required_src "extern \"C\" __device__ int thread() { return threadIdx.x; }")
84check_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
88if (NOT LIBOMPTARGET_NVPTX_CUDA_COMPILER_SUPPORTS_FLAGS_REQUIRED)
89 return()
90endif()
91
92set(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.
96set(extern_device_shared_src "extern __device__ __shared__ int test;")
97
98check_bitcode_compilation(LIBOMPTARGET_NVPTX_CUDA_COMPILER_SUPPORTS_EXTERN_SHARED "${extern_device_shared_src}" ${LIBOMPTARGET_NVPTX_SELECTED_CUDA_COMPILER_FLAGS})
99if (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}")
109endif()
110
111# We can compile LLVM Bitcode from CUDA source code!
112set(LIBOMPTARGET_NVPTX_BCLIB_SUPPORTED TRUE)