Skip to content

Commit c4936ce

Browse files
[SYCL] Introduce new properties for virtual functions (#14014)
See language specification for those properties in #10540
1 parent 4f73195 commit c4936ce

File tree

8 files changed

+300
-1
lines changed

8 files changed

+300
-1
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#pragma once
2+
3+
#include <sycl/ext/oneapi/properties/property.hpp>
4+
#include <sycl/ext/oneapi/properties/property_value.hpp>
5+
6+
namespace sycl {
7+
inline namespace _V1 {
8+
namespace ext::oneapi::experimental {
9+
struct indirectly_callable_key {
10+
template <typename Set>
11+
using value_t =
12+
sycl::ext::oneapi::experimental::property_value<indirectly_callable_key,
13+
Set>;
14+
};
15+
16+
template <typename Set = void>
17+
inline constexpr indirectly_callable_key::value_t<Set> indirectly_callable;
18+
19+
struct calls_indirectly_key {
20+
template <typename First = void, typename... SetIds>
21+
using value_t =
22+
sycl::ext::oneapi::experimental::property_value<calls_indirectly_key,
23+
First, SetIds...>;
24+
};
25+
26+
template <typename First = void, typename... Rest>
27+
inline constexpr calls_indirectly_key::value_t<First, Rest...> calls_indirectly;
28+
29+
template <> struct is_property_key<indirectly_callable_key> : std::true_type {};
30+
template <> struct is_property_key<calls_indirectly_key> : std::true_type {};
31+
32+
namespace detail {
33+
34+
template <>
35+
struct IsCompileTimeProperty<indirectly_callable_key> : std::true_type {};
36+
template <>
37+
struct IsCompileTimeProperty<calls_indirectly_key> : std::true_type {};
38+
39+
template <> struct PropertyToKind<indirectly_callable_key> {
40+
static constexpr PropKind Kind = PropKind::IndirectlyCallable;
41+
};
42+
43+
template <> struct PropertyToKind<calls_indirectly_key> {
44+
static constexpr PropKind Kind = PropKind::CallsIndirectly;
45+
};
46+
47+
template <typename Set>
48+
struct PropertyMetaInfo<indirectly_callable_key::value_t<Set>> {
49+
static constexpr const char *name = "indirectly-callable";
50+
static constexpr const char *value =
51+
#ifdef __SYCL_DEVICE_ONLY__
52+
__builtin_sycl_unique_stable_name(Set);
53+
#else
54+
"";
55+
#endif
56+
};
57+
58+
template <typename First, typename... Rest>
59+
struct PropertyMetaInfo<calls_indirectly_key::value_t<First, Rest...>> {
60+
static constexpr const char *name = "calls-indirectly";
61+
static constexpr const char *value =
62+
#ifdef __SYCL_DEVICE_ONLY__
63+
// FIXME: we should handle Rest... here as well
64+
__builtin_sycl_unique_stable_name(First);
65+
#else
66+
"";
67+
#endif
68+
};
69+
70+
} // namespace detail
71+
72+
} // namespace ext::oneapi::experimental
73+
} // namespace _V1
74+
} // namespace sycl

sycl/include/sycl/ext/oneapi/properties/property.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,10 @@ enum PropKind : uint32_t {
205205
WorkItemProgress = 64,
206206
NDRangeKernel = 65,
207207
SingleTaskKernel = 66,
208+
IndirectlyCallable = 67,
209+
CallsIndirectly = 68,
208210
// PropKindSize must always be the last value.
209-
PropKindSize = 67,
211+
PropKindSize = 69,
210212
};
211213

212214
struct property_key_base_tag {};

sycl/include/sycl/handler.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <sycl/ext/oneapi/device_global/properties.hpp>
3535
#include <sycl/ext/oneapi/experimental/graph.hpp>
3636
#include <sycl/ext/oneapi/experimental/use_root_sync_prop.hpp>
37+
#include <sycl/ext/oneapi/experimental/virtual_functions.hpp>
3738
#include <sycl/ext/oneapi/kernel_properties/properties.hpp>
3839
#include <sycl/ext/oneapi/properties/properties.hpp>
3940
#include <sycl/group.hpp>
@@ -962,6 +963,10 @@ class __SYCL_EXPORT handler {
962963
sycl::ext::intel::experimental::fp_control_key>() &&
963964
KI::isESIMD()),
964965
"Floating point control property is supported for ESIMD kernels only.");
966+
static_assert(
967+
!PropertiesT::template has_property<
968+
sycl::ext::oneapi::experimental::indirectly_callable_key>(),
969+
"indirectly_callable property cannot be applied to SYCL kernels");
965970
if constexpr (PropertiesT::template has_property<
966971
sycl::ext::intel::experimental::cache_config_key>()) {
967972
auto Config = Props.template get_property<

sycl/test/include_deps/sycl_detail_core.hpp.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,5 +178,6 @@
178178
// CHECK-NEXT: ext/oneapi/bindless_images_interop.hpp
179179
// CHECK-NEXT: ext/oneapi/bindless_images_mem_handle.hpp
180180
// CHECK-NEXT: ext/oneapi/experimental/use_root_sync_prop.hpp
181+
// CHECK-NEXT: ext/oneapi/experimental/virtual_functions.hpp
181182
// CHECK-NEXT: ext/oneapi/kernel_properties/properties.hpp
182183
// CHECK-EMPTY:
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// RUN: %clangxx -fsycl -fsycl-device-only -emit-llvm -S %s -o %t.ll
2+
// RUN: FileCheck %s < %t.ll
3+
//
4+
// This test is intended to check integration between SYCL headers and SYCL FE,
5+
// i.e. to make sure that setting properties related to virtual functions will
6+
// result in the right LLVM IR.
7+
//
8+
// This test is specifically focused on the calls_indirectly property.
9+
//
10+
// CHECK: define {{.*}}KEmpty{{.*}} #[[#ATTR_SET_DEFAULT:]]
11+
// CHECK: define {{.*}}KInt{{.*}} #[[#ATTR_SET_INT:]]
12+
// CHECK: define {{.*}}KVoid{{.*}} #[[#ATTR_SET_DEFAULT]]
13+
// CHECK: define {{.*}}KUserDefined{{.*}} #[[#ATTR_SET_USER_DEFINED:]]
14+
// TODO: update the check below
15+
// As of now calls_indirectly_property takes into account only the first
16+
// template argument ignoring the rest. This will be fixed in a follow-up
17+
// patches and the test should be updated to reflect that, because current
18+
// behavior is not correct.
19+
// CHECK: define {{.*}}KMultiple{{.*}} #[[#ATTR_SET_INT]]
20+
//
21+
// CHECK-DAG: attributes #[[#ATTR_SET_DEFAULT]] {{.*}} "calls-indirectly"="_ZTSv"
22+
// CHECK-DAG: attributes #[[#ATTR_SET_INT]] {{.*}} "calls-indirectly"="_ZTSi"
23+
// CHECK-DAG: attributes #[[#ATTR_SET_USER_DEFINED]] {{.*}} "calls-indirectly"="_ZTS12user_defined"
24+
25+
#include <sycl/sycl.hpp>
26+
27+
namespace oneapi = sycl::ext::oneapi::experimental;
28+
29+
struct user_defined {
30+
int a;
31+
float b;
32+
};
33+
34+
class KEmpty;
35+
class KInt;
36+
class KVoid;
37+
class KUserDefined;
38+
class KMultiple;
39+
40+
int main() {
41+
sycl::queue q;
42+
43+
oneapi::properties props_empty{oneapi::calls_indirectly<>};
44+
oneapi::properties props_int{oneapi::calls_indirectly<int>};
45+
oneapi::properties props_void{oneapi::calls_indirectly<void>};
46+
oneapi::properties props_user_defined{oneapi::calls_indirectly<user_defined>};
47+
oneapi::properties props_multiple{
48+
oneapi::calls_indirectly<int, user_defined>};
49+
50+
q.single_task<KEmpty>(props_empty, [=]() {});
51+
q.single_task<KInt>(props_int, [=]() {});
52+
q.single_task<KVoid>(props_void, [=]() {});
53+
q.single_task<KUserDefined>(props_user_defined, [=]() {});
54+
q.single_task<KMultiple>(props_multiple, [=]() {});
55+
56+
return 0;
57+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// RUN: %clangxx -fsycl -fsycl-device-only -emit-llvm -S -Xclang -fsycl-allow-virtual-functions %s -o %t.ll
2+
// RUN: FileCheck %s < %t.ll
3+
//
4+
// This test is intended to check integration between SYCL headers and SYCL FE,
5+
// i.e. to make sure that setting properties related to virtual functions will
6+
// result in the right LLVM IR.
7+
//
8+
// This test is specifically focused on the indirectly_callable property.
9+
//
10+
// CHECK: define {{.*}} @_ZN4Base3fooEv{{.*}} #[[#ATTR_SET_DEFAULT:]]
11+
// CHECK: define {{.*}} @_ZN7Derived3fooEv{{.*}} #[[#ATTR_SET_DEFAULT]]
12+
// CHECK: define {{.*}} @_ZN7Derived3barEv{{.*}} #[[#ATTR_SET_DEFAULT]]
13+
// CHECK: define {{.*}} @_ZN10SubDerived3barEv{{.*}} #[[#ATTR_SET_INT:]]
14+
// CHECK: define {{.*}} @_ZN13SubSubDerived3foo{{.*}} #[[#ATTR_SET_DEFAULT]]
15+
// CHECK: define {{.*}} @_ZN13SubSubDerived3barEv{{.*}} #[[#ATTR_SET_BASE:]]
16+
//
17+
// CHECK-DAG: attributes #[[#ATTR_SET_DEFAULT]] {{.*}} "indirectly-callable"="_ZTSv"
18+
// CHECK-DAG: attributes #[[#ATTR_SET_INT]] {{.*}} "indirectly-callable"="_ZTSi"
19+
// CHECK-DAG: attributes #[[#ATTR_SET_BASE]] {{.*}} "indirectly-callable"="_ZTS4Base"
20+
21+
#include <sycl/sycl.hpp>
22+
23+
namespace oneapi = sycl::ext::oneapi::experimental;
24+
25+
class Base {
26+
public:
27+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(oneapi::indirectly_callable<>)
28+
virtual int foo();
29+
};
30+
31+
int Base::foo() { return 42; }
32+
33+
class Derived : public Base {
34+
public:
35+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(oneapi::indirectly_callable<void>)
36+
virtual int bar();
37+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(oneapi::indirectly_callable<>)
38+
int foo() override;
39+
};
40+
41+
int Derived::foo() { return 43; }
42+
43+
int Derived::bar() { return 0; }
44+
45+
class SubDerived : public Derived {
46+
public:
47+
int foo() override { return 44; }
48+
49+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(oneapi::indirectly_callable<int>)
50+
int bar() override;
51+
};
52+
53+
int SubDerived::bar() { return 1; }
54+
55+
class SubSubDerived : public SubDerived {
56+
public:
57+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(oneapi::indirectly_callable<>)
58+
int foo() override;
59+
60+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(oneapi::indirectly_callable<Base>)
61+
int bar() override;
62+
};
63+
64+
int SubSubDerived::foo() { return 45; }
65+
66+
int SubSubDerived::bar() { return 2; }
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %clangxx %fsycl-host-only -fsyntax-only -Xclang -verify -Xclang -verify-ignore-unexpected=note,warning %s
2+
3+
#include <sycl/sycl.hpp>
4+
5+
namespace oneapi = sycl::ext::oneapi::experimental;
6+
7+
struct user_defined {
8+
int a;
9+
float b;
10+
};
11+
12+
int main() {
13+
sycl::queue q;
14+
15+
oneapi::properties props_empty{oneapi::indirectly_callable<>};
16+
oneapi::properties props_void{oneapi::indirectly_callable<void>};
17+
oneapi::properties props_int{oneapi::indirectly_callable<int>};
18+
oneapi::properties props_user{oneapi::indirectly_callable<user_defined>};
19+
20+
// expected-error-re@sycl/handler.hpp:* {{static assertion failed due to requirement {{.*}} indirectly_callable property cannot be applied to SYCL kernels}}
21+
q.single_task(props_empty, [=]() {});
22+
// expected-error-re@sycl/handler.hpp:* {{static assertion failed due to requirement {{.*}} indirectly_callable property cannot be applied to SYCL kernels}}
23+
q.single_task(props_void, [=]() {});
24+
// expected-error-re@sycl/handler.hpp:* {{static assertion failed due to requirement {{.*}} indirectly_callable property cannot be applied to SYCL kernels}}
25+
q.single_task(props_int, [=]() {});
26+
// expected-error-re@sycl/handler.hpp:* {{static assertion failed due to requirement {{.*}} indirectly_callable property cannot be applied to SYCL kernels}}
27+
q.single_task(props_user, [=]() {});
28+
29+
return 0;
30+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// RUN: %clangxx -fsycl -fsyntax-only -Xclang -verify %s
2+
//
3+
// This test is intended to check that we can successfully compile code that
4+
// uses new properties from the virtual functions extension.
5+
//
6+
// expected-no-diagnostics
7+
8+
#include <sycl/sycl.hpp>
9+
10+
namespace oneapi = sycl::ext::oneapi::experimental;
11+
12+
class Base {
13+
public:
14+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(oneapi::indirectly_callable<>)
15+
virtual void foo() {}
16+
};
17+
18+
class Derived : public Base {
19+
public:
20+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(oneapi::indirectly_callable<>)
21+
void foo() override {}
22+
23+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(oneapi::indirectly_callable<void>)
24+
virtual void bar() {}
25+
};
26+
27+
class SubDerived : public Derived {
28+
public:
29+
void foo() override {}
30+
31+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(oneapi::indirectly_callable<int>)
32+
void bar() override {}
33+
};
34+
35+
class SubSubDerived : public SubDerived {
36+
public:
37+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(oneapi::indirectly_callable<>)
38+
void foo() override {}
39+
40+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(oneapi::indirectly_callable<Base>)
41+
void bar() override {}
42+
};
43+
44+
int main() {
45+
sycl::queue q;
46+
47+
static_assert(
48+
oneapi::is_property_key<oneapi::indirectly_callable_key>::value);
49+
static_assert(oneapi::is_property_key<oneapi::calls_indirectly_key>::value);
50+
51+
oneapi::properties props_empty{oneapi::calls_indirectly<>};
52+
oneapi::properties props_void{oneapi::calls_indirectly<void>};
53+
oneapi::properties props_int{oneapi::calls_indirectly<int>};
54+
oneapi::properties props_base{oneapi::calls_indirectly<Base>};
55+
oneapi::properties props_multiple{oneapi::calls_indirectly<int, Base>};
56+
57+
q.single_task(props_empty, [=]() {});
58+
q.single_task(props_void, [=]() {});
59+
q.single_task(props_int, [=]() {});
60+
q.single_task(props_base, [=]() {});
61+
q.single_task(props_multiple, [=]() {});
62+
63+
return 0;
64+
}

0 commit comments

Comments
 (0)