[clang-repl] [codegen] Reduce the state in TBAA. NFC for static compilation. (#98138)
[llvm-project.git] / libclc / CMakeLists.txt
blob02bb859ae8590b5d71475a1ffdd84a96b0a8abfa
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
35 set( LIBCLC_MIN_LLVM 3.9.0 )
37 set( LIBCLC_TARGETS_TO_BUILD "all"
38     CACHE STRING "Semicolon-separated list of libclc targets to build, or 'all'." )
40 option( ENABLE_RUNTIME_SUBNORMAL "Enable runtime linking of subnormal support." OFF )
42 if( LIBCLC_STANDALONE_BUILD OR CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
43   # Out-of-tree configuration
44   set( LIBCLC_STANDALONE_BUILD TRUE )
46   find_package(LLVM REQUIRED HINTS "${LLVM_CMAKE_DIR}")
47   include(AddLLVM)
49   message( STATUS "libclc LLVM version: ${LLVM_PACKAGE_VERSION}" )
51   if( LLVM_PACKAGE_VERSION VERSION_LESS LIBCLC_MIN_LLVM )
52     message( FATAL_ERROR "libclc needs at least LLVM ${LIBCLC_MIN_LLVM}" )
53   endif()
55   # Import required tools
56   if( NOT EXISTS ${LIBCLC_CUSTOM_LLVM_TOOLS_BINARY_DIR} )
57     foreach( tool IN ITEMS clang llvm-as llvm-link opt )
58       find_program( LLVM_TOOL_${tool} ${tool} PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH )
59       set( ${tool}_exe ${LLVM_TOOL_${tool}} )
60       set( ${tool}_target )
61     endforeach()
62   endif()
63 else()
64   # In-tree configuration
65   set( LIBCLC_STANDALONE_BUILD FALSE )
67   set( LLVM_PACKAGE_VERSION ${LLVM_VERSION} )
69   # Note that we check this later (for both build types) but we can provide a
70   # more useful error message when built in-tree. We assume that LLVM tools are
71   # always available so don't warn here.
72   if( NOT clang IN_LIST LLVM_ENABLE_PROJECTS )
73     message(FATAL_ERROR "Clang is not enabled, but is required to build libclc in-tree")
74   endif()
76   if( NOT EXISTS ${LIBCLC_CUSTOM_LLVM_TOOLS_BINARY_DIR} )
77     setup_host_tool( clang CLANG clang_exe clang_target )
78     setup_host_tool( llvm-as LLVM_AS llvm-as_exe llvm-as_target )
79     setup_host_tool( llvm-link LLVM_LINK llvm-link_exe llvm-link_target )
80     setup_host_tool( opt OPT opt_exe opt_target )
81   endif()
82 endif()
84 if( EXISTS ${LIBCLC_CUSTOM_LLVM_TOOLS_BINARY_DIR} )
85   message( WARNING "Using custom LLVM tools to build libclc: "
86     "${LIBCLC_CUSTOM_LLVM_TOOLS_BINARY_DIR}, "
87     " ensure the tools are up to date." )
88   # Note - use a differently named variable than LLVM_TOOL_${tool} as above, as
89   # the variable name is used to cache the result of find_program. If we used
90   # the same name, a user wouldn't be able to switch a build between default
91   # and custom tools.
92   foreach( tool IN ITEMS clang llvm-as llvm-link opt )
93     find_program( LLVM_CUSTOM_TOOL_${tool} ${tool}
94       PATHS ${LIBCLC_CUSTOM_LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH )
95     set( ${tool}_exe ${LLVM_CUSTOM_TOOL_${tool}} )
96     set( ${tool}_target )
97   endforeach()
98 endif()
100 foreach( tool IN ITEMS clang opt llvm-as llvm-link )
101   if( NOT EXISTS "${${tool}_exe}" AND NOT TARGET "${${tool}_target}" )
102     message( FATAL_ERROR "libclc toolchain incomplete - missing tool ${tool}!" )
103   endif()
104 endforeach()
106 # llvm-spirv is an optional dependency, used to build spirv-* targets.
107 find_program( LLVM_SPIRV llvm-spirv PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH )
109 if( LLVM_SPIRV )
110   add_executable( libclc::llvm-spirv IMPORTED GLOBAL )
111   set_target_properties( libclc::llvm-spirv PROPERTIES IMPORTED_LOCATION ${LLVM_SPIRV} )
112 endif()
114 # List of all targets. Note that some are added dynamically below.
115 set( LIBCLC_TARGETS_ALL
116   amdgcn--
117   amdgcn--amdhsa
118   clspv--
119   clspv64--
120   r600--
121   nvptx--
122   nvptx64--
123   nvptx--nvidiacl
124   nvptx64--nvidiacl
127 # mesa3d environment is only available since LLVM 4.0
128 if( LLVM_PACKAGE_VERSION VERSION_GREATER_EQUAL 4.0.0 )
129   list( APPEND LIBCLC_TARGETS_ALL amdgcn-mesa-mesa3d )
130 endif()
132 # spirv-mesa3d and spirv64-mesa3d targets can only be built with the (optional)
133 # llvm-spirv external tool.
134 if( TARGET libclc::llvm-spirv )
135   list( APPEND LIBCLC_TARGETS_ALL  spirv-mesa3d- spirv64-mesa3d- )
136 endif()
138 if( LIBCLC_TARGETS_TO_BUILD STREQUAL "all" )
139   set( LIBCLC_TARGETS_TO_BUILD ${LIBCLC_TARGETS_ALL} )
140 endif()
142 list( SORT LIBCLC_TARGETS_TO_BUILD )
144 # Verify that the user hasn't requested mesa3d targets without an available
145 # llvm-spirv tool.
146 if( "spirv-mesa3d-" IN_LIST LIBCLC_TARGETS_TO_BUILD OR "spirv64-mesa3d-" IN_LIST LIBCLC_TARGETS_TO_BUILD )
147   if( NOT TARGET libclc::llvm-spirv )
148     message( FATAL_ERROR "SPIR-V targets requested, but spirv-tools is not installed" )
149   endif()
150 endif()
152 # Construct LLVM version define
153 set( LLVM_VERSION_DEFINE "-DHAVE_LLVM=0x${LLVM_VERSION_MAJOR}0${LLVM_VERSION_MINOR}" )
155 # This needs to be set before any target that needs it
156 # We need to use LLVM_INCLUDE_DIRS here, because if we are linking to an
157 # llvm build directory, this includes $src/llvm/include which is where all the
158 # headers are not $build/include/ which is what LLVM_INCLUDE_DIR is set to.
159 include_directories( ${LLVM_INCLUDE_DIRS} )
161 # Setup prepare_builtins tools
162 set(LLVM_LINK_COMPONENTS
163   BitReader
164   BitWriter
165   Core
166   IRReader
167   Support
169 if( LIBCLC_STANDALONE_BUILD )
170   add_llvm_executable( prepare_builtins utils/prepare-builtins.cpp )
171   set( prepare_builtins_exe prepare_builtins )
172   set( prepare_builtins_target prepare_builtins )
173 else()
174   add_llvm_utility( prepare_builtins utils/prepare-builtins.cpp )
175   setup_host_tool( prepare_builtins PREPARE_BUILTINS prepare_builtins_exe prepare_builtins_target )
176 endif()
177 target_compile_definitions( prepare_builtins PRIVATE ${LLVM_VERSION_DEFINE} )
178 # These were not properly reported in early LLVM and we don't need them
179 target_compile_options( prepare_builtins PRIVATE -fno-rtti -fno-exceptions )
181 # Setup arch devices
182 set( r600--_devices cedar cypress barts cayman )
183 set( amdgcn--_devices tahiti )
184 set( amdgcn-mesa-mesa3d_devices ${amdgcn--_devices} )
185 set( amdgcn--amdhsa_devices none )
186 set( clspv--_devices none )
187 set( clspv64--_devices none )
188 set( nvptx--_devices none )
189 set( nvptx64--_devices none )
190 set( nvptx--nvidiacl_devices none )
191 set( nvptx64--nvidiacl_devices none )
192 set( spirv-mesa3d-_devices none )
193 set( spirv64-mesa3d-_devices none )
195 # Setup aliases
196 set( cedar_aliases palm sumo sumo2 redwood juniper )
197 set( cypress_aliases hemlock )
198 set( barts_aliases turks caicos )
199 set( cayman_aliases aruba )
200 set( tahiti_aliases pitcairn verde oland hainan bonaire kabini kaveri hawaii
201   mullins tonga tongapro iceland carrizo fiji stoney polaris10 polaris11
202   gfx602 gfx705 gfx805
203   gfx900 gfx902 gfx904 gfx906 gfx908 gfx909 gfx90a gfx90c gfx940 gfx941 gfx942
204   gfx1010 gfx1011 gfx1012 gfx1013
205   gfx1030 gfx1031 gfx1032 gfx1033 gfx1034 gfx1035 gfx1036
206   gfx1100 gfx1101 gfx1102 gfx1103
207   gfx1150 gfx1151 gfx1152
208   gfx1200 gfx1201
211 # pkg-config file
212 configure_file( libclc.pc.in libclc.pc @ONLY )
213 install( FILES ${CMAKE_CURRENT_BINARY_DIR}/libclc.pc DESTINATION "${CMAKE_INSTALL_DATADIR}/pkgconfig" )
214 install( DIRECTORY generic/include/clc DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" )
216 if( ENABLE_RUNTIME_SUBNORMAL )
217   foreach( file IN ITEMS subnormal_use_default subnormal_disable )
218     link_bc(
219        TARGET ${file}
220        INPUTS ${CMAKE_CURRENT_SOURCE_DIR}/generic/lib/${file}.ll
221     )
222     install( FILES $<TARGET_PROPERTY:${file},TARGET_FILE> ARCHIVE
223       DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" )
224   endforeach()
225 endif()
227 find_package( Python3 REQUIRED COMPONENTS Interpreter )
228 file( TO_CMAKE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/generic/lib/gen_convert.py script_loc )
229 add_custom_command(
230   OUTPUT convert.cl
231   COMMAND ${Python3_EXECUTABLE} ${script_loc} > convert.cl
232   DEPENDS ${script_loc} )
233 add_custom_target( "generate_convert.cl" DEPENDS convert.cl )
234 set_target_properties( "generate_convert.cl" PROPERTIES FOLDER "libclc/Sourcegenning" )
236 add_custom_command(
237   OUTPUT clspv-convert.cl
238   COMMAND ${Python3_EXECUTABLE} ${script_loc} --clspv > clspv-convert.cl
239   DEPENDS ${script_loc} )
240 add_custom_target( "clspv-generate_convert.cl" DEPENDS clspv-convert.cl )
241 set_target_properties( "clspv-generate_convert.cl" PROPERTIES FOLDER "libclc/Sourcegenning" )
243 enable_testing()
245 foreach( t ${LIBCLC_TARGETS_TO_BUILD} )
246   message( STATUS "libclc target '${t}' is enabled" )
247   string( REPLACE "-" ";" TRIPLE  ${t} )
248   list( GET TRIPLE 0 ARCH )
249   list( GET TRIPLE 1 VENDOR )
250   list( GET TRIPLE 2 OS )
252   set( dirs )
254   if ( NOT ${ARCH} STREQUAL spirv AND NOT ${ARCH} STREQUAL spirv64 AND
255        NOT ${ARCH} STREQUAL clspv AND NOT ${ARCH} STREQUAL clspv64)
256     LIST( APPEND dirs generic )
257   endif()
259   if( ${ARCH} STREQUAL r600 OR ${ARCH} STREQUAL amdgcn )
260     list( APPEND dirs amdgpu )
261   endif()
263   # nvptx is special
264   if( ${ARCH} STREQUAL nvptx OR ${ARCH} STREQUAL nvptx64 )
265     set( DARCH ptx )
266   else()
267     set( DARCH ${ARCH} )
268   endif()
270   # Enumerate SOURCES* files
271   set( source_list )
272   foreach( l ${dirs} ${DARCH} ${DARCH}-${OS} ${DARCH}-${VENDOR}-${OS} )
273     foreach( s "SOURCES" "SOURCES_${LLVM_MAJOR}.${LLVM_MINOR}" )
274       file( TO_CMAKE_PATH ${l}/lib/${s} file_loc )
275       file( TO_CMAKE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${file_loc} loc )
276       # Prepend the location to give higher priority to
277       # specialized implementation
278       if( EXISTS ${loc} )
279         set( source_list ${file_loc} ${source_list} )
280       endif()
281     endforeach()
282   endforeach()
284   # Add the generated convert.cl here to prevent adding the one listed in
285   # SOURCES
286   set( objects )   # A "set" of already-added input files
287   set( rel_files ) # Source directory input files, relative to the root dir
288   set( gen_files ) # Generated binary input files, relative to the binary dir
289   if( NOT ${ARCH} STREQUAL "spirv" AND NOT ${ARCH} STREQUAL "spirv64" )
290     if( NOT ENABLE_RUNTIME_SUBNORMAL AND NOT ${ARCH} STREQUAL "clspv" AND
291         NOT ${ARCH} STREQUAL "clspv64" )
292       list( APPEND gen_files convert.cl )
293       list( APPEND objects convert.cl )
294       list( APPEND rel_files generic/lib/subnormal_use_default.ll )
295     elseif(${ARCH} STREQUAL "clspv" OR ${ARCH} STREQUAL "clspv64")
296       list( APPEND gen_files clspv-convert.cl )
297       list( APPEND objects clspv-convert.cl )
298     endif()
299   endif()
301   foreach( l ${source_list} )
302     file( READ ${l} file_list )
303     string( REPLACE "\n" ";" file_list ${file_list} )
304     get_filename_component( dir ${l} DIRECTORY )
305     foreach( f ${file_list} )
306       # Only add each file once, so that targets can 'specialize' builtins
307       if( NOT ${f} IN_LIST objects )
308         list( APPEND objects ${f} )
309         list( APPEND rel_files ${dir}/${f} )
310       endif()
311     endforeach()
312   endforeach()
314   foreach( d ${${t}_devices} )
315     get_libclc_device_info(
316       TRIPLE ${t}
317       DEVICE ${d}
318       CPU cpu
319       ARCH_SUFFIX arch_suffix
320       CLANG_TRIPLE clang_triple
321     )
323     set( mcpu )
324     if( NOT "${cpu}" STREQUAL "" )
325       set( mcpu "-mcpu=${cpu}" )
326     endif()
328     message( STATUS "  device: ${d} ( ${${d}_aliases} )" )
330     if ( ARCH STREQUAL spirv OR ARCH STREQUAL spirv64 )
331       set( build_flags -O0 -finline-hint-functions )
332       set( opt_flags )
333       set( spvflags --spirv-max-version=1.1 )
334     elseif( ARCH STREQUAL clspv OR ARCH STREQUAL clspv64 )
335       set( build_flags "-Wno-unknown-assumption")
336       set( opt_flags -O3 )
337     else()
338       set( build_flags )
339       set( opt_flags -O3 )
340     endif()
342     set( LIBCLC_ARCH_OBJFILE_DIR "${LIBCLC_OBJFILE_DIR}/${arch_suffix}" )
343     file( MAKE_DIRECTORY ${LIBCLC_ARCH_OBJFILE_DIR} )
345     string( TOUPPER "CLC_${ARCH}" CLC_TARGET_DEFINE )
347     list( APPEND build_flags
348       -D__CLC_INTERNAL
349       -D${CLC_TARGET_DEFINE}
350       -I${CMAKE_CURRENT_SOURCE_DIR}/generic/include
351       # FIXME: Fix libclc to not require disabling this noisy warning
352       -Wno-bitwise-conditional-parentheses
353     )
355     set( bytecode_files "" )
356     foreach( file IN LISTS gen_files rel_files )
357       # We need to take each file and produce an absolute input file, as well
358       # as a unique architecture-specific output file. We deal with a mix of
359       # different input files, which makes this trickier.
360       if( ${file} IN_LIST gen_files )
361         # Generated files are given just as file names, which we must make
362         # absolute to the binary directory.
363         set( input_file ${CMAKE_CURRENT_BINARY_DIR}/${file} )
364         set( output_file "${LIBCLC_ARCH_OBJFILE_DIR}/${file}.bc" )
365       else()
366         # Other files are originally relative to each SOURCE file, which are
367         # then make relative to the libclc root directory. We must normalize
368         # the path (e.g., ironing out any ".."), then make it relative to the
369         # root directory again, and use that relative path component for the
370         # binary path.
371         get_filename_component( abs_path ${file} ABSOLUTE BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR} )
372         file( RELATIVE_PATH root_rel_path ${CMAKE_CURRENT_SOURCE_DIR} ${abs_path} )
373         set( input_file ${CMAKE_CURRENT_SOURCE_DIR}/${file} )
374         set( output_file "${LIBCLC_ARCH_OBJFILE_DIR}/${root_rel_path}.bc" )
375       endif()
377       get_filename_component( file_dir ${file} DIRECTORY )
379       compile_to_bc(
380         TRIPLE ${clang_triple}
381         INPUT ${input_file}
382         OUTPUT ${output_file}
383         EXTRA_OPTS "${mcpu}" -fno-builtin -nostdlib
384                    "${build_flags}" -I${CMAKE_CURRENT_SOURCE_DIR}/${file_dir}
385         DEPENDENCIES generate_convert.cl clspv-generate_convert.cl
386       )
387       list( APPEND bytecode_files ${output_file} )
388     endforeach()
390     set( builtins_comp_lib_tgt builtins.comp.${arch_suffix} )
391     add_custom_target( ${builtins_comp_lib_tgt}
392       DEPENDS ${bytecode_files}
393     )
394     set_target_properties( ${builtins_comp_lib_tgt} PROPERTIES FOLDER "libclc/Device IR/Comp" )
396     set( builtins_link_lib_tgt builtins.link.${arch_suffix} )
397     link_bc(
398       TARGET ${builtins_link_lib_tgt}
399       INPUTS ${bytecode_files}
400       DEPENDENCIES ${builtins_comp_lib_tgt}
401     )
403     set( builtins_link_lib $<TARGET_PROPERTY:${builtins_link_lib_tgt},TARGET_FILE> )
405     if( ARCH STREQUAL spirv OR ARCH STREQUAL spirv64 )
406       set( spv_suffix ${arch_suffix}.spv )
407       add_custom_command( OUTPUT ${spv_suffix}
408         COMMAND libclc::llvm-spirv ${spvflags} -o ${spv_suffix} ${builtins_link_lib}
409         DEPENDS ${builtins_link_lib} ${builtins_link_lib_tgt}
410       )
411       add_custom_target( "prepare-${spv_suffix}" ALL DEPENDS "${spv_suffix}" )
412       set_target_properties( "prepare-${spv_suffix}" PROPERTIES FOLDER "libclc/Device IR/Prepare" )
413       install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${spv_suffix}
414          DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" )
415     else()
416       set( builtins_opt_lib_tgt builtins.opt.${arch_suffix} )
418       # Add opt target
419       add_custom_command( OUTPUT ${builtins_opt_lib_tgt}.bc
420         COMMAND ${opt_exe} ${opt_flags} -o ${builtins_opt_lib_tgt}.bc
421           ${builtins_link_lib}
422         DEPENDS ${opt_target} ${builtins_link_lib} ${builtins_link_lib_tgt}
423       )
424       add_custom_target( ${builtins_opt_lib_tgt}
425         ALL DEPENDS ${builtins_opt_lib_tgt}.bc
426       )
427       set_target_properties( ${builtins_opt_lib_tgt}
428         PROPERTIES TARGET_FILE ${builtins_opt_lib_tgt}.bc
429                    FOLDER "libclc/Device IR/Opt"
430       )
432       set( builtins_opt_lib $<TARGET_PROPERTY:${builtins_opt_lib_tgt},TARGET_FILE> )
434       # Add prepare target
435       set( obj_suffix ${arch_suffix}.bc )
436       add_custom_command( OUTPUT ${obj_suffix}
437         COMMAND ${prepare_builtins_exe} -o ${obj_suffix} ${builtins_opt_lib}
438         DEPENDS ${builtins_opt_lib} ${builtins_opt_lib_tgt} ${prepare_builtins_target} )
439       add_custom_target( prepare-${obj_suffix} ALL DEPENDS ${obj_suffix} )
440       set_target_properties( "prepare-${obj_suffix}" PROPERTIES FOLDER "libclc/Device IR/Prepare" )
442       # nvptx-- targets don't include workitem builtins
443       if( NOT clang_triple MATCHES ".*ptx.*--$" )
444         add_test( NAME external-calls-${obj_suffix}
445           COMMAND ./check_external_calls.sh ${CMAKE_CURRENT_BINARY_DIR}/${obj_suffix} ${LLVM_TOOLS_BINARY_DIR}
446           WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
447       endif()
449       install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${obj_suffix} DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" )
450       foreach( a ${${d}_aliases} )
451         set( alias_suffix "${a}-${clang_triple}.bc" )
452         add_custom_target( ${alias_suffix} ALL
453           COMMAND ${CMAKE_COMMAND} -E create_symlink ${obj_suffix} ${alias_suffix}
454           DEPENDS prepare-${obj_suffix} )
455         set_target_properties( "${alias_suffix}" PROPERTIES FOLDER "libclc/Device IR/Aliases" )
456         install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${alias_suffix} DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" )
457       endforeach( a )
458     endif()
459   endforeach( d )
460 endforeach( t )