[TargetVersion] Only enable on RISC-V and AArch64 (#115991)
[llvm-project.git] / libclc / CMakeLists.txt
blob2c2c7f16e29442f9bdc5c27e0fb56d3a1978e704
1 cmake_minimum_required(VERSION 3.20.0)
3 if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
4   project(libclc VERSION 0.2.0 LANGUAGES CXX C)
5 endif()
6 set(LLVM_SUBPROJECT_TITLE "libclc")
8 set(CMAKE_CXX_STANDARD 17)
10 # Add path for custom modules
11 list( INSERT CMAKE_MODULE_PATH 0 "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" )
13 set( LIBCLC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} )
14 set( LIBCLC_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR} )
15 set( LIBCLC_OBJFILE_DIR ${LIBCLC_BINARY_DIR}/obj.libclc.dir )
17 include( AddLibclc )
19 include( GNUInstallDirs )
20 set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
21   amdgcn-amdhsa/lib/SOURCES;
22   amdgcn/lib/SOURCES;
23   amdgcn-mesa3d/lib/SOURCES;
24   amdgpu/lib/SOURCES;
25   clspv/lib/SOURCES;
26   clspv64/lib/SOURCES;
27   generic/lib/SOURCES;
28   ptx/lib/SOURCES;
29   ptx-nvidiacl/lib/SOURCES;
30   r600/lib/SOURCES;
31   spirv/lib/SOURCES;
32   spirv64/lib/SOURCES;
33   # CLC internal libraries
34   clc/lib/generic/SOURCES;
35   clc/lib/clspv/SOURCES;
36   clc/lib/clspv64/SOURCES;
37   clc/lib/spirv/SOURCES;
38   clc/lib/spirv64/SOURCES;
41 set( LIBCLC_MIN_LLVM 3.9.0 )
43 set( LIBCLC_TARGETS_TO_BUILD "all"
44     CACHE STRING "Semicolon-separated list of libclc targets to build, or 'all'." )
46 option( ENABLE_RUNTIME_SUBNORMAL "Enable runtime linking of subnormal support." OFF )
48 if( LIBCLC_STANDALONE_BUILD OR CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
49   # Out-of-tree configuration
50   set( LIBCLC_STANDALONE_BUILD TRUE )
52   find_package(LLVM REQUIRED HINTS "${LLVM_CMAKE_DIR}")
53   include(AddLLVM)
55   message( STATUS "libclc LLVM version: ${LLVM_PACKAGE_VERSION}" )
57   if( LLVM_PACKAGE_VERSION VERSION_LESS LIBCLC_MIN_LLVM )
58     message( FATAL_ERROR "libclc needs at least LLVM ${LIBCLC_MIN_LLVM}" )
59   endif()
61   # Import required tools
62   if( NOT EXISTS ${LIBCLC_CUSTOM_LLVM_TOOLS_BINARY_DIR} )
63     foreach( tool IN ITEMS clang llvm-as llvm-link opt )
64       find_program( LLVM_TOOL_${tool} ${tool} PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH )
65       set( ${tool}_exe ${LLVM_TOOL_${tool}} )
66       set( ${tool}_target )
67     endforeach()
68   endif()
69 else()
70   # In-tree configuration
71   set( LIBCLC_STANDALONE_BUILD FALSE )
73   set( LLVM_PACKAGE_VERSION ${LLVM_VERSION} )
75   # Note that we check this later (for both build types) but we can provide a
76   # more useful error message when built in-tree. We assume that LLVM tools are
77   # always available so don't warn here.
78   if( NOT clang IN_LIST LLVM_ENABLE_PROJECTS )
79     message(FATAL_ERROR "Clang is not enabled, but is required to build libclc in-tree")
80   endif()
82   if( NOT EXISTS ${LIBCLC_CUSTOM_LLVM_TOOLS_BINARY_DIR} )
83     get_host_tool_path( clang CLANG clang_exe clang_target )
84     get_host_tool_path( llvm-as LLVM_AS llvm-as_exe llvm-as_target )
85     get_host_tool_path( llvm-link LLVM_LINK llvm-link_exe llvm-link_target )
86     get_host_tool_path( opt OPT opt_exe opt_target )
87   endif()
88 endif()
90 if( EXISTS ${LIBCLC_CUSTOM_LLVM_TOOLS_BINARY_DIR} )
91   message( WARNING "Using custom LLVM tools to build libclc: "
92     "${LIBCLC_CUSTOM_LLVM_TOOLS_BINARY_DIR}, "
93     " ensure the tools are up to date." )
94   # Note - use a differently named variable than LLVM_TOOL_${tool} as above, as
95   # the variable name is used to cache the result of find_program. If we used
96   # the same name, a user wouldn't be able to switch a build between default
97   # and custom tools.
98   foreach( tool IN ITEMS clang llvm-as llvm-link opt )
99     find_program( LLVM_CUSTOM_TOOL_${tool} ${tool}
100       PATHS ${LIBCLC_CUSTOM_LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH )
101     set( ${tool}_exe ${LLVM_CUSTOM_TOOL_${tool}} )
102     set( ${tool}_target )
103   endforeach()
104 endif()
106 foreach( tool IN ITEMS clang opt llvm-as llvm-link )
107   if( NOT EXISTS "${${tool}_exe}" AND "${tool}_target" STREQUAL "" )
108     message( FATAL_ERROR "libclc toolchain incomplete - missing tool ${tool}!" )
109   endif()
110 endforeach()
112 # llvm-spirv is an optional dependency, used to build spirv-* targets.
113 # It may be provided in-tree or externally.
114 if( TARGET llvm-spirv )
115   get_host_tool_path( llvm-spirv LLVM_SPIRV llvm-spirv_exe llvm-spirv_target )
116 else()
117   find_program( LLVM_SPIRV llvm-spirv PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH )
118   set( llvm-spirv_exe "${LLVM_SPIRV}" )
119   set( llvm-spirv_target )
120 endif()
122 # List of all targets. Note that some are added dynamically below.
123 set( LIBCLC_TARGETS_ALL
124   amdgcn--
125   amdgcn--amdhsa
126   clspv--
127   clspv64--
128   r600--
129   nvptx--
130   nvptx64--
131   nvptx--nvidiacl
132   nvptx64--nvidiacl
135 # mesa3d environment is only available since LLVM 4.0
136 if( LLVM_PACKAGE_VERSION VERSION_GREATER_EQUAL 4.0.0 )
137   list( APPEND LIBCLC_TARGETS_ALL amdgcn-mesa-mesa3d )
138 endif()
140 # spirv-mesa3d and spirv64-mesa3d targets can only be built with the (optional)
141 # llvm-spirv external tool.
142 if( llvm-spirv_exe )
143   list( APPEND LIBCLC_TARGETS_ALL  spirv-mesa3d- spirv64-mesa3d- )
144 endif()
146 # Verify that the user hasn't requested mesa3d targets without an available
147 # llvm-spirv tool.
148 if( "spirv-mesa3d-" IN_LIST LIBCLC_TARGETS_TO_BUILD OR "spirv64-mesa3d-" IN_LIST LIBCLC_TARGETS_TO_BUILD )
149   if( NOT llvm-spirv_exe )
150     message( FATAL_ERROR "SPIR-V targets requested, but spirv-tools is not installed" )
151   endif()
152 endif()
154 if( LIBCLC_TARGETS_TO_BUILD STREQUAL "all" )
155   set( LIBCLC_TARGETS_TO_BUILD ${LIBCLC_TARGETS_ALL} )
156 else()
157   foreach(TARGET_TO_BUILD ${LIBCLC_TARGETS_TO_BUILD})
158     if (NOT ${TARGET_TO_BUILD} IN_LIST LIBCLC_TARGETS_ALL)
159       message ( FATAL_ERROR "Unknown target in LIBCLC_TARGETS_TO_BUILD: \"${TARGET_TO_BUILD}\"\n"
160                             "Valid targets are: ${LIBCLC_TARGETS_ALL}\n")
161     endif()
162   endforeach()
163 endif()
165 list( SORT LIBCLC_TARGETS_TO_BUILD )
167 # Construct LLVM version define
168 set( LLVM_VERSION_DEFINE "-DHAVE_LLVM=0x${LLVM_VERSION_MAJOR}0${LLVM_VERSION_MINOR}" )
170 # This needs to be set before any target that needs it
171 # We need to use LLVM_INCLUDE_DIRS here, because if we are linking to an
172 # llvm build directory, this includes $src/llvm/include which is where all the
173 # headers are not $build/include/ which is what LLVM_INCLUDE_DIR is set to.
174 include_directories( ${LLVM_INCLUDE_DIRS} )
176 # Setup prepare_builtins tools
177 set(LLVM_LINK_COMPONENTS
178   BitReader
179   BitWriter
180   Core
181   IRReader
182   Support
184 if( LIBCLC_STANDALONE_BUILD )
185   add_llvm_executable( prepare_builtins utils/prepare-builtins.cpp )
186   set( prepare_builtins_exe prepare_builtins )
187   set( prepare_builtins_target prepare_builtins )
188 else()
189   add_llvm_utility( prepare_builtins utils/prepare-builtins.cpp )
190   setup_host_tool( prepare_builtins PREPARE_BUILTINS prepare_builtins_exe prepare_builtins_target )
191 endif()
192 target_compile_definitions( prepare_builtins PRIVATE ${LLVM_VERSION_DEFINE} )
193 # These were not properly reported in early LLVM and we don't need them
194 target_compile_options( prepare_builtins PRIVATE -fno-rtti -fno-exceptions )
196 # Setup arch devices
197 set( r600--_devices cedar cypress barts cayman )
198 set( amdgcn--_devices tahiti )
199 set( amdgcn-mesa-mesa3d_devices ${amdgcn--_devices} )
200 set( amdgcn--amdhsa_devices none )
201 set( clspv--_devices none )
202 set( clspv64--_devices none )
203 set( nvptx--_devices none )
204 set( nvptx64--_devices none )
205 set( nvptx--nvidiacl_devices none )
206 set( nvptx64--nvidiacl_devices none )
207 set( spirv-mesa3d-_devices none )
208 set( spirv64-mesa3d-_devices none )
210 # Setup aliases
211 set( cedar_aliases palm sumo sumo2 redwood juniper )
212 set( cypress_aliases hemlock )
213 set( barts_aliases turks caicos )
214 set( cayman_aliases aruba )
215 set( tahiti_aliases pitcairn verde oland hainan bonaire kabini kaveri hawaii
216   mullins tonga tongapro iceland carrizo fiji stoney polaris10 polaris11
217   gfx602 gfx705 gfx805
218   gfx900 gfx902 gfx904 gfx906 gfx908 gfx909 gfx90a gfx90c gfx940 gfx941 gfx942
219   gfx1010 gfx1011 gfx1012 gfx1013
220   gfx1030 gfx1031 gfx1032 gfx1033 gfx1034 gfx1035 gfx1036
221   gfx1100 gfx1101 gfx1102 gfx1103
222   gfx1150 gfx1151 gfx1152 gfx1153
223   gfx1200 gfx1201
226 # pkg-config file
227 configure_file( libclc.pc.in libclc.pc @ONLY )
228 install( FILES ${CMAKE_CURRENT_BINARY_DIR}/libclc.pc DESTINATION "${CMAKE_INSTALL_DATADIR}/pkgconfig" )
229 install( DIRECTORY generic/include/clc DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" )
231 if( ENABLE_RUNTIME_SUBNORMAL )
232   foreach( file IN ITEMS subnormal_use_default subnormal_disable )
233     link_bc(
234        TARGET ${file}
235        INPUTS ${CMAKE_CURRENT_SOURCE_DIR}/generic/lib/${file}.ll
236     )
237     install(
238       FILES $<TARGET_PROPERTY:${file},TARGET_FILE>
239       DESTINATION "${CMAKE_INSTALL_DATADIR}/clc"
240     )
241   endforeach()
242 endif()
244 find_package( Python3 REQUIRED COMPONENTS Interpreter )
245 file( TO_CMAKE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/generic/lib/gen_convert.py script_loc )
246 add_custom_command(
247   OUTPUT convert.cl
248   COMMAND ${Python3_EXECUTABLE} ${script_loc} > convert.cl
249   DEPENDS ${script_loc} )
250 add_custom_target( "generate_convert.cl" DEPENDS convert.cl )
251 set_target_properties( "generate_convert.cl" PROPERTIES FOLDER "libclc/Sourcegenning" )
253 add_custom_command(
254   OUTPUT clspv-convert.cl
255   COMMAND ${Python3_EXECUTABLE} ${script_loc} --clspv > clspv-convert.cl
256   DEPENDS ${script_loc} )
257 add_custom_target( "clspv-generate_convert.cl" DEPENDS clspv-convert.cl )
258 set_target_properties( "clspv-generate_convert.cl" PROPERTIES FOLDER "libclc/Sourcegenning" )
260 enable_testing()
262 foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
263   message( STATUS "libclc target '${t}' is enabled" )
264   string( REPLACE "-" ";" TRIPLE  ${t} )
265   list( GET TRIPLE 0 ARCH )
266   list( GET TRIPLE 1 VENDOR )
267   list( GET TRIPLE 2 OS )
269   set( dirs )
271   if ( NOT ${ARCH} STREQUAL spirv AND NOT ${ARCH} STREQUAL spirv64 AND
272        NOT ${ARCH} STREQUAL clspv AND NOT ${ARCH} STREQUAL clspv64)
273     LIST( APPEND dirs generic )
274   endif()
276   if( ${ARCH} STREQUAL r600 OR ${ARCH} STREQUAL amdgcn )
277     list( APPEND dirs amdgpu )
278   endif()
280   # nvptx is special
281   if( ${ARCH} STREQUAL nvptx OR ${ARCH} STREQUAL nvptx64 )
282     set( DARCH ptx )
283   else()
284     set( DARCH ${ARCH} )
285   endif()
287   set( clc_lib_files )
288   libclc_configure_lib_source(
289     clc_lib_files
290     CLC_INTERNAL
291     LIB_ROOT_DIR clc
292     DIRS ${dirs} ${DARCH} ${DARCH}-${OS} ${DARCH}-${VENDOR}-${OS}
293   )
295   set( opencl_lib_files )
296   set( opencl_gen_files )
298   if( NOT ARCH STREQUAL spirv AND NOT ARCH STREQUAL spirv64 )
299     if( ARCH STREQUAL clspv OR ARCH STREQUAL clspv64 )
300       list( APPEND opencl_gen_files clspv-convert.cl )
301     elseif ( NOT ENABLE_RUNTIME_SUBNORMAL )
302       list( APPEND opencl_gen_files convert.cl )
303       list( APPEND opencl_lib_files generic/lib/subnormal_use_default.ll )
304     endif()
305   endif()
307   libclc_configure_lib_source(
308     opencl_lib_files
309     DIRS ${dirs} ${DARCH} ${DARCH}-${OS} ${DARCH}-${VENDOR}-${OS}
310   )
312   foreach( d ${${t}_devices} )
313     get_libclc_device_info(
314       TRIPLE ${t}
315       DEVICE ${d}
316       CPU cpu
317       ARCH_SUFFIX arch_suffix
318       CLANG_TRIPLE clang_triple
319     )
321     message( STATUS "  device: ${d} ( ${${d}_aliases} )" )
323     if ( ARCH STREQUAL spirv OR ARCH STREQUAL spirv64 )
324       set( build_flags -O0 -finline-hint-functions -DCLC_SPIRV )
325       set( opt_flags )
326       set( spvflags --spirv-max-version=1.1 )
327       set( MACRO_ARCH SPIRV32 )
328       if( ARCH STREQUAL spirv64 )
329         set( MACRO_ARCH SPIRV64 )
330       endif()
331     elseif( ARCH STREQUAL clspv OR ARCH STREQUAL clspv64 )
332       set( build_flags "-Wno-unknown-assumption" -DCLC_CLSPV )
333       set( opt_flags -O3 )
334       set( MACRO_ARCH CLSPV32 )
335       if( ARCH STREQUAL clspv64 )
336         set( MACRO_ARCH CLSPV64 )
337       endif()
338     else()
339       set( build_flags )
340       set( opt_flags -O3 )
341       set( MACRO_ARCH ${ARCH} )
342     endif()
344     set( LIBCLC_ARCH_OBJFILE_DIR "${LIBCLC_OBJFILE_DIR}/${arch_suffix}" )
345     file( MAKE_DIRECTORY ${LIBCLC_ARCH_OBJFILE_DIR} )
347     string( TOUPPER "CLC_${MACRO_ARCH}" CLC_TARGET_DEFINE )
349     list( APPEND build_flags
350       -D__CLC_INTERNAL
351       -D${CLC_TARGET_DEFINE}
352       # All libclc builtin libraries see CLC headers
353       -I${CMAKE_CURRENT_SOURCE_DIR}/clc/include
354       # FIXME: Fix libclc to not require disabling this noisy warning
355       -Wno-bitwise-conditional-parentheses
356     )
358     if( NOT "${cpu}" STREQUAL "" )
359       list( APPEND build_flags -mcpu=${cpu} )
360     endif()
362     add_libclc_builtin_set(
363       CLC_INTERNAL
364       ARCH ${ARCH}
365       ARCH_SUFFIX clc-${arch_suffix}
366       TRIPLE ${clang_triple}
367       COMPILE_FLAGS ${build_flags}
368       OPT_FLAGS ${opt_flags}
369       LIB_FILES ${clc_lib_files}
370     )
372     list( APPEND build_flags
373       -I${CMAKE_CURRENT_SOURCE_DIR}/generic/include
374     )
376     add_libclc_builtin_set(
377       ARCH ${ARCH}
378       ARCH_SUFFIX ${arch_suffix}
379       TRIPLE ${clang_triple}
380       COMPILE_FLAGS ${build_flags}
381       OPT_FLAGS ${opt_flags}
382       LIB_FILES ${opencl_lib_files}
383       GEN_FILES ${opencl_gen_files}
384       ALIASES ${${d}_aliases}
385       # Link in the CLC builtins and internalize their symbols
386       INTERNAL_LINK_DEPENDENCIES $<TARGET_PROPERTY:builtins.link.clc-${arch_suffix},TARGET_FILE>
387     )
388   endforeach( d )
389 endforeach( t )