|
| 1 | +SYCL INTEL spatial pipes |
| 2 | +======================== |
| 3 | + |
| 4 | +Introduction |
| 5 | +============ |
| 6 | + |
| 7 | +SPIR-V is first class target in which SYCL pipes should be representable, and |
| 8 | +pipes are already exposed within SPIR-V. For this implementation API functions |
| 9 | +call for SPIR-V friendly mangled functions instead of OpenCL built-ins. |
| 10 | +This document describes how SYCL pipes are being lowered to SPIR-V. |
| 11 | + |
| 12 | +OpenCL 2.2 program pipe representation in SPIR-V |
| 13 | +================================================ |
| 14 | + |
| 15 | +The SPIR-V program pipe representation is used to be an underlying |
| 16 | +representation of intra-kernel and inter-kernel static pipe connectivity. |
| 17 | +The SPIR-V pipe representation exists in a series of pieces: |
| 18 | + |
| 19 | + - OpTypePipeStorage: Type representing memory allocated for storage of data |
| 20 | + within a pipe. Used for OpenCL 2.2 program pipes (program-scope pipes) that |
| 21 | + the host program is not aware of, but that enables connectivity between |
| 22 | + kernels. |
| 23 | + |
| 24 | + - OpConstantPipeStorage: Instruction that creates an OpTypePipeStorage object. |
| 25 | + Requires packet size (number of bytes) and capacity (number of packets) to be |
| 26 | + defined. |
| 27 | + |
| 28 | + - OpTypePipe: A pipe object that can act as a read/write endpoint of some pipe |
| 29 | + storage, either allocated by the host and passed as a kernel argument, or |
| 30 | + allocated at "program scope" through a pipe storage object. |
| 31 | + |
| 32 | + - OpCreatePipeFromPipeStorage: Creates a pipe object (that can be read/written) |
| 33 | + from an OpTypePipeStorage instance. |
| 34 | + |
| 35 | + - OpReadPipe / OpWritePipe: Read packet from or write packet to a pipe object. |
| 36 | + |
| 37 | +Lowering of kernel to kernel pipes to SPIR-V (non-blocking) |
| 38 | +=========================================================== |
| 39 | + |
| 40 | +This connectivity is achieved through OpTypePipeStorage which allows a SPIR-V |
| 41 | +device consumer to leverage static connectivity. An OpConstantPipeStorage |
| 42 | +instruction must create a single instance of OpPipeStorage for each kernel to |
| 43 | +kernel pipe type used by any kernel within the application. |
| 44 | + |
| 45 | +OpTypePipe objects is created from OpPipeStorage using |
| 46 | +OpCreatePipeFromPipeStorage. The number of OpTypePipe objects created from an |
| 47 | +OpPipeStorage object is an implementation detail, as are the access qualifiers |
| 48 | +applied to those types. For example, an implementation is free to create a |
| 49 | +different OpTypePipe corresponding to each read and write, with unidirectional |
| 50 | +access qualifiers annotated, or it can create fewer OpTypePipe objects, although |
| 51 | +read and write pipes must be distinct according to OpReadPipe and OpWritePipe |
| 52 | +rules. |
| 53 | + |
| 54 | +NOTE: The SPIR-V OpReadPipe and OpWritePipe instructions are non-blocking. |
| 55 | + |
| 56 | +Details SPIR-V representation in LLVM IR |
| 57 | +======================================== |
| 58 | + |
| 59 | +Pipe built-ins are mangled in LLVM IR to make it SPIR-V friendly. |
| 60 | +As an example: |
| 61 | + |
| 62 | + SPIR-V built-in | Mangled built-in in LLVM IR |
| 63 | + ----------------------------+----------------------------------------------- |
| 64 | + OpReadPipe | __spirv_ReadPipe |
| 65 | + ----------------------------+----------------------------------------------- |
| 66 | + OpWritePipe | __spirv_WritePipe |
| 67 | + ----------------------------+----------------------------------------------- |
| 68 | + OpCreatePipeFromPipeStorage | __spirv_CreatePipeFromPipeStorage_{read|write} |
| 69 | + |
| 70 | +More about SPIR-V representation in LLVM IR can be found under the link: |
| 71 | +.. _SPIRVRepresentationInLLVM.rst: https://github.com/KhronosGroup/SPIRV-LLVM-Translator/blob/master/docs/SPIRVRepresentationInLLVM.rst/ |
| 72 | + |
| 73 | +In SYCL headers the built-ins are declared as external functions with the |
| 74 | +appropriate mangling. The translator will transform calls of these built-ins |
| 75 | +into calls of SPIR-V instructions. |
| 76 | + |
| 77 | +Example of SYCL -> LLVM IR -> SPIR-V -> LLVM-IR code transformations |
| 78 | +==================================================================== |
| 79 | +Consider following SYCL device code: |
| 80 | +.. code:: cpp |
| 81 | + pipe<class some_pipe, int, 1>::write(42, SuccessCode); |
| 82 | +
|
| 83 | +After compiling this code with clang we will be given following piece of IR for |
| 84 | +the write pipe function call (NOTE: for this implementation clang-known |
| 85 | +OpenCL 2.0 pipe types are reused): |
| 86 | +.. code:: cpp |
| 87 | + define internal spir_func void @_ZN2cl4sycl4pipeIZ4mainE9some_pipeiLi1EE5writeEiRb(i32, i8* dereferenceable(1)) #4 align 2 { |
| 88 | + //... |
| 89 | + %12 = call spir_func i32 @_Z17__spirv_WritePipeIiEi8ocl_pipePT_ii(%opencl.pipe_wo_t addrspace(1)* %10, i32 addrspace(4)* %11, i32 4, i32 4) #8 |
| 90 | + //... |
| 91 | + } |
| 92 | +
|
| 93 | +with following declaration: |
| 94 | +.. code:: cpp |
| 95 | + %12 = call spir_func i32 @_Z17__spirv_WritePipeIiEi8ocl_pipePT_ii(%opencl.pipe_wo_t addrspace(1)* %10, i32 addrspace(4)* %11, i32 4, i32 4) #8 |
| 96 | +
|
| 97 | +SPIR-V translator will drop all of these manglings, just making a call of SPIR-V |
| 98 | +write pipe built-in: |
| 99 | +.. code:: cpp |
| 100 | + 7 WritePipe 51 158 156 157 52 52 |
| 101 | +
|
| 102 | +Resulting code for translation back to LLVM IR from SPIR-V are calls of OpenCL |
| 103 | +built-ins: |
| 104 | +.. code:: cpp |
| 105 | + define internal spir_func void @_ZN2cl4sycl4pipeIZ4mainE9some_pipeiLi1EE5writeEiRb(i32, i8*) #0 { |
| 106 | + //... |
| 107 | + %9 = call spir_func i32 @__write_pipe_2(%opencl.pipe_wo_t addrspace(1)* %6, i8 addrspace(4)* %8, i32 4, i32 4) //... |
| 108 | + } |
| 109 | +
|
| 110 | +again with write pipe declaration (but now it's built-in!): |
| 111 | +.. code:: cpp |
| 112 | + declare spir_func i32 @__write_pipe_2(%opencl.pipe_wo_t addrspace(1)*, i8 addrspace(4)*, i32, i32) #0 |
| 113 | +
|
| 114 | +The first argument in a call of __write_pipe_2 OpenCL built-in is a pipe object, |
| 115 | +which is created as a result of SPIR-V built-in call |
| 116 | +__spirv_CreatePipeFromPipeStorage_{read|write} which has no OpenCL |
| 117 | +representation and therefore stays in IR before and after SPIR-V tool-chain as: |
| 118 | +.. code:: cpp |
| 119 | + %9 = call spir_func %opencl.pipe_wo_t addrspace(1)* @_Z39__spirv_CreatePipeFromPipeStorage_writeIiE8ocl_pipe11PipeStorage(%struct._ZTS11PipeStorage.PipeStorage* byval align 4 %6) #8 |
0 commit comments