Skip to content

Commit 7dd09d9

Browse files
authored
[SYCL] Add asan AOT libdevice for different GPU/CPU (#15939)
Device address sanitizer libraries can be optimized in AOT compilation mode, some redundant code checking which device current kernel is running on can be removed. This PR creates corresponding AOT address sanitizer device libraries for CPU, PVC, DG2 target and link them according to real AOT target. This PR also renames previous libsycl-sanitizer to libsycl-asan since current device sanitizer only supports address sanitizer and memory sanitizer will be added in the future. --------- Signed-off-by: jinge90 <ge.jin@intel.com>
1 parent 22cb417 commit 7dd09d9

File tree

14 files changed

+460
-85
lines changed

14 files changed

+460
-85
lines changed

clang/lib/Driver/ToolChains/SYCL.cpp

Lines changed: 158 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,84 @@ static bool selectBfloatLibs(const llvm::Triple &Triple, const Compilation &C,
345345
return NeedLibs;
346346
}
347347

348+
struct OclocInfo {
349+
const char *DeviceName;
350+
const char *PackageName;
351+
const char *Version;
352+
SmallVector<int, 8> HexValues;
353+
};
354+
355+
// The PVCDevices data structure is organized by device name, with the
356+
// corresponding ocloc split release, version and possible Hex representations
357+
// of various PVC devices. This information is gathered from the following:
358+
// https://github.com/intel/compute-runtime/blob/master/shared/source/dll/devices/devices_base.inl
359+
// https://github.com/intel/compute-runtime/blob/master/shared/source/dll/devices/devices_additional.inl
360+
static OclocInfo PVCDevices[] = {
361+
{"pvc-sdv", "gen12+", "12.60.1", {}},
362+
{"pvc",
363+
"gen12+",
364+
"12.60.7",
365+
{0x0BD0, 0x0BD5, 0x0BD6, 0x0BD7, 0x0BD8, 0x0BD9, 0x0BDA, 0x0BDB}}};
366+
367+
static std::string getDeviceArg(const ArgStringList &CmdArgs) {
368+
bool DeviceSeen = false;
369+
std::string DeviceArg;
370+
for (StringRef Arg : CmdArgs) {
371+
// -device <arg> comes in as a single arg, split up all potential space
372+
// separated values.
373+
SmallVector<StringRef> SplitArgs;
374+
Arg.split(SplitArgs, ' ');
375+
for (StringRef SplitArg : SplitArgs) {
376+
if (DeviceSeen) {
377+
DeviceArg = SplitArg.str();
378+
break;
379+
}
380+
if (SplitArg == "-device")
381+
DeviceSeen = true;
382+
}
383+
if (DeviceSeen)
384+
break;
385+
}
386+
387+
return DeviceArg;
388+
}
389+
390+
static bool checkPVCDevice(std::string SingleArg, std::string &DevArg) {
391+
// Handle shortened versions.
392+
bool CheckShortVersion = true;
393+
for (auto Char : SingleArg) {
394+
if (!std::isdigit(Char) && Char != '.') {
395+
CheckShortVersion = false;
396+
break;
397+
}
398+
}
399+
// Check for device, version or hex (literal values)
400+
for (unsigned int I = 0; I < std::size(PVCDevices); I++) {
401+
if (StringRef(SingleArg).equals_insensitive(PVCDevices[I].DeviceName) ||
402+
StringRef(SingleArg).equals_insensitive(PVCDevices[I].Version)) {
403+
DevArg = SingleArg;
404+
return true;
405+
}
406+
407+
for (int HexVal : PVCDevices[I].HexValues) {
408+
int Value = 0;
409+
if (!StringRef(SingleArg).getAsInteger(0, Value) && Value == HexVal) {
410+
// TODO: Pass back the hex string to use for -device_options when
411+
// IGC is updated to allow. Currently -device_options only accepts
412+
// the device ID (i.e. pvc) or the version (12.60.7).
413+
return true;
414+
}
415+
}
416+
if (CheckShortVersion &&
417+
StringRef(PVCDevices[I].Version).starts_with(SingleArg)) {
418+
DevArg = SingleArg;
419+
return true;
420+
}
421+
}
422+
423+
return false;
424+
}
425+
348426
SmallVector<std::string, 8>
349427
SYCL::getDeviceLibraries(const Compilation &C, const llvm::Triple &TargetTriple,
350428
bool IsSpirvAOT) {
@@ -360,6 +438,8 @@ SYCL::getDeviceLibraries(const Compilation &C, const llvm::Triple &TargetTriple,
360438
StringRef DeviceLibOption;
361439
};
362440

441+
enum { JIT = 0, AOT_CPU, AOT_DG2, AOT_PVC };
442+
363443
// Currently, all SYCL device libraries will be linked by default.
364444
llvm::StringMap<bool> DeviceLibLinkInfo = {
365445
{"libc", true}, {"libm-fp32", true}, {"libm-fp64", true},
@@ -460,8 +540,11 @@ SYCL::getDeviceLibraries(const Compilation &C, const llvm::Triple &TargetTriple,
460540
{"libsycl-itt-compiler-wrappers", "internal"},
461541
{"libsycl-itt-stubs", "internal"}};
462542
#if !defined(_WIN32)
463-
const SYCLDeviceLibsList SYCLDeviceSanitizerLibs = {
464-
{"libsycl-sanitizer", "internal"}};
543+
const SYCLDeviceLibsList SYCLDeviceAsanLibs = {
544+
{"libsycl-asan", "internal"},
545+
{"libsycl-asan-cpu", "internal"},
546+
{"libsycl-asan-dg2", "internal"},
547+
{"libsycl-asan-pvc", "internal"}};
465548
#endif
466549

467550
const SYCLDeviceLibsList SYCLNativeCpuDeviceLibs = {
@@ -493,6 +576,66 @@ SYCL::getDeviceLibraries(const Compilation &C, const llvm::Triple &TargetTriple,
493576
}
494577
};
495578

579+
auto addSingleLibrary = [&](const DeviceLibOptInfo &Lib) {
580+
if (!DeviceLibLinkInfo[Lib.DeviceLibOption])
581+
return;
582+
SmallString<128> LibName(Lib.DeviceLibName);
583+
llvm::sys::path::replace_extension(LibName, LibSuffix);
584+
LibraryList.push_back(Args.MakeArgString(LibName));
585+
};
586+
587+
// This function is used to check whether there is only one GPU device
588+
// (PVC or DG2) specified in AOT compilation mode. If yes, we can use
589+
// corresponding libsycl-asan-* to improve device sanitizer performance,
590+
// otherwise stick to fallback device sanitizer library used in JIT mode.
591+
auto getSpecificGPUTarget = [](const ArgStringList &CmdArgs) -> size_t {
592+
std::string DeviceArg = getDeviceArg(CmdArgs);
593+
if ((DeviceArg.empty()) || (DeviceArg.find(",") != std::string::npos))
594+
return JIT;
595+
596+
std::string Temp;
597+
if (checkPVCDevice(DeviceArg, Temp))
598+
return AOT_PVC;
599+
600+
if (DeviceArg == "dg2")
601+
return AOT_DG2;
602+
603+
return JIT;
604+
};
605+
606+
auto getSingleBuildTarget = [&]() -> size_t {
607+
if (!IsSpirvAOT)
608+
return JIT;
609+
610+
llvm::opt::Arg *SYCLTarget = Args.getLastArg(options::OPT_fsycl_targets_EQ);
611+
if (!SYCLTarget || (SYCLTarget->getValues().size() != 1))
612+
return JIT;
613+
614+
StringRef SYCLTargetStr = SYCLTarget->getValue();
615+
if (SYCLTargetStr.starts_with("spir64_x86_64"))
616+
return AOT_CPU;
617+
618+
if (SYCLTargetStr == "intel_gpu_pvc")
619+
return AOT_PVC;
620+
621+
if (SYCLTargetStr.starts_with("intel_gpu_dg2"))
622+
return AOT_DG2;
623+
624+
if (SYCLTargetStr.starts_with("spir64_gen")) {
625+
ArgStringList TargArgs;
626+
Args.AddAllArgValues(TargArgs, options::OPT_Xs, options::OPT_Xs_separate);
627+
Args.AddAllArgValues(TargArgs, options::OPT_Xsycl_backend);
628+
llvm::opt::Arg *A = nullptr;
629+
if ((A = Args.getLastArg(options::OPT_Xsycl_backend_EQ)) &&
630+
StringRef(A->getValue()).starts_with("spir64_gen"))
631+
TargArgs.push_back(A->getValue(1));
632+
633+
return getSpecificGPUTarget(TargArgs);
634+
}
635+
636+
return JIT;
637+
};
638+
496639
addLibraries(SYCLDeviceWrapperLibs);
497640
if (IsSpirvAOT)
498641
addLibraries(SYCLDeviceFallbackLibs);
@@ -512,13 +655,14 @@ SYCL::getDeviceLibraries(const Compilation &C, const llvm::Triple &TargetTriple,
512655
addLibraries(SYCLDeviceAnnotationLibs);
513656

514657
#if !defined(_WIN32)
658+
size_t sanitizer_lib_idx = getSingleBuildTarget();
515659
if (Arg *A = Args.getLastArg(options::OPT_fsanitize_EQ,
516660
options::OPT_fno_sanitize_EQ)) {
517661
if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
518662
A->getValues().size() == 1) {
519663
std::string SanitizeVal = A->getValue();
520664
if (SanitizeVal == "address")
521-
addLibraries(SYCLDeviceSanitizerLibs);
665+
addSingleLibrary(SYCLDeviceAsanLibs[sanitizer_lib_idx]);
522666
}
523667
} else {
524668
// User can pass -fsanitize=address to device compiler via
@@ -546,7 +690,7 @@ SYCL::getDeviceLibraries(const Compilation &C, const llvm::Triple &TargetTriple,
546690
}
547691

548692
if (IsDeviceAsanEnabled)
549-
addLibraries(SYCLDeviceSanitizerLibs);
693+
addSingleLibrary(SYCLDeviceAsanLibs[sanitizer_lib_idx]);
550694
}
551695
#endif
552696

@@ -663,7 +807,10 @@ static llvm::SmallVector<StringRef, 16> SYCLDeviceLibList{
663807
#if defined(_WIN32)
664808
"msvc-math",
665809
#else
666-
"sanitizer",
810+
"asan",
811+
"asan-pvc",
812+
"asan-cpu",
813+
"asan-dg2",
667814
#endif
668815
"imf",
669816
"imf-fp64",
@@ -1131,87 +1278,23 @@ void SYCL::fpga::BackendCompiler::ConstructJob(
11311278
C.addCommand(std::move(Cmd));
11321279
}
11331280

1134-
struct OclocInfo {
1135-
const char *DeviceName;
1136-
const char *PackageName;
1137-
const char *Version;
1138-
SmallVector<int, 8> HexValues;
1139-
};
1140-
1141-
// The PVCDevices data structure is organized by device name, with the
1142-
// corresponding ocloc split release, version and possible Hex representations
1143-
// of various PVC devices. This information is gathered from the following:
1144-
// https://github.com/intel/compute-runtime/blob/master/shared/source/dll/devices/devices_base.inl
1145-
// https://github.com/intel/compute-runtime/blob/master/shared/source/dll/devices/devices_additional.inl
1146-
static OclocInfo PVCDevices[] = {
1147-
{"pvc-sdv", "gen12+", "12.60.1", {}},
1148-
{"pvc",
1149-
"gen12+",
1150-
"12.60.7",
1151-
{0x0BD0, 0x0BD5, 0x0BD6, 0x0BD7, 0x0BD8, 0x0BD9, 0x0BDA, 0x0BDB}}};
1152-
11531281
// Determine if any of the given arguments contain any PVC based values for
11541282
// the -device option.
11551283
static bool hasPVCDevice(const ArgStringList &CmdArgs, std::string &DevArg) {
1156-
bool DeviceSeen = false;
1157-
StringRef DeviceArg;
1158-
for (StringRef Arg : CmdArgs) {
1159-
// -device <arg> comes in as a single arg, split up all potential space
1160-
// separated values.
1161-
SmallVector<StringRef> SplitArgs;
1162-
Arg.split(SplitArgs, ' ');
1163-
for (StringRef SplitArg : SplitArgs) {
1164-
if (DeviceSeen) {
1165-
DeviceArg = SplitArg;
1166-
break;
1167-
}
1168-
if (SplitArg == "-device")
1169-
DeviceSeen = true;
1170-
}
1171-
if (DeviceSeen)
1172-
break;
1173-
}
1174-
if (DeviceArg.empty())
1284+
std::string Res = getDeviceArg(CmdArgs);
1285+
if (Res.empty())
11751286
return false;
1176-
11771287
// Go through all of the arguments to '-device' and determine if any of these
11781288
// are pvc based. We only match literal values and will not find a match
11791289
// when ranges or wildcards are used.
11801290
// Here we parse the targets, tokenizing via ','
1291+
StringRef DeviceArg(Res.c_str());
11811292
SmallVector<StringRef> SplitArgs;
11821293
DeviceArg.split(SplitArgs, ",");
11831294
for (const auto &SingleArg : SplitArgs) {
1184-
StringRef OclocTarget;
1185-
// Handle shortened versions.
1186-
bool CheckShortVersion = true;
1187-
for (auto Char : SingleArg.str()) {
1188-
if (!std::isdigit(Char) && Char != '.') {
1189-
CheckShortVersion = false;
1190-
break;
1191-
}
1192-
}
1193-
// Check for device, version or hex (literal values)
1194-
for (unsigned int I = 0; I < std::size(PVCDevices); I++) {
1195-
if (SingleArg.equals_insensitive(PVCDevices[I].DeviceName) ||
1196-
SingleArg.equals_insensitive(PVCDevices[I].Version)) {
1197-
DevArg = SingleArg.str();
1198-
return true;
1199-
}
1200-
for (int HexVal : PVCDevices[I].HexValues) {
1201-
int Value = 0;
1202-
if (!SingleArg.getAsInteger(0, Value) && Value == HexVal) {
1203-
// TODO: Pass back the hex string to use for -device_options when
1204-
// IGC is updated to allow. Currently -device_options only accepts
1205-
// the device ID (i.e. pvc) or the version (12.60.7).
1206-
return true;
1207-
}
1208-
}
1209-
if (CheckShortVersion &&
1210-
StringRef(PVCDevices[I].Version).starts_with(SingleArg)) {
1211-
DevArg = SingleArg.str();
1212-
return true;
1213-
}
1214-
}
1295+
bool IsPVC = checkPVCDevice(SingleArg.str(), DevArg);
1296+
if (IsPVC)
1297+
return true;
12151298
}
12161299
return false;
12171300
}

clang/test/Driver/Inputs/SYCL/lib/libsycl-asan-dg2.bc

Whitespace-only changes.

clang/test/Driver/Inputs/SYCL/lib/libsycl-asan-dg2.o

Whitespace-only changes.

clang/test/Driver/Inputs/SYCL/lib/libsycl-asan-pvc.bc

Whitespace-only changes.

clang/test/Driver/Inputs/SYCL/lib/libsycl-asan-pvc.o

Whitespace-only changes.

clang/test/Driver/Inputs/SYCL/lib/libsycl-asan.bc

Whitespace-only changes.

clang/test/Driver/Inputs/SYCL/lib/libsycl-asan.o

Whitespace-only changes.

0 commit comments

Comments
 (0)