xref: /openbsd/gnu/llvm/clang/docs/SYCLSupport.rst (revision a9ac8606)
1*a9ac8606Spatrick=============================================
2*a9ac8606SpatrickSYCL Compiler and Runtime architecture design
3*a9ac8606Spatrick=============================================
4*a9ac8606Spatrick
5*a9ac8606Spatrick.. contents::
6*a9ac8606Spatrick   :local:
7*a9ac8606Spatrick
8*a9ac8606SpatrickIntroduction
9*a9ac8606Spatrick============
10*a9ac8606Spatrick
11*a9ac8606SpatrickThis document describes the architecture of the SYCL compiler and runtime
12*a9ac8606Spatricklibrary. More details are provided in
13*a9ac8606Spatrick`external document <https://github.com/intel/llvm/blob/sycl/sycl/doc/CompilerAndRuntimeDesign.md>`_\ ,
14*a9ac8606Spatrickwhich are going to be added to clang documentation in the future.
15*a9ac8606Spatrick
16*a9ac8606SpatrickAddress space handling
17*a9ac8606Spatrick======================
18*a9ac8606Spatrick
19*a9ac8606SpatrickThe SYCL specification represents pointers to disjoint memory regions using C++
20*a9ac8606Spatrickwrapper classes on an accelerator to enable compilation with a standard C++
21*a9ac8606Spatricktoolchain and a SYCL compiler toolchain. Section 3.8.2 of SYCL 2020
22*a9ac8606Spatrickspecification defines
23*a9ac8606Spatrick`memory model <https://www.khronos.org/registry/SYCL/specs/sycl-2020/html/sycl-2020.html#_sycl_device_memory_model>`_\ ,
24*a9ac8606Spatricksection 4.7.7 - `address space classes <https://www.khronos.org/registry/SYCL/specs/sycl-2020/html/sycl-2020.html#_address_space_classes>`_
25*a9ac8606Spatrickand section 5.9 covers `address space deduction <https://www.khronos.org/registry/SYCL/specs/sycl-2020/html/sycl-2020.html#_address_space_deduction>`_.
26*a9ac8606SpatrickThe SYCL specification allows two modes of address space deduction: "generic as
27*a9ac8606Spatrickdefault address space" (see section 5.9.3) and "inferred address space" (see
28*a9ac8606Spatricksection 5.9.4). Current implementation supports only "generic as default address
29*a9ac8606Spatrickspace" mode.
30*a9ac8606Spatrick
31*a9ac8606SpatrickSYCL borrows its memory model from OpenCL however SYCL doesn't perform
32*a9ac8606Spatrickthe address space qualifier inference as detailed in
33*a9ac8606Spatrick`OpenCL C v3.0 6.7.8 <https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_C.html#addr-spaces-inference>`_.
34*a9ac8606Spatrick
35*a9ac8606SpatrickThe default address space is "generic-memory", which is a virtual address space
36*a9ac8606Spatrickthat overlaps the global, local, and private address spaces. SYCL mode enables
37*a9ac8606Spatrickfollowing conversions:
38*a9ac8606Spatrick
39*a9ac8606Spatrick- explicit conversions to/from the default address space from/to the address
40*a9ac8606Spatrick  space-attributed type
41*a9ac8606Spatrick- implicit conversions from the address space-attributed type to the default
42*a9ac8606Spatrick  address space
43*a9ac8606Spatrick- explicit conversions to/from the global address space from/to the
44*a9ac8606Spatrick  ``__attribute__((opencl_global_device))`` or
45*a9ac8606Spatrick  ``__attribute__((opencl_global_host))`` address space-attributed type
46*a9ac8606Spatrick- implicit conversions from the ``__attribute__((opencl_global_device))`` or
47*a9ac8606Spatrick  ``__attribute__((opencl_global_host))`` address space-attributed type to the
48*a9ac8606Spatrick  global address space
49*a9ac8606Spatrick
50*a9ac8606SpatrickAll named address spaces are disjoint and sub-sets of default address space.
51*a9ac8606Spatrick
52*a9ac8606SpatrickThe SPIR target allocates SYCL namespace scope variables in the global address
53*a9ac8606Spatrickspace.
54*a9ac8606Spatrick
55*a9ac8606SpatrickPointers to default address space should get lowered into a pointer to a generic
56*a9ac8606Spatrickaddress space (or flat to reuse more general terminology). But depending on the
57*a9ac8606Spatrickallocation context, the default address space of a non-pointer type is assigned
58*a9ac8606Spatrickto a specific address space. This is described in
59*a9ac8606Spatrick`common address space deduction rules <https://www.khronos.org/registry/SYCL/specs/sycl-2020/html/sycl-2020.html#subsec:commonAddressSpace>`_
60*a9ac8606Spatricksection.
61*a9ac8606Spatrick
62*a9ac8606SpatrickThis is also in line with the behaviour of CUDA (`small example
63*a9ac8606Spatrick<https://godbolt.org/z/veqTfo9PK>`_).
64*a9ac8606Spatrick
65*a9ac8606Spatrick``multi_ptr`` class implementation example:
66*a9ac8606Spatrick
67*a9ac8606Spatrick.. code-block:: C++
68*a9ac8606Spatrick
69*a9ac8606Spatrick   // check that SYCL mode is ON and we can use non-standard decorations
70*a9ac8606Spatrick   #if defined(__SYCL_DEVICE_ONLY__)
71*a9ac8606Spatrick   // GPU/accelerator implementation
72*a9ac8606Spatrick   template <typename T, address_space AS> class multi_ptr {
73*a9ac8606Spatrick     // DecoratedType applies corresponding address space attribute to the type T
74*a9ac8606Spatrick     // DecoratedType<T, global_space>::type == "__attribute__((opencl_global)) T"
75*a9ac8606Spatrick     // See sycl/include/CL/sycl/access/access.hpp for more details
76*a9ac8606Spatrick     using pointer_t = typename DecoratedType<T, AS>::type *;
77*a9ac8606Spatrick
78*a9ac8606Spatrick     pointer_t m_Pointer;
79*a9ac8606Spatrick     public:
80*a9ac8606Spatrick     pointer_t get() { return m_Pointer; }
81*a9ac8606Spatrick     T& operator* () { return *reinterpret_cast<T*>(m_Pointer); }
82*a9ac8606Spatrick   }
83*a9ac8606Spatrick   #else
84*a9ac8606Spatrick   // CPU/host implementation
85*a9ac8606Spatrick   template <typename T, address_space AS> class multi_ptr {
86*a9ac8606Spatrick     T *m_Pointer; // regular undecorated pointer
87*a9ac8606Spatrick     public:
88*a9ac8606Spatrick     T *get() { return m_Pointer; }
89*a9ac8606Spatrick     T& operator* () { return *m_Pointer; }
90*a9ac8606Spatrick   }
91*a9ac8606Spatrick   #endif
92*a9ac8606Spatrick
93*a9ac8606SpatrickDepending on the compiler mode, ``multi_ptr`` will either decorate its internal
94*a9ac8606Spatrickdata with the address space attribute or not.
95*a9ac8606Spatrick
96*a9ac8606SpatrickTo utilize clang's existing functionality, we reuse the following OpenCL address
97*a9ac8606Spatrickspace attributes for pointers:
98*a9ac8606Spatrick
99*a9ac8606Spatrick.. list-table::
100*a9ac8606Spatrick   :header-rows: 1
101*a9ac8606Spatrick
102*a9ac8606Spatrick   * - Address space attribute
103*a9ac8606Spatrick     - SYCL address_space enumeration
104*a9ac8606Spatrick   * - ``__attribute__((opencl_global))``
105*a9ac8606Spatrick     - global_space, constant_space
106*a9ac8606Spatrick   * - ``__attribute__((opencl_global_device))``
107*a9ac8606Spatrick     - global_space
108*a9ac8606Spatrick   * - ``__attribute__((opencl_global_host))``
109*a9ac8606Spatrick     - global_space
110*a9ac8606Spatrick   * - ``__attribute__((opencl_local))``
111*a9ac8606Spatrick     - local_space
112*a9ac8606Spatrick   * - ``__attribute__((opencl_private))``
113*a9ac8606Spatrick     - private_space
114*a9ac8606Spatrick
115*a9ac8606Spatrick
116*a9ac8606Spatrick.. code-block:: C++
117*a9ac8606Spatrick
118*a9ac8606Spatrick    //TODO: add support for __attribute__((opencl_global_host)) and __attribute__((opencl_global_device)).
119*a9ac8606Spatrick
120