Skip to content

Commit acf1abb

Browse files
authored
[SYCL] Update calls_indirectly property (#15523)
This allows calls_indirectly property to handle all passed template arguments, but not the only first one. Also applying some minor changes to the spec. Spec & Design: #10540
1 parent a04915e commit acf1abb

File tree

4 files changed

+74
-33
lines changed

4 files changed

+74
-33
lines changed

sycl/include/sycl/ext/oneapi/experimental/virtual_functions.hpp

+52-11
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,16 @@ template <typename Set>
1919
inline constexpr indirectly_callable_key::value_t<Set> indirectly_callable_in;
2020

2121
struct calls_indirectly_key {
22-
template <typename First = void, typename... SetIds>
22+
template <typename... SetIds>
2323
using value_t =
2424
sycl::ext::oneapi::experimental::property_value<calls_indirectly_key,
25-
First, SetIds...>;
25+
SetIds...>;
2626
};
2727

2828
inline constexpr calls_indirectly_key::value_t<void> assume_indirect_calls;
2929

30-
template <typename First, typename... Rest>
31-
inline constexpr calls_indirectly_key::value_t<First, Rest...>
30+
template <typename... SetIds>
31+
inline constexpr calls_indirectly_key::value_t<SetIds...>
3232
assume_indirect_calls_to;
3333

3434
template <> struct is_property_key<indirectly_callable_key> : std::true_type {};
@@ -60,16 +60,57 @@ struct PropertyMetaInfo<indirectly_callable_key::value_t<Set>> {
6060
#endif
6161
};
6262

63-
template <typename First, typename... Rest>
64-
struct PropertyMetaInfo<calls_indirectly_key::value_t<First, Rest...>> {
65-
static_assert(
66-
sizeof...(Rest) == 0,
67-
"assume_indirect_calls_to property only supports a single set for now");
63+
#ifdef __SYCL_DEVICE_ONLY__
64+
// Helper to concatenate several lists of characters into a single string.
65+
// Lists are separated from each other with comma within the resulting string.
66+
template <typename List, typename... Rest> struct ConcatenateCharsToStr;
67+
68+
// Specialization for a single list
69+
template <char... Chars> struct ConcatenateCharsToStr<CharList<Chars...>> {
70+
static constexpr char value[] = {Chars..., '\0'};
71+
};
72+
73+
// Specialization for two lists
74+
template <char... Chars, char... CharsToAppend>
75+
struct ConcatenateCharsToStr<CharList<Chars...>, CharList<CharsToAppend...>>
76+
: ConcatenateCharsToStr<CharList<Chars..., ',', CharsToAppend...>> {};
77+
78+
// Specialization for the case when there are more than two lists
79+
template <char... Chars, char... CharsToAppend, typename... Rest>
80+
struct ConcatenateCharsToStr<CharList<Chars...>, CharList<CharsToAppend...>,
81+
Rest...>
82+
: ConcatenateCharsToStr<CharList<Chars..., ',', CharsToAppend...>,
83+
Rest...> {};
84+
85+
// Helper to convert type T to a list of characters representing the type (its
86+
// mangled name).
87+
template <typename T, size_t... Indices> struct StableNameToCharsHelper {
88+
using chars = CharList<__builtin_sycl_unique_stable_name(T)[Indices]...>;
89+
};
90+
91+
// Wrapper helper for the struct above
92+
template <typename T, typename Sequence> struct StableNameToChars;
93+
94+
// Specialization of that wrapper helper which accepts sequence of integers
95+
template <typename T, size_t... Indices>
96+
struct StableNameToChars<T, std::integer_sequence<size_t, Indices...>>
97+
: StableNameToCharsHelper<T, Indices...> {};
98+
99+
// Creates a comma-separated string with unique stable names for each type in
100+
// Ts.
101+
template <typename... Ts>
102+
struct UniqueStableNameListStr
103+
: ConcatenateCharsToStr<typename StableNameToChars<
104+
Ts, std::make_index_sequence<__builtin_strlen(
105+
__builtin_sycl_unique_stable_name(Ts))>>::chars...> {};
106+
#endif // __SYCL_DEVICE_ONLY__
107+
108+
template <typename... SetIds>
109+
struct PropertyMetaInfo<calls_indirectly_key::value_t<SetIds...>> {
68110
static constexpr const char *name = "calls-indirectly";
69111
static constexpr const char *value =
70112
#ifdef __SYCL_DEVICE_ONLY__
71-
// FIXME: we should handle Rest... here as well
72-
__builtin_sycl_unique_stable_name(First);
113+
UniqueStableNameListStr<SetIds...>::value;
73114
#else
74115
"";
75116
#endif

sycl/test-e2e/VirtualFunctions/2/2/single-construct-single-use.cpp

+14-4
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,18 @@ class IncrementBy8 : public BaseIncrement {
5151
void increment(int *Data) override { *Data += 8 + Mod; }
5252
};
5353

54+
struct SetIncBy16;
55+
class IncrementBy16 : public BaseIncrement {
56+
public:
57+
IncrementBy16(int Mod, int /* unused */) : BaseIncrement(Mod) {}
58+
59+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(oneapi::indirectly_callable_in<SetIncBy16>)
60+
void increment(int *Data) override { *Data += 16 + Mod; }
61+
};
62+
5463
int main() try {
55-
using storage_t =
56-
obj_storage_t<BaseIncrement, IncrementBy2, IncrementBy4, IncrementBy8>;
64+
using storage_t = obj_storage_t<BaseIncrement, IncrementBy2, IncrementBy4,
65+
IncrementBy8, IncrementBy16>;
5766

5867
storage_t HostStorage;
5968
sycl::buffer<storage_t> DeviceStorage(sycl::range{1});
@@ -66,8 +75,9 @@ int main() try {
6675
sycl::queue q(asyncHandler);
6776

6877
// TODO: cover uses case when objects are passed through USM
69-
constexpr oneapi::properties props{oneapi::assume_indirect_calls};
70-
for (unsigned TestCase = 0; TestCase < 4; ++TestCase) {
78+
constexpr oneapi::properties props{
79+
oneapi::assume_indirect_calls_to<void, SetIncBy16>};
80+
for (unsigned TestCase = 0; TestCase < 5; ++TestCase) {
7181
int HostData = 42;
7282
int Data = HostData;
7383
sycl::buffer<int> DataStorage(&Data, sycl::range{1});

sycl/test/virtual-functions/calls-indirectly-ir.cpp

+5-12
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,12 @@
1111
// CHECK: define {{.*}}KInt{{.*}} #[[#ATTR_SET_INT:]]
1212
// CHECK: define {{.*}}KVoid{{.*}} #[[#ATTR_SET_DEFAULT]]
1313
// 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-disabled: define {{.*}}KMultiple{{.*}} #[[#ATTR_SET_INT]]
14+
// CHECK: define {{.*}}KMultiple{{.*}} #[[#ATTR_SET_MULTIPLE:]]
2015
//
2116
// CHECK-DAG: attributes #[[#ATTR_SET_DEFAULT]] {{.*}} "calls-indirectly"="_ZTSv"
2217
// CHECK-DAG: attributes #[[#ATTR_SET_INT]] {{.*}} "calls-indirectly"="_ZTSi"
2318
// CHECK-DAG: attributes #[[#ATTR_SET_USER_DEFINED]] {{.*}} "calls-indirectly"="_ZTS12user_defined"
19+
// CHECK-DAG: attributes #[[#ATTR_SET_MULTIPLE]] {{.*}} "calls-indirectly"="_ZTSi,_ZTS12user_defined"
2420

2521
#include <sycl/sycl.hpp>
2622

@@ -45,17 +41,14 @@ int main() {
4541
oneapi::properties props_void{oneapi::assume_indirect_calls_to<void>};
4642
oneapi::properties props_user_defined{
4743
oneapi::assume_indirect_calls_to<user_defined>};
48-
// assume_indirect_calls_to is currently limited to a single set, so this test
49-
// is disabled.
50-
// FIXME: re-enable once the restriction is lifted.
51-
// oneapi::properties props_multiple{
52-
// oneapi::assume_indirect_calls_to<int, user_defined>};
44+
oneapi::properties props_multiple{
45+
oneapi::assume_indirect_calls_to<int, user_defined>};
5346

5447
q.single_task<KEmpty>(props_empty, [=]() {});
5548
q.single_task<KInt>(props_int, [=]() {});
5649
q.single_task<KVoid>(props_void, [=]() {});
5750
q.single_task<KUserDefined>(props_user_defined, [=]() {});
58-
// q.single_task<KMultiple>(props_multiple, [=]() {});
51+
q.single_task<KMultiple>(props_multiple, [=]() {});
5952

6053
return 0;
6154
}

sycl/test/virtual-functions/properties-positive.cpp

+3-6
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,14 @@ int main() {
5252
oneapi::properties props_void{oneapi::assume_indirect_calls_to<void>};
5353
oneapi::properties props_int{oneapi::assume_indirect_calls_to<int>};
5454
oneapi::properties props_base{oneapi::assume_indirect_calls_to<Base>};
55-
// assume_indirect_calls_to is currently limited to a single set, so this test
56-
// is disabled.
57-
// FIXME: re-enable once the restriction is lifted.
58-
// oneapi::properties props_multiple{
59-
// oneapi::assume_indirect_calls_to<int, Base>};
55+
oneapi::properties props_multiple{
56+
oneapi::assume_indirect_calls_to<int, Base>};
6057

6158
q.single_task(props_empty, [=]() {});
6259
q.single_task(props_void, [=]() {});
6360
q.single_task(props_int, [=]() {});
6461
q.single_task(props_base, [=]() {});
65-
// q.single_task(props_multiple, [=]() {});
62+
q.single_task(props_multiple, [=]() {});
6663

6764
return 0;
6865
}

0 commit comments

Comments
 (0)