[llvm] [libsycl] Implement nd_range kernel submissions (PR #206505)

Kseniya Tikhomirova via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 13 06:52:45 PDT 2026


================
@@ -0,0 +1,147 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the declaration of the SYCL 2020 group class.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBSYCL___IMPL_GROUP_HPP
+#define _LIBSYCL___IMPL_GROUP_HPP
+
+#include <sycl/__impl/detail/config.hpp>
+#include <sycl/__impl/detail/linearization.hpp>
+#include <sycl/__impl/index_space_classes.hpp>
+#include <sycl/__impl/memory_enums.hpp>
+#include <sycl/__spirv/spirv_vars.hpp>
+
+#include <cstddef>
+
+_LIBSYCL_BEGIN_NAMESPACE_SYCL
+
+template <int> class nd_item;
+
+// SYCL2020 4.9.1.7. group class.
+/// The group class encapsulates all functionality required to represent a
+///  particular work-group within a parallel execution.
+template <int Dimensions = 1> class group {
+public:
+  using id_type = id<Dimensions>;
+  using range_type = range<Dimensions>;
+  using linear_id_type = std::size_t;
+  static constexpr int dimensions = Dimensions;
+  static constexpr memory_scope fence_scope = memory_scope::work_group;
+
+  group(const group &rhs) = default;
+  group(group &&rhs) = default;
+  group &operator=(const group &rhs) = default;
+  group &operator=(group &&rhs) = default;
+
+  /// \return an id representing the index of the work-group within the global
+  /// nd-range for every dimension.
+  id<Dimensions> get_group_id() const noexcept {
+    return __spirv::initBuiltInWorkgroupId<Dimensions, id<Dimensions>>();
+  }
+
+  /// Equivalent to `return get_group_id()[dimension]`.
+  std::size_t get_group_id(int dimension) const noexcept {
+    return get_group_id()[dimension];
+  }
+
+  /// \return a SYCL id representing the calling work-item’s position within the
+  /// work-group.
+  id<Dimensions> get_local_id() const noexcept {
+    return __spirv::initBuiltInLocalInvocationId<Dimensions, id<Dimensions>>();
+  }
+
+  /// Equivalent to `return get_local_id()[dimension]`.
+  std::size_t get_local_id(int dimension) const noexcept {
+    return get_local_id()[dimension];
+  }
+
+  /// \return a SYCL range representing all dimensions of the local range.
+  range<Dimensions> get_local_range() const noexcept {
+    return __spirv::initBuiltInWorkgroupSize<Dimensions, range<Dimensions>>();
+  }
+
+  /// Equivalent to `return get_local_range()[dimension]`.
+  std::size_t get_local_range(int dimension) const noexcept {
+    return get_local_range()[dimension];
+  }
+
+  /// \return a SYCL range representing the number of work-groups in the
+  /// nd-range.
+  range<Dimensions> get_group_range() const noexcept {
+    return __spirv::initBuiltInNumWorkgroups<Dimensions, range<Dimensions>>();
+  }
+
+  /// Equivalent to `return get_group_range()[dimension]`.
+  std::size_t get_group_range(int dimension) const noexcept {
+    return get_group_range()[dimension];
+  }
+
+  /// \return a SYCL range representing the maximum number of work-items in any
+  /// work-group in the nd-range.
+  range<Dimensions> get_max_local_range() const noexcept {
+    return get_local_range();
+  }
+
+  /// Equivalent to `return get_group_id(dimension)`.
+  std::size_t operator[](int dimension) const noexcept {
+    return get_group_id(dimension);
+  }
+
+  /// \return the linearized work-group id within the nd-range.
+  std::size_t get_group_linear_id() const noexcept {
+    return detail::linearize_id(get_group_id(), get_group_range());
+  }
+
+  /// \return a linearized version of the calling work-item’s local id.
+  std::size_t get_local_linear_id() const noexcept {
+    return detail::linearize_id(get_local_id(), get_local_range());
+  }
+
+  /// \return the total number of work-groups in the nd-range.
+  std::size_t get_group_linear_range() const noexcept {
+    auto groupRange = get_group_range();
+    return multiply_all_dims(groupRange);
+  }
+
+  /// \return the total number of work-items in this work-group.
+  std::size_t get_local_linear_range() const noexcept {
+    auto localRange = get_local_range();
+    return multiply_all_dims(localRange);
+  }
+
+  /// \return true for exactly one work-item in the work-group, if the calling
+  /// work-item is the leader of the work-group, and false for all other
+  /// work-items in the work-group.
+  bool leader() const noexcept { return (get_local_linear_id() == 0); }
+
+  // TODO: implement parallel_for_work_item, async_work_group_copy and wait_for.
+
+protected:
+  group() = default;
+
+  static std::size_t
+  multiply_all_dims(const range<Dimensions> &Range) noexcept {
+    if constexpr (Dimensions == 1) {
+      return Range[0];
+    } else if constexpr (Dimensions == 2) {
+      return Range[0] * Range[1];
+    } else {
+      return Range[0] * Range[1] * Range[2];
+    }
+  }
+
+  template <int dimensions> friend class sycl::nd_item;
----------------
KseniyaTikhomirova wrote:

class group has its own remplate parameter Dimensions. I can't use the same name for friend function declaration inside class here.

https://github.com/llvm/llvm-project/pull/206505


More information about the llvm-commits mailing list