diff --git a/clang/docs/SYCLSupport.md b/clang/docs/SYCLSupport.md --- a/clang/docs/SYCLSupport.md +++ b/clang/docs/SYCLSupport.md @@ -813,6 +813,113 @@ The SPIR-V specific functions are implemented in for the SYCL host device here: `sycl/source/spirv_ops.cpp`. +### Address spaces handling + +SYCL specification uses C++ classes to represent pointers to disjoint memory +regions on an accelerator to enable compilation with standard C++ toolchain and +SYCL compiler toolchain. Section 3.8.2 of SYCL 2020 specification defines +[memory model](https://www.khronos.org/registry/SYCL/specs/sycl-2020/html/sycl-2020.html#_sycl_device_memory_model), +section 4.7.7 - [address space classes](https://www.khronos.org/registry/SYCL/specs/sycl-2020/html/sycl-2020.html#_address_space_classes) +and section 5.9.2 covers [address space deduction](https://www.khronos.org/registry/SYCL/specs/sycl-2020/html/sycl-2020.html#_address_space_deduction). + +For instance: + +``` C++ +// check that SYCL mode is ON and we can use non-standard decorations +#if defined(__SYCL_DEVICE_ONLY__) +// GPU/accelerator implementation +template class multi_ptr { + // DecoratedType applies corresponding address space attribute to the type T + // DecoratedType::type == "__attribute__((opencl_global)) T" + // See sycl/include/CL/sycl/access/access.hpp for more details + using pointer_t = typename DecoratedType::type *; + + pointer_t m_Pointer; + public: + pointer_t get() { return m_Pointer; } + T& operator* () { return *reinterpret_cast(m_Pointer); } +} +#else +// CPU/host implementation +template class multi_ptr { + T *m_Pointer; // regular undecorated pointer + public: + T *get() { return m_Pointer; } + T& operator* () { return *m_Pointer; } +} +#endif +``` + +Depending on the compiler mode `multi_ptr` will either decorate internal data +with address space attribute or not. + +The main address space semantic difference of SYCL mode from OpenCL is that +SYCL doesn't assign OpenCL generic address space to a declaration's type without +explicit address space attribute. Similar to other single-source C++-based GPU +programming modes like OpenMP/CUDA/HIP, SYCL uses clang's "default" address +space for types with no address space attributes. During the lowering to LLVM +IR, the default address space is mapped to the SPIR generic address space. +Declarations are assigned to the relevant memory region depending on their +declaration context and pointers to them are cast to generic. This design has +two important features: keeps the type system consistent with C++ on one hand +and enable tools for emitting device code aligned with SPIR memory model (and +other GPU targets). + +So inside a function, this variable declaration: + +```C++ +int var; +``` + +SYCL device compiler turns into + +```C++ +VarDecl var 'int' +``` + +OpenCL compiler turn into + +```C++ +VarDecl var '__private int' +``` + +Changing variable type has massive and destructive effect in C++. For instance +this does not compile in C++ for OpenCL mode: + +```C++ +template +struct is_same { + static constexpr int value = 0; +}; + +template +struct is_same { + static constexpr int value = 1; +}; + +void foo(int p) { + static_assert(is_same::value, "int is not an int?"); // Fails: p is '__private int' != 'int' + static_assert(is_same::value, "int* is not an int*?"); // Fails: p is '__private int*' != '__generic int*' +} +``` + +To utilize existing clang's functionality, we re-use following OpenCL address +space attributes in SYCL mode: + +| Address space attribute | SYCL address_space enumeration | +|-------------------------|--------------------------------| +| `__attribute__((opencl_global))` | global_space, constant_space | +| `__attribute__((opencl_global_host))` | global_host_space | +| `__attribute__((opencl_global_device))` | global_device_space | +| `__attribute__((opencl_local))` | local_space | +| `__attribute__((opencl_private))` | private_space | +| `__attribute__((opencl_constant))` | N/A + +> **NOTE**: although SYCL device compiler supports +`__attribute__((opencl_constant))`, the use of this attribute is limited within +SYCL implementation. An OpenCL constant pointer can not be casted to a pointer +with any other address space (including default). + ### Compiler/Runtime interface ## SYCL Runtime architecture