Skip to content

Commit 6741147

Browse files
authored
[SYCL] Fix build options merge in program manager (#3849)
The program manager gets build options from several sources including device code image, SYCL API and environment variables. Make sure that options are space separated.
1 parent ba0da8b commit 6741147

File tree

4 files changed

+352
-67
lines changed

4 files changed

+352
-67
lines changed

sycl/source/detail/program_manager/program_manager.cpp

Lines changed: 56 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,54 @@ RT::PiProgram ProgramManager::createPIProgram(const RTDeviceBinaryImage &Img,
347347

348348
return Res;
349349
}
350+
static void applyOptionsFromImage(std::string &CompileOpts,
351+
std::string &LinkOpts,
352+
const RTDeviceBinaryImage &Img) {
353+
// Build options are overridden if environment variables are present.
354+
// Environment variables are not changed during program lifecycle so it
355+
// is reasonable to use static here to read them only once.
356+
static const char *CompileOptsEnv =
357+
SYCLConfig<SYCL_PROGRAM_COMPILE_OPTIONS>::get();
358+
static const char *LinkOptsEnv = SYCLConfig<SYCL_PROGRAM_LINK_OPTIONS>::get();
359+
// Update only if compile options are not overwritten by environment
360+
// variable
361+
if (!CompileOptsEnv) {
362+
if (!CompileOpts.empty())
363+
CompileOpts += " ";
364+
CompileOpts += Img.getCompileOptions();
365+
}
366+
367+
// The -vc-codegen option is always preserved for ESIMD kernels, regardless
368+
// of the contents SYCL_PROGRAM_COMPILE_OPTIONS environment variable.
369+
pi_device_binary_property isEsimdImage = Img.getProperty("isEsimdImage");
370+
if (isEsimdImage && pi::DeviceBinaryProperty(isEsimdImage).asUint32()) {
371+
if (!CompileOpts.empty())
372+
CompileOpts += " ";
373+
CompileOpts += "-vc-codegen";
374+
}
375+
376+
// Update only if link options are not overwritten by environment variable
377+
if (!LinkOptsEnv)
378+
if (!LinkOpts.empty())
379+
LinkOpts += " ";
380+
LinkOpts += Img.getLinkOptions();
381+
}
382+
383+
static void applyOptionsFromEnvironment(std::string &CompileOpts,
384+
std::string &LinkOpts) {
385+
// Build options are overridden if environment variables are present.
386+
// Environment variables are not changed during program lifecycle so it
387+
// is reasonable to use static here to read them only once.
388+
static const char *CompileOptsEnv =
389+
SYCLConfig<SYCL_PROGRAM_COMPILE_OPTIONS>::get();
390+
if (CompileOptsEnv) {
391+
CompileOpts = CompileOptsEnv;
392+
}
393+
static const char *LinkOptsEnv = SYCLConfig<SYCL_PROGRAM_LINK_OPTIONS>::get();
394+
if (LinkOptsEnv) {
395+
LinkOpts = LinkOptsEnv;
396+
}
397+
}
350398

351399
RT::PiProgram ProgramManager::getBuiltPIProgram(OSModuleHandle M,
352400
const context &Context,
@@ -374,26 +422,12 @@ RT::PiProgram ProgramManager::getBuiltPIProgram(OSModuleHandle M,
374422

375423
std::string CompileOpts;
376424
std::string LinkOpts;
377-
// Build options are overridden if environment variables are present.
378-
// Environment variables are not changed during program lifecycle so it
379-
// is reasonable to use static here to read them only once.
380-
static const char *CompileOptsEnv =
381-
SYCLConfig<SYCL_PROGRAM_COMPILE_OPTIONS>::get();
382-
if (CompileOptsEnv) {
383-
CompileOpts = CompileOptsEnv;
384-
} else { // Use build options only when the environment variable is missed
385-
if (Prg) {
386-
std::string BuildOptions = Prg->get_build_options();
387-
if (!BuildOptions.empty()) {
388-
CompileOpts += " ";
389-
CompileOpts += BuildOptions;
390-
}
391-
}
392-
}
393-
static const char *LinkOptsEnv = SYCLConfig<SYCL_PROGRAM_LINK_OPTIONS>::get();
394-
if (LinkOptsEnv) {
395-
LinkOpts = LinkOptsEnv;
425+
if (Prg) {
426+
CompileOpts = Prg->get_build_options();
396427
}
428+
429+
applyOptionsFromEnvironment(CompileOpts, LinkOpts);
430+
397431
SerializedObj SpecConsts;
398432
if (Prg)
399433
Prg->stableSerializeSpecConstRegistry(SpecConsts);
@@ -402,24 +436,8 @@ RT::PiProgram ProgramManager::getBuiltPIProgram(OSModuleHandle M,
402436
&LinkOpts, &JITCompilationIsRequired, SpecConsts] {
403437
const RTDeviceBinaryImage &Img =
404438
getDeviceImage(M, KSId, Context, Device, JITCompilationIsRequired);
405-
// Update only if compile options are not overwritten by environment
406-
// variable
407-
if (!CompileOptsEnv) {
408-
CompileOpts += Img.getCompileOptions();
409-
}
410-
411-
// The -vc-codegen option is always preserved for ESIMD kernels, regardless
412-
// of the contents SYCL_PROGRAM_COMPILE_OPTIONS environment variable.
413-
pi_device_binary_property isEsimdImage = Img.getProperty("isEsimdImage");
414-
if (isEsimdImage && pi::DeviceBinaryProperty(isEsimdImage).asUint32()) {
415-
if (!CompileOpts.empty())
416-
CompileOpts += " ";
417-
CompileOpts += "-vc-codegen";
418-
}
419439

420-
// Update only if link options are not overwritten by environment variable
421-
if (!LinkOptsEnv)
422-
LinkOpts += Img.getLinkOptions();
440+
applyOptionsFromImage(CompileOpts, LinkOpts, Img);
423441
ContextImplPtr ContextImpl = getSyclObjImpl(Context);
424442
const detail::plugin &Plugin = ContextImpl->getPlugin();
425443
RT::PiProgram NativePrg;
@@ -1518,41 +1536,15 @@ device_image_plain ProgramManager::build(const device_image_plain &DeviceImage,
15181536

15191537
std::string CompileOpts;
15201538
std::string LinkOpts;
1521-
// Build options are overridden if environment variables are present.
1522-
// Environment variables are not changed during program lifecycle so it
1523-
// is reasonable to use static here to read them only once.
1524-
static const char *CompileOptsEnv =
1525-
SYCLConfig<SYCL_PROGRAM_COMPILE_OPTIONS>::get();
1526-
if (CompileOptsEnv)
1527-
CompileOpts = CompileOptsEnv;
1528-
1529-
static const char *LinkOptsEnv = SYCLConfig<SYCL_PROGRAM_LINK_OPTIONS>::get();
1530-
if (LinkOptsEnv) {
1531-
LinkOpts = LinkOptsEnv;
1532-
}
1539+
applyOptionsFromEnvironment(CompileOpts, LinkOpts);
15331540

15341541
const RTDeviceBinaryImage *ImgPtr = InputImpl->get_bin_image_ref();
15351542
const RTDeviceBinaryImage &Img = *ImgPtr;
15361543

15371544
// TODO: Unify this code with getBuiltPIProgram
15381545
auto BuildF = [this, &Context, Img, &Devs, &CompileOpts, &LinkOpts,
15391546
&InputImpl] {
1540-
// Update only if compile options are not overwritten by environment
1541-
// variable
1542-
if (!CompileOptsEnv) {
1543-
CompileOpts += Img.getCompileOptions();
1544-
pi_device_binary_property isEsimdImage = Img.getProperty("isEsimdImage");
1545-
1546-
if (isEsimdImage && pi::DeviceBinaryProperty(isEsimdImage).asUint32()) {
1547-
if (!CompileOpts.empty())
1548-
CompileOpts += " ";
1549-
CompileOpts += "-vc-codegen";
1550-
}
1551-
}
1552-
1553-
// Update only if link options are not overwritten by environment variable
1554-
if (!LinkOptsEnv)
1555-
LinkOpts += Img.getLinkOptions();
1547+
applyOptionsFromImage(CompileOpts, LinkOpts, Img);
15561548
ContextImplPtr ContextImpl = getSyclObjImpl(Context);
15571549
const detail::plugin &Plugin = ContextImpl->getPlugin();
15581550

sycl/unittests/helpers/PiImage.hpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,14 @@ class PiProperty {
5151

5252
private:
5353
void updateNativeType() {
54-
MNative = NativeType{const_cast<char *>(MName.c_str()),
55-
const_cast<char *>(MData.data()), MType, MData.size()};
54+
if (MType == PI_PROPERTY_TYPE_UINT32) {
55+
MNative = NativeType{const_cast<char *>(MName.c_str()), nullptr, MType,
56+
*((uint32_t *)MData.data())};
57+
} else {
58+
MNative =
59+
NativeType{const_cast<char *>(MName.c_str()),
60+
const_cast<char *>(MData.data()), MType, MData.size()};
61+
}
5662
}
5763
std::string MName;
5864
std::vector<char> MData;
@@ -366,6 +372,17 @@ void addSpecConstants(PiArray<PiProperty> SpecConstants,
366372
std::move(DefaultValues));
367373
}
368374

375+
/// Utility function to add ESIMD kernel flag to property set.
376+
void addESIMDFlag(PiPropertySet &Props) {
377+
std::vector<char> ValData(sizeof(uint32_t));
378+
ValData[0] = 1;
379+
PiProperty Prop{"isEsimdImage", ValData, PI_PROPERTY_TYPE_UINT32};
380+
381+
PiArray<PiProperty> Value{std::move(Prop)};
382+
383+
Props.insert(__SYCL_PI_PROPERTY_SET_SYCL_MISC_PROP, std::move(Value));
384+
}
385+
369386
/// Utility function to generate offload entries for kernels without arguments.
370387
PiArray<PiOffloadEntry>
371388
makeEmptyKernels(std::initializer_list<std::string> KernelNames) {

sycl/unittests/misc/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
set(sycl_lib_dir $<TARGET_FILE_DIR:sycl>)
22
add_definitions(-DSYCL_LIB_DIR="${sycl_lib_dir}")
33
add_sycl_unittest(MiscTests SHARED
4-
OsUtils.cpp
54
CircularBuffer.cpp
5+
KernelBuildOptions.cpp
6+
OsUtils.cpp
67
)

0 commit comments

Comments
 (0)