Skip to content

Commit 91eaa05

Browse files
[SYCL][NFCI] Refactor unittest::UrArray (#15604)
This is a first patch in series of detaching unit-test classes from UR names. In a previous attempts to do so (#14815) there were concerns about what to do with `UrArray` and this PR is another attempt (see also #15014) to do that. This PR renames `UrArray` into `LifetimeExtender` to better communicate its purpose: data structures emitted by the compiler (and therefore used by the runtime) to describe device image and their properties do not store data, but only hold pointers to them. Therefore when we mock those in our unit-tests we need to ensure that their lifetime is long enough to cover the whole test. This is a non-functional change by its spirit, but what used to be `UrArray` is now hidden from writers of unit-tests and the interface is switched to `std::vector` - that is done to hide an implementation detail and simplify amount of knowledge required to write unit-tests.
1 parent 4fe6531 commit 91eaa05

18 files changed

+107
-91
lines changed

sycl/unittests/Extensions/DeviceGlobal.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,11 @@ static sycl::unittest::UrImage generateDeviceGlobalImage() {
6565
UrProperty DevGlobInfo =
6666
makeDeviceGlobalInfo(DeviceGlobalName, sizeof(int) * 2, 0);
6767
PropSet.insert(__SYCL_PROPERTY_SET_SYCL_DEVICE_GLOBALS,
68-
UrArray<UrProperty>{std::move(DevGlobInfo)});
68+
std::vector<UrProperty>{std::move(DevGlobInfo)});
6969

7070
std::vector<unsigned char> Bin{10, 11, 12, 13, 14, 15}; // Random data
7171

72-
UrArray<UrOffloadEntry> Entries =
72+
std::vector<UrOffloadEntry> Entries =
7373
makeEmptyKernels({DeviceGlobalTestKernelName});
7474

7575
UrImage Img{SYCL_DEVICE_BINARY_TYPE_SPIRV, // Format
@@ -96,11 +96,11 @@ static sycl::unittest::UrImage generateDeviceGlobalImgScopeImage() {
9696
UrProperty DevGlobInfo =
9797
makeDeviceGlobalInfo(DeviceGlobalImgScopeName, sizeof(int) * 2, 1);
9898
PropSet.insert(__SYCL_PROPERTY_SET_SYCL_DEVICE_GLOBALS,
99-
UrArray<UrProperty>{std::move(DevGlobInfo)});
99+
std::vector<UrProperty>{std::move(DevGlobInfo)});
100100

101101
std::vector<unsigned char> Bin{10, 11, 12, 13, 14, 15}; // Random data
102102

103-
UrArray<UrOffloadEntry> Entries =
103+
std::vector<UrOffloadEntry> Entries =
104104
makeEmptyKernels({DeviceGlobalImgScopeTestKernelName});
105105

106106
UrImage Img{SYCL_DEVICE_BINARY_TYPE_SPIRV, // Format

sycl/unittests/Extensions/USMMemcpy2D.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ static sycl::unittest::UrImage generateMemopsImage() {
132132

133133
std::vector<unsigned char> Bin{10, 11, 12, 13, 14, 15}; // Random data
134134

135-
UrArray<UrOffloadEntry> Entries = makeEmptyKernels(
135+
std::vector<UrOffloadEntry> Entries = makeEmptyKernels(
136136
{USMFillHelperKernelNameLong, USMFillHelperKernelNameChar,
137137
USMMemcpyHelperKernelNameLong, USMMemcpyHelperKernelNameChar});
138138

sycl/unittests/Extensions/VirtualFunctions/RuntimeLinking.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ static sycl::unittest::UrImage
5050
generateImage(std::initializer_list<std::string> KernelNames,
5151
const std::string &VFSets, bool UsesVFSets, unsigned char Magic) {
5252
sycl::unittest::UrPropertySet PropSet;
53-
sycl::unittest::UrArray<sycl::unittest::UrProperty> Props;
53+
std::vector<sycl::unittest::UrProperty> Props;
5454
uint64_t PropSize = VFSets.size();
5555
std::vector<char> Storage(/* bytes for size */ 8 + PropSize +
5656
/* null terminator */ 1);
@@ -69,7 +69,7 @@ generateImage(std::initializer_list<std::string> KernelNames,
6969

7070
std::vector<unsigned char> Bin{Magic};
7171

72-
sycl::unittest::UrArray<sycl::unittest::UrOffloadEntry> Entries =
72+
std::vector<sycl::unittest::UrOffloadEntry> Entries =
7373
sycl::unittest::makeEmptyKernels(KernelNames);
7474

7575
sycl::unittest::UrImage Img{

sycl/unittests/SYCL2020/IsCompatible.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ generateDefaultImage(std::initializer_list<std::string> KernelNames,
3232

3333
std::vector<unsigned char> Bin{0, 1, 2, 3, 4, 5}; // Random data
3434

35-
UrArray<UrOffloadEntry> Entries = makeEmptyKernels(KernelNames);
35+
std::vector<UrOffloadEntry> Entries = makeEmptyKernels(KernelNames);
3636

3737
UrImage Img{SYCL_DEVICE_BINARY_TYPE_SPIRV, // Format
3838
__SYCL_DEVICE_BINARY_TARGET_SPIRV64, // DeviceTargetSpec

sycl/unittests/SYCL2020/KernelBundle.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ generateDefaultImage(std::initializer_list<std::string> KernelNames,
3737

3838
std::vector<unsigned char> Bin{0, 1, 2, 3, 4, 5}; // Random data
3939

40-
UrArray<UrOffloadEntry> Entries = makeEmptyKernels(KernelNames);
40+
std::vector<UrOffloadEntry> Entries = makeEmptyKernels(KernelNames);
4141

4242
UrImage Img{BinaryType, // Format
4343
DeviceTargetSpec,

sycl/unittests/SYCL2020/KernelBundleStateFiltering.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ generateDefaultImage(std::initializer_list<std::string> KernelNames,
4646
static unsigned char NImage = 0;
4747
std::vector<unsigned char> Bin{NImage++};
4848

49-
UrArray<UrOffloadEntry> Entries = makeEmptyKernels(KernelNames);
49+
std::vector<UrOffloadEntry> Entries = makeEmptyKernels(KernelNames);
5050

5151
UrImage Img{BinaryType, // Format
5252
DeviceTargetSpec,

sycl/unittests/SYCL2020/KernelID.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ generateDefaultImage(std::initializer_list<std::string> Kernels) {
5555

5656
std::vector<unsigned char> Bin{0, 1, 2, 3, 4, 5}; // Random data
5757

58-
UrArray<UrOffloadEntry> Entries = makeEmptyKernels(Kernels);
58+
std::vector<UrOffloadEntry> Entries = makeEmptyKernels(Kernels);
5959

6060
UrImage Img{SYCL_DEVICE_BINARY_TYPE_SPIRV, // Format
6161
__SYCL_DEVICE_BINARY_TARGET_SPIRV64, // DeviceTargetSpec

sycl/unittests/SYCL2020/SpecializationConstant.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ static sycl::unittest::UrImage generateImageWithSpecConsts() {
4949

5050
std::vector<unsigned char> Bin{0, 1, 2, 3, 4, 5}; // Random data
5151

52-
UrArray<UrOffloadEntry> Entries =
52+
std::vector<UrOffloadEntry> Entries =
5353
makeEmptyKernels({"SpecializationConstant_TestKernel"});
5454
UrImage Img{SYCL_DEVICE_BINARY_TYPE_SPIRV, // Format
5555
__SYCL_DEVICE_BINARY_TARGET_SPIRV64, // DeviceTargetSpec

sycl/unittests/assert/assert.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ static sycl::unittest::UrImage generateDefaultImage() {
8686

8787
std::vector<unsigned char> Bin{0, 1, 2, 3, 4, 5}; // Random data
8888

89-
UrArray<UrOffloadEntry> Entries = makeEmptyKernels({KernelName});
89+
std::vector<UrOffloadEntry> Entries = makeEmptyKernels({KernelName});
9090

9191
UrImage Img{SYCL_DEVICE_BINARY_TYPE_SPIRV, // Format
9292
__SYCL_DEVICE_BINARY_TARGET_SPIRV64, // DeviceTargetSpec
@@ -109,7 +109,7 @@ static sycl::unittest::UrImage generateCopierKernelImage() {
109109

110110
std::vector<unsigned char> Bin{10, 11, 12, 13, 14, 15}; // Random data
111111

112-
UrArray<UrOffloadEntry> Entries = makeEmptyKernels({CopierKernelName});
112+
std::vector<UrOffloadEntry> Entries = makeEmptyKernels({CopierKernelName});
113113

114114
UrImage Img{SYCL_DEVICE_BINARY_TYPE_SPIRV, // Format
115115
__SYCL_DEVICE_BINARY_TARGET_SPIRV64, // DeviceTargetSpec

sycl/unittests/helpers/UrImage.hpp

Lines changed: 75 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -109,62 +109,49 @@ class UrOffloadEntry {
109109
NativeType MNative;
110110
};
111111

112-
/// Generic array of UR entries.
113-
template <typename T> class UrArray {
112+
namespace internal {
113+
// Content from this namespace shouldn't be used anywhere outside of this file
114+
115+
/// "native" data structures used by SYCL RT do not hold the data, but only
116+
/// point to it. The data itself is embedded into the binary data sections in
117+
/// real applications.
118+
/// In unit-tests we mock those data structures and therefore we need to ensure
119+
/// that the lifetime of the underlying data is correct and we won't perform
120+
/// any illegal memory accesses in unit-tests.
121+
template <typename T> class LifetimeExtender {
114122
public:
115-
explicit UrArray(std::vector<T> Entries) : MMockEntries(std::move(Entries)) {
116-
updateEntries();
117-
}
118-
119-
UrArray(std::initializer_list<T> Entries) : MMockEntries(std::move(Entries)) {
120-
updateEntries();
123+
explicit LifetimeExtender(std::vector<T> Entries)
124+
: MMockEntries(std::move(Entries)) {
125+
MEntries.clear();
126+
std::transform(MMockEntries.begin(), MMockEntries.end(),
127+
std::back_inserter(MEntries),
128+
[](const T &Entry) { return Entry.convertToNativeType(); });
121129
}
122130

123-
UrArray() = default;
124-
125-
void push_back(const T &Entry) {
126-
MMockEntries.push_back(Entry);
127-
MEntriesNeedUpdate = true;
128-
}
131+
LifetimeExtender() = default;
129132

130133
typename T::NativeType *begin() {
131-
if (MEntriesNeedUpdate) {
132-
updateEntries();
133-
}
134-
135134
if (MEntries.empty())
136135
return nullptr;
137136

138137
return &*MEntries.begin();
139138
}
140139
typename T::NativeType *end() {
141-
if (MEntriesNeedUpdate) {
142-
updateEntries();
143-
}
144-
145140
if (MEntries.empty())
146141
return nullptr;
147142

148143
return &*MEntries.rbegin() + 1;
149144
}
150145

151146
private:
152-
void updateEntries() {
153-
MEntries.clear();
154-
std::transform(MMockEntries.begin(), MMockEntries.end(),
155-
std::back_inserter(MEntries),
156-
[](const T &Entry) { return Entry.convertToNativeType(); });
157-
}
158147
std::vector<T> MMockEntries;
159148
std::vector<typename T::NativeType> MEntries;
160-
bool MEntriesNeedUpdate = false;
161149
};
162150

163151
#ifdef __cpp_deduction_guides
164-
template <typename T> UrArray(std::vector<T>) -> UrArray<T>;
165-
166-
template <typename T> UrArray(std::initializer_list<T>) -> UrArray<T>;
152+
template <typename T> LifetimeExtender(std::vector<T>) -> LifetimeExtender<T>;
167153
#endif // __cpp_deduction_guides
154+
} // namespace internal
168155

169156
/// Convenience wrapper for sycl_device_binary_property_set.
170157
class UrPropertySet {
@@ -187,19 +174,23 @@ class UrPropertySet {
187174
// Value must be an all-zero 32-bit mask, which would mean that no fallback
188175
// libraries are needed to be loaded.
189176
UrProperty DeviceLibReqMask("", Data, SYCL_PROPERTY_TYPE_UINT32);
190-
insert(__SYCL_PROPERTY_SET_DEVICELIB_REQ_MASK, UrArray{DeviceLibReqMask});
177+
insert(__SYCL_PROPERTY_SET_DEVICELIB_REQ_MASK, std::move(DeviceLibReqMask));
178+
}
179+
180+
/// Adds a new property to the set.
181+
///
182+
/// \param Name is a property name. See ur.hpp for list of known names.
183+
/// \param Prop is a property value.
184+
void insert(const std::string &Name, UrProperty &&Props) {
185+
insert(Name, internal::LifetimeExtender{std::vector{std::move(Props)}});
191186
}
192187

193188
/// Adds a new array of properties to the set.
194189
///
195190
/// \param Name is a property array name. See ur.hpp for list of known names.
196191
/// \param Props is an array of property values.
197-
void insert(const std::string &Name, UrArray<UrProperty> Props) {
198-
MNames.push_back(Name);
199-
MMockProperties.push_back(std::move(Props));
200-
MProperties.push_back(_sycl_device_binary_property_set_struct{
201-
MNames.back().data(), MMockProperties.back().begin(),
202-
MMockProperties.back().end()});
192+
void insert(const std::string &Name, std::vector<UrProperty> &&Props) {
193+
insert(Name, internal::LifetimeExtender{std::move(Props)});
203194
}
204195

205196
_sycl_device_binary_property_set_struct *begin() {
@@ -215,36 +206,65 @@ class UrPropertySet {
215206
}
216207

217208
private:
209+
/// Adds a new array of properties to the set.
210+
///
211+
/// \param Name is a property array name. See ur.hpp for list of known names.
212+
/// \param Props is an array of property values.
213+
void insert(const std::string &Name,
214+
internal::LifetimeExtender<UrProperty> Props) {
215+
MNames.push_back(Name);
216+
MMockProperties.push_back(std::move(Props));
217+
MProperties.push_back(_sycl_device_binary_property_set_struct{
218+
MNames.back().data(), MMockProperties.back().begin(),
219+
MMockProperties.back().end()});
220+
}
221+
218222
std::vector<std::string> MNames;
219-
std::vector<UrArray<UrProperty>> MMockProperties;
223+
std::vector<internal::LifetimeExtender<UrProperty>> MMockProperties;
220224
std::vector<_sycl_device_binary_property_set_struct> MProperties;
221225
};
222226

223227
/// Convenience wrapper around UR internal structures, that manages UR binary
224228
/// image data lifecycle.
225229
class UrImage {
226-
public:
230+
private:
227231
/// Constructs an arbitrary device image.
228232
UrImage(uint16_t Version, uint8_t Kind, uint8_t Format,
229233
const std::string &DeviceTargetSpec,
230234
const std::string &CompileOptions, const std::string &LinkOptions,
231-
std::vector<char> Manifest, std::vector<unsigned char> Binary,
232-
UrArray<UrOffloadEntry> OffloadEntries, UrPropertySet PropertySet)
235+
std::vector<char> &&Manifest, std::vector<unsigned char> &&Binary,
236+
internal::LifetimeExtender<UrOffloadEntry> OffloadEntries,
237+
UrPropertySet PropertySet)
233238
: MVersion(Version), MKind(Kind), MFormat(Format),
234239
MDeviceTargetSpec(DeviceTargetSpec), MCompileOptions(CompileOptions),
235240
MLinkOptions(LinkOptions), MManifest(std::move(Manifest)),
236241
MBinary(std::move(Binary)), MOffloadEntries(std::move(OffloadEntries)),
237242
MPropertySet(std::move(PropertySet)) {}
238243

244+
public:
245+
/// Constructs an arbitrary device image.
246+
UrImage(uint16_t Version, uint8_t Kind, uint8_t Format,
247+
const std::string &DeviceTargetSpec,
248+
const std::string &CompileOptions, const std::string &LinkOptions,
249+
std::vector<char> &&Manifest, std::vector<unsigned char> &&Binary,
250+
std::vector<UrOffloadEntry> &&OffloadEntries,
251+
UrPropertySet PropertySet)
252+
: UrImage(Version, Kind, Format, DeviceTargetSpec, CompileOptions,
253+
LinkOptions, std::move(Manifest), std::move(Binary),
254+
internal::LifetimeExtender(std::move(OffloadEntries)),
255+
std::move(PropertySet)) {}
256+
239257
/// Constructs a SYCL device image of the latest version.
240258
UrImage(uint8_t Format, const std::string &DeviceTargetSpec,
241259
const std::string &CompileOptions, const std::string &LinkOptions,
242-
std::vector<unsigned char> Binary,
243-
UrArray<UrOffloadEntry> OffloadEntries, UrPropertySet PropertySet)
260+
std::vector<unsigned char> &&Binary,
261+
std::vector<UrOffloadEntry> &&OffloadEntries,
262+
UrPropertySet PropertySet)
244263
: UrImage(SYCL_DEVICE_BINARY_VERSION,
245264
SYCL_DEVICE_BINARY_OFFLOAD_KIND_SYCL, Format, DeviceTargetSpec,
246265
CompileOptions, LinkOptions, {}, std::move(Binary),
247-
std::move(OffloadEntries), std::move(PropertySet)) {}
266+
internal::LifetimeExtender(std::move(OffloadEntries)),
267+
std::move(PropertySet)) {}
248268

249269
sycl_device_binary_struct convertToNativeType() {
250270
return sycl_device_binary_struct{
@@ -275,7 +295,7 @@ class UrImage {
275295
std::string MLinkOptions;
276296
std::vector<char> MManifest;
277297
std::vector<unsigned char> MBinary;
278-
UrArray<UrOffloadEntry> MOffloadEntries;
298+
internal::LifetimeExtender<UrOffloadEntry> MOffloadEntries;
279299
UrPropertySet MPropertySet;
280300
};
281301

@@ -392,7 +412,7 @@ inline UrProperty makeSpecConstant(std::vector<char> &ValData,
392412
/// Utility function to mark kernel as the one using assert
393413
inline void setKernelUsesAssert(const std::vector<std::string> &Names,
394414
UrPropertySet &Set) {
395-
UrArray<UrProperty> Value;
415+
std::vector<UrProperty> Value;
396416
for (const std::string &N : Names)
397417
Value.push_back({N, {0, 0, 0, 0}, SYCL_PROPERTY_TYPE_UINT32});
398418
Set.insert(__SYCL_PROPERTY_SET_SYCL_ASSERT_USED, std::move(Value));
@@ -401,16 +421,14 @@ inline void setKernelUsesAssert(const std::vector<std::string> &Names,
401421
/// Utility function to add specialization constants to property set.
402422
///
403423
/// This function overrides the default spec constant values.
404-
inline void addSpecConstants(UrArray<UrProperty> SpecConstants,
424+
inline void addSpecConstants(std::vector<UrProperty> &&SpecConstants,
405425
std::vector<char> ValData, UrPropertySet &Props) {
406426
Props.insert(__SYCL_PROPERTY_SET_SPEC_CONST_MAP, std::move(SpecConstants));
407427

408428
UrProperty Prop{"all", std::move(ValData), SYCL_PROPERTY_TYPE_BYTE_ARRAY};
409429

410-
UrArray<UrProperty> DefaultValues{std::move(Prop)};
411-
412430
Props.insert(__SYCL_PROPERTY_SET_SPEC_CONST_DEFAULT_VALUES_MAP,
413-
std::move(DefaultValues));
431+
std::move(Prop));
414432
}
415433

416434
/// Utility function to add ESIMD kernel flag to property set.
@@ -419,15 +437,13 @@ inline void addESIMDFlag(UrPropertySet &Props) {
419437
ValData[0] = 1;
420438
UrProperty Prop{"isEsimdImage", ValData, SYCL_PROPERTY_TYPE_UINT32};
421439

422-
UrArray<UrProperty> Value{std::move(Prop)};
423-
424-
Props.insert(__SYCL_PROPERTY_SET_SYCL_MISC_PROP, std::move(Value));
440+
Props.insert(__SYCL_PROPERTY_SET_SYCL_MISC_PROP, std::move(Prop));
425441
}
426442

427443
/// Utility function to generate offload entries for kernels without arguments.
428-
inline UrArray<UrOffloadEntry>
444+
inline std::vector<UrOffloadEntry>
429445
makeEmptyKernels(std::initializer_list<std::string> KernelNames) {
430-
UrArray<UrOffloadEntry> Entries;
446+
std::vector<UrOffloadEntry> Entries;
431447

432448
for (const auto &Name : KernelNames) {
433449
UrOffloadEntry E{Name, {}, 0};
@@ -531,7 +547,7 @@ inline void
531547
addDeviceRequirementsProps(UrPropertySet &Props,
532548
const std::vector<sycl::aspect> &Aspects,
533549
const std::vector<int> &ReqdWGSize = {}) {
534-
UrArray<UrProperty> Value{makeAspectsProp(Aspects)};
550+
std::vector<UrProperty> Value{makeAspectsProp(Aspects)};
535551
if (!ReqdWGSize.empty())
536552
Value.push_back(makeReqdWGSizeProp(ReqdWGSize));
537553
Props.insert(__SYCL_PROPERTY_SET_SYCL_DEVICE_REQUIREMENTS, std::move(Value));
@@ -550,7 +566,7 @@ generateDefaultImage(std::initializer_list<std::string> KernelNames) {
550566
std::vector<unsigned char> Bin(Combined.begin(), Combined.end());
551567
Bin.push_back(0);
552568

553-
UrArray<UrOffloadEntry> Entries = makeEmptyKernels(KernelNames);
569+
std::vector<UrOffloadEntry> Entries = makeEmptyKernels(KernelNames);
554570

555571
UrImage Img{SYCL_DEVICE_BINARY_TYPE_SPIRV, // Format
556572
__SYCL_DEVICE_BINARY_TARGET_SPIRV64, // DeviceTargetSpec

sycl/unittests/kernel-and-program/Cache.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ static sycl::unittest::UrImage generateDefaultImage() {
6161

6262
std::vector<unsigned char> Bin{0, 1, 2, 3, 4, 5}; // Random data
6363

64-
UrArray<UrOffloadEntry> Entries =
64+
std::vector<UrOffloadEntry> Entries =
6565
makeEmptyKernels({"CacheTestKernel", "CacheTestKernel2"});
6666

6767
UrImage Img{SYCL_DEVICE_BINARY_TYPE_SPIRV, // Format

sycl/unittests/kernel-and-program/KernelBuildOptions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ static sycl::unittest::UrImage generateDefaultImage() {
7878
addESIMDFlag(PropSet);
7979
std::vector<unsigned char> Bin{0, 1, 2, 3, 4, 5}; // Random data
8080

81-
UrArray<UrOffloadEntry> Entries = makeEmptyKernels({"BuildOptsTestKernel"});
81+
std::vector<UrOffloadEntry> Entries = makeEmptyKernels({"BuildOptsTestKernel"});
8282

8383
UrImage Img{SYCL_DEVICE_BINARY_TYPE_SPIRV, // Format
8484
__SYCL_DEVICE_BINARY_TARGET_SPIRV64, // DeviceTargetSpec

0 commit comments

Comments
 (0)