File: interop.cmake

package info (click to toggle)
ispc 1.28.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 97,620 kB
  • sloc: cpp: 77,067; python: 8,303; yacc: 3,337; lex: 1,126; ansic: 631; sh: 475; makefile: 17
file content (295 lines) | stat: -rw-r--r-- 12,248 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
## Copyright 2021-2023 Intel Corporation
## SPDX-License-Identifier: BSD-3-Clause

###############################################################################
## Definititions for ISPC/ESIMD and ISPC/DPC++ interoperability ###############
###############################################################################

# This module contains helper functions allowing to link several modules on
# LLVM IR level and translate final module to SPIR-V format.
# For ISPC and DPC++ SYCL the workflow is easy:
#   1. compile to bitcode
# This bitcode file is ready to be linked with others and translated to .spv.
# For DPC++ ESIMD:
#   1. extract ESIMD bitcode using clang-offload-bundler from DPC++ library
#   2. lower extracted bitcode to real VC backend intrinsics using sycl-post-link
# Lowered bitcode file can be linked with ISPC bitcode using llvm-link and
# translated then to .spv with llvm-spirv.

# Find DPCPP compiler
set(OLD_CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH})
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
find_package(dpcpp_compiler REQUIRED)
set(CMAKE_MODULE_PATH ${OLD_CMAKE_MODULE_PATH})
unset(OLD_CMAKE_MODULE_PATH)

# Create DPCPP library or SPIR-V file
# target_name: name of the target to use for the created library
# ARGN: DPCPP source files
function (add_dpcpp_library target_name)
    cmake_parse_arguments(PARSE_ARGV 1 DPCPP "SPV" "" "")
    set(outdir ${CMAKE_CURRENT_BINARY_DIR})

    set(DPCPP_CXX_FLAGS "")
    if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
        set(DPCPP_CXX_FLAGS "-O3")
    elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
        set(DPCPP_CXX_FLAGS "-g")
    elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo")
        set(DPCPP_CXX_FLAGS "-O2" "-g")
    else()
        message(FATAL_ERROR "add_dpcpp_library only supports Debug;Release;RelWithDebInfo build configs")
    endif()

    # Compile each DPCPP file
    set(DPCPP_RESULTS "")
    foreach(src ${DPCPP_UNPARSED_ARGUMENTS})
        get_filename_component(fname ${src} NAME_WE)

        # If input path is not absolute, prepend ${CMAKE_CURRENT_LIST_DIR}
        if(NOT IS_ABSOLUTE ${src})
            set(input ${CMAKE_CURRENT_LIST_DIR}/${src})
        else()
            set(input ${src})
        endif()
        set (TARGET_OUTPUT_FILE "${outdir}/${fname}")
        if (DPCPP_SPV)
            set(TARGET_OUTPUT_FILE_RESULT "${TARGET_OUTPUT_FILE}.spv")
        else()
            set(TARGET_OUTPUT_FILE_RESULT "${TARGET_OUTPUT_FILE}.o")
        endif()

        if(DPCPP_CUSTOM_INCLUDE_DIR)
            string(REPLACE ";" ";-I;" DPCPP_CUSTOM_INCLUDE_DIR_PARMS "${DPCPP_CUSTOM_INCLUDE_DIR}")
            set(DPCPP_CUSTOM_INCLUDE_DIR_PARMS "-I" ${DPCPP_CUSTOM_INCLUDE_DIR_PARMS})
        endif()

        # Allow function pointers in DPC++ and do not instrument SYCL code.
        list(APPEND DPCPP_CUSTOM_FLAGS "-Xclang" "-fsycl-allow-func-ptr" "-fno-sycl-instrument-device-code")
        if (DPCPP_SPV)
            # Get only SYCL device code to bicode first
            # WA: SYCL assert implementation should be treated separately.
            # Disable usage of asserts for now with "-DSYCL_DISABLE_FALLBACK_ASSERT=1"
            list(APPEND DPCPP_CUSTOM_FLAGS "-fsycl-device-only" "-DSYCL_DISABLE_FALLBACK_ASSERT=1")
        else()
            list(APPEND DPCPP_CUSTOM_FLAGS "-c")
        endif()

        list(APPEND SYCL_POST_LINK_ARGS
            "-split=auto"
            "-symbols"
            "-lower-esimd"
            "-emit-param-info"
            "-emit-exported-symbols"
            "-spec-const=native"
            "-device-globals"
            "-O2"
        )

        list(APPEND SPV_EXTENSIONS
            "-all"
            "+SPV_EXT_shader_atomic_float_add"
            "+SPV_EXT_shader_atomic_float_min_max"
            "+SPV_KHR_no_integer_wrap_decoration"
            "+SPV_KHR_float_controls"
            "+SPV_INTEL_subgroups"
            "+SPV_INTEL_media_block_io"
            "+SPV_INTEL_fpga_reg"
            "+SPV_INTEL_device_side_avc_motion_estimation"
            "+SPV_INTEL_fpga_loop_controls"
            "+SPV_INTEL_fpga_memory_attributes"
            "+SPV_INTEL_fpga_memory_accesses"
            "+SPV_INTEL_unstructured_loop_controls"
            "+SPV_INTEL_blocking_pipes"
            "+SPV_INTEL_io_pipes"
            "+SPV_INTEL_function_pointers"
            "+SPV_INTEL_kernel_attributes"
            "+SPV_INTEL_float_controls2"
            "+SPV_INTEL_inline_assembly"
            "+SPV_INTEL_optimization_hints"
            "+SPV_INTEL_arbitrary_precision_integers"
            "+SPV_INTEL_vector_compute"
            "+SPV_INTEL_fast_composite"
            "+SPV_INTEL_fpga_buffer_location"
            "+SPV_INTEL_arbitrary_precision_fixed_point"
            "+SPV_INTEL_arbitrary_precision_floating_point"
            "+SPV_INTEL_variable_length_array"
            "+SPV_INTEL_fp_fast_math_mode"
            "+SPV_INTEL_fpga_cluster_attributes"
            "+SPV_INTEL_loop_fuse"
            "+SPV_INTEL_long_constant_composite"
            "+SPV_INTEL_fpga_invocation_pipelining_attributes"
        )
        string(REPLACE ";" "," SPV_EXT_PARMS "${SPV_EXTENSIONS}")

        list(APPEND DPCPP_LLVM_SPIRV_ARGS
            "-spirv-debug-info-version=ocl-100"
            "-spirv-allow-extra-diexpressions"
            "-spirv-allow-unknown-intrinsics=llvm.genx."
            "-spirv-ext=${SPV_EXT_PARMS}"
        )

        add_custom_command(
            DEPENDS ${input}
            OUTPUT "${TARGET_OUTPUT_FILE_RESULT}"
            COMMAND ${DPCPP_COMPILER}
                -fsycl
                -fPIE
                ${DPCPP_CXX_FLAGS}
                ${DPCPP_CUSTOM_INCLUDE_DIR_PARMS}
                ${DPCPP_CUSTOM_FLAGS}
                -I ${CMAKE_CURRENT_SOURCE_DIR}
                -o "$<IF:$<BOOL:${DPCPP_SPV}>,${TARGET_OUTPUT_FILE}.bc,${TARGET_OUTPUT_FILE}.o>"
                ${input}

            # Run sycl-post-link on it
            COMMAND
            "$<$<BOOL:${DPCPP_SPV}>:${DPCPP_SYCL_POST_LINK}>"
            "$<$<BOOL:${DPCPP_SPV}>:${SYCL_POST_LINK_ARGS};${TARGET_OUTPUT_FILE}.bc>"
            "$<$<BOOL:${DPCPP_SPV}>:-o;${TARGET_OUTPUT_FILE}.postlink.bc>"

            # And finally back to SPV to the original expected target SPV name
            COMMAND
            "$<$<BOOL:${DPCPP_SPV}>:${DPCPP_LLVM_SPIRV}>"
            # Pick the right input to llvm-spirv based on if we're linking scalar or esimd
            # DPCPP libraries.
            "$<$<BOOL:${DPCPP_SPV}>:${TARGET_OUTPUT_FILE}.postlink_0.bc>"
            "$<$<BOOL:${DPCPP_SPV}>:${DPCPP_LLVM_SPIRV_ARGS}>"
            "$<$<BOOL:${DPCPP_SPV}>:-o;${TARGET_OUTPUT_FILE}.spv>"
            COMMENT "Building DPCPP object ${TARGET_OUTPUT_FILE_RESULT}"
            COMMAND_EXPAND_LISTS
            VERBATIM
        )

        list(APPEND DPCPP_RESULTS ${TARGET_OUTPUT_FILE_RESULT})
    endforeach()

    if (DPCPP_SPV)
        add_custom_target(${target_name} DEPENDS ${DPCPP_RESULTS})
    else()
        add_library(${target_name} STATIC)
        set_target_properties(${target_name} PROPERTIES
            LINKER_LANGUAGE CXX
            SOURCES "${DPCPP_RESULTS}")
    endif()
endfunction()

# Extract esimd bitcode
# target_name: name of the target to use for the extracted bitcode. The bitcode
#              file output path will be set as the LIBRARY_OUTPUT_DIRECTORY property
#              and the file name set to the LIBRARY_OUTPUT_NAME property
# library: the library to extract bitcode from
function (dpcpp_get_esimd_bitcode target_name library)
    set(outdir ${CMAKE_CURRENT_BINARY_DIR})
    # Result after unbundle command
    set(bundler_result_tmp "${outdir}/${target_name}.out")
    # Result after bitcode linking of unbundled output
    set(bundler_result "${outdir}/${target_name}.bc")
    # Intermediate bitcode file with link to the real one
    set(lower_post_link "${outdir}/${target_name}_lower.bc")
    # Final esimd bitcode file
    set(post_link_result "${outdir}/${target_name}_lower_esimd_0.bc")

    add_custom_command(
        DEPENDS ${library}
        OUTPUT ${lower_post_link} ${post_link_result}
        COMMAND ${DPCPP_CLANG_BUNDLER}
            --input=$<TARGET_FILE:${library}>
            --unbundle
            --targets=sycl-spir64-unknown-unknown-sycldevice
            --type=a
            --output=${bundler_result_tmp}
        COMMAND ${DPCPP_LLVM_LINK}
            ${bundler_result_tmp}
            -o ${bundler_result}
        COMMAND ${DPCPP_SYCL_POST_LINK}
            -split=auto
            -symbols
            -lower-esimd
            -emit-param-info
            -emit-exported-symbols
            -spec-const=native
            -device-globals
            -O2
            -o ${lower_post_link}
            ${bundler_result}
        COMMENT "Extracting ESIMD Bitcode ${bundler_result_tmp}"
    )
    add_custom_target(${target_name} DEPENDS ${post_link_result})
    set_target_properties(${target_name} PROPERTIES
        LIBRARY_OUTPUT_DIRECTORY ${outdir}
        LIBRARY_OUTPUT_NAME ${target_name}_lower_esimd_0.bc
    )
endfunction()

# Extract dpcpp sycl bitcode
# target_name: name of the target to use for the extracted bitcode. The bitcode
#              file output path will be set as the LIBRARY_OUTPUT_DIRECTORY property
#              and the file name set to the LIBRARY_OUTPUT_NAME property
# library: the library to extract bitcode from
function (dpcpp_get_sycl_bitcode target_name library)
    set(outdir ${CMAKE_CURRENT_BINARY_DIR})
    # Result after unbundle command
    set(bundler_result_tmp "${outdir}/${target_name}.out")
    # Result after bitcode linking of unbundled output
    set(bundler_result "${outdir}/${target_name}.bc")

    add_custom_command(
        DEPENDS ${library}
        OUTPUT ${bundler_result}
        COMMAND ${DPCPP_CLANG_BUNDLER}
            --input=$<TARGET_FILE:${library}>
            --unbundle
            --targets=sycl-spir64-unknown-unknown-sycldevice
            --type=a
            --output=${bundler_result_tmp}
        COMMAND ${DPCPP_LLVM_LINK}
            ${bundler_result_tmp}
            -o ${bundler_result}
        COMMENT "Extracting DPC++ Bitcode ${bundler_result}"
    )

    add_custom_target(${target_name} DEPENDS ${bundler_result})
    set_target_properties(${target_name} PROPERTIES
        LIBRARY_OUTPUT_DIRECTORY ${outdir}
        LIBRARY_OUTPUT_NAME ${target_name}.bc
    )
endfunction()

function(ispc_target_link_dpcpp_libraries TARGET_NAME)
    if (NOT BUILD_GPU)
        message(FATAL_ERROR "Linking of ISPC/DPC++ modules is supported on GPU only")
    endif()
    get_property(GPU_LINK_LIBRARIES TARGET ${TARGET_NAME}_gpu PROPERTY ISPC_DPCPP_LINK_LIBRARIES)
    # Get the library file name for each library we want to link
    foreach (lib ${ARGN})
      # Make the dpcpp_bc target to extract the bitcode so we can link it
      dpcpp_get_sycl_bitcode(${lib}_dpcpp_bc ${lib})

      get_property(LIB_OUTPUT_PATH TARGET ${lib}_dpcpp_bc PROPERTY LIBRARY_OUTPUT_DIRECTORY)
      get_property(LIB_OUTPUT_NAME TARGET ${lib}_dpcpp_bc PROPERTY LIBRARY_OUTPUT_NAME)
      list(APPEND GPU_LINK_LIBRARIES ${LIB_OUTPUT_PATH}/${LIB_OUTPUT_NAME})
    endforeach()
    set_target_properties(${TARGET_NAME}_gpu
      PROPERTIES ISPC_DPCPP_LINK_LIBRARIES "${GPU_LINK_LIBRARIES}")
endfunction()

function(ispc_target_link_dpcpp_esimd_libraries TARGET_NAME)
    if (NOT BUILD_GPU)
        message(FATAL_ERROR "Linking of ISPC/DPC++ modules is supported on GPU only")
    endif()
    get_property(GPU_LINK_LIBRARIES TARGET ${TARGET_NAME}_gpu PROPERTY ISPC_DPCPP_LINK_LIBRARIES)
    # Get the library file name for each library we want to link
    foreach (lib ${ARGN})
      # Make the dpcpp_bc target to extract the bitcode so we can link it
      dpcpp_get_esimd_bitcode(${lib}_dpcpp_esimd_bc ${lib})

      get_property(LIB_OUTPUT_PATH TARGET ${lib}_dpcpp_esimd_bc PROPERTY LIBRARY_OUTPUT_DIRECTORY)
      get_property(LIB_OUTPUT_NAME TARGET ${lib}_dpcpp_esimd_bc PROPERTY LIBRARY_OUTPUT_NAME)
      list(APPEND GPU_LINK_LIBRARIES ${LIB_OUTPUT_PATH}/${LIB_OUTPUT_NAME})
    endforeach()
    set_target_properties(${TARGET_NAME}_gpu PROPERTIES
      ISPC_DPCPP_LINK_LIBRARIES "${GPU_LINK_LIBRARIES}"
      ISPC_DPCPP_LINKING_ESIMD 1
     )
endfunction()