Skip to content

Commit

Permalink
Merge branch 'intel:sycl' into indeterminate_constructor_work_group_m…
Browse files Browse the repository at this point in the history
…emory
  • Loading branch information
lbushi25 authored Nov 11, 2024
2 parents 32c5cb6 + ac3a03e commit 418365d
Show file tree
Hide file tree
Showing 107 changed files with 3,767 additions and 691 deletions.
1 change: 0 additions & 1 deletion .github/workflows/sycl-linux-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,6 @@ jobs:
--cmake-opt=-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
--cmake-opt="-DLLVM_INSTALL_UTILS=ON" \
--cmake-opt="-DNATIVECPU_USE_OCK=Off" \
--cmake-opt="-DSYCL_PI_TESTS=OFF" \
--cmake-opt="-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=SPIRV"
- name: Compile
id: build
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/sycl-macos-build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ jobs:
--ci-defaults $ARGS \
--cmake-opt=-DCMAKE_C_COMPILER_LAUNCHER=ccache \
--cmake-opt=-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
--cmake-opt="-DLLVM_INSTALL_UTILS=ON" \
--cmake-opt="-DSYCL_PI_TESTS=OFF"
--cmake-opt="-DLLVM_INSTALL_UTILS=ON"
- name: Compile
run: cmake --build $GITHUB_WORKSPACE/build --target deploy-sycl-toolchain
57 changes: 36 additions & 21 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10353,33 +10353,48 @@ void OffloadWrapper::ConstructJob(Compilation &C, const JobAction &JA,
assert(JA.getInputs().size() == Inputs.size() &&
"Not have inputs for all dependence actions??");

// For FPGA, we wrap the host objects before archiving them when using
// -fsycl-link. This allows for better extraction control from the
// archive when we need the host objects for subsequent compilations.
if (OffloadingKind == Action::OFK_None &&
C.getArgs().hasArg(options::OPT_fintelfpga) &&
C.getArgs().hasArg(options::OPT_fsycl_link_EQ)) {

// Add offload targets and inputs.
CmdArgs.push_back(C.getArgs().MakeArgString(
Twine("-kind=") + Action::GetOffloadKindName(OffloadingKind)));
CmdArgs.push_back(
TCArgs.MakeArgString(Twine("-target=") + Triple.getTriple()));
// For FPGA, we wrap the host objects before archiving them when using
// -fsycl-link. This allows for better extraction control from the
// archive when we need the host objects for subsequent compilations.
if (C.getArgs().hasArg(options::OPT_fintelfpga)) {

if (Inputs[0].getType() == types::TY_Tempfiletable ||
Inputs[0].getType() == types::TY_Tempfilelist)
// Input files are passed via the batch job file table.
CmdArgs.push_back(C.getArgs().MakeArgString("-batch"));
// Add offload targets and inputs.
CmdArgs.push_back(C.getArgs().MakeArgString(
Twine("-kind=") + Action::GetOffloadKindName(OffloadingKind)));
CmdArgs.push_back(
TCArgs.MakeArgString(Twine("-target=") + Triple.getTriple()));

// Add input.
assert(Inputs[0].isFilename() && "Invalid input.");
CmdArgs.push_back(TCArgs.MakeArgString(Inputs[0].getFilename()));
if (Inputs[0].getType() == types::TY_Tempfiletable ||
Inputs[0].getType() == types::TY_Tempfilelist)
// Input files are passed via the batch job file table.
CmdArgs.push_back(C.getArgs().MakeArgString("-batch"));

C.addCommand(std::make_unique<Command>(
JA, *this, ResponseFileSupport::None(),
TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())),
CmdArgs, Inputs));
return;
// Add input.
assert(Inputs[0].isFilename() && "Invalid input.");
CmdArgs.push_back(TCArgs.MakeArgString(Inputs[0].getFilename()));

C.addCommand(std::make_unique<Command>(
JA, *this, ResponseFileSupport::None(),
TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())),
CmdArgs, Inputs));
return;
} else {
// When compiling and linking separately, we need to propagate the
// compression related CLI options to offload-wrapper. Don't propagate
// these options when wrapping objects for FPGA.
if (C.getInputArgs().getLastArg(options::OPT_offload_compress)) {
CmdArgs.push_back(
C.getArgs().MakeArgString(Twine("-offload-compress")));
// -offload-compression-level=<>
if (Arg *A = C.getInputArgs().getLastArg(
options::OPT_offload_compression_level_EQ))
CmdArgs.push_back(C.getArgs().MakeArgString(
Twine("-offload-compression-level=") + A->getValue()));
}
}
}

// Add offload targets and inputs.
Expand Down
233 changes: 158 additions & 75 deletions clang/lib/Driver/ToolChains/SYCL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,84 @@ static bool selectBfloatLibs(const llvm::Triple &Triple, const Compilation &C,
return NeedLibs;
}

struct OclocInfo {
const char *DeviceName;
const char *PackageName;
const char *Version;
SmallVector<int, 8> HexValues;
};

// The PVCDevices data structure is organized by device name, with the
// corresponding ocloc split release, version and possible Hex representations
// of various PVC devices. This information is gathered from the following:
// https://github.com/intel/compute-runtime/blob/master/shared/source/dll/devices/devices_base.inl
// https://github.com/intel/compute-runtime/blob/master/shared/source/dll/devices/devices_additional.inl
static OclocInfo PVCDevices[] = {
{"pvc-sdv", "gen12+", "12.60.1", {}},
{"pvc",
"gen12+",
"12.60.7",
{0x0BD0, 0x0BD5, 0x0BD6, 0x0BD7, 0x0BD8, 0x0BD9, 0x0BDA, 0x0BDB}}};

static std::string getDeviceArg(const ArgStringList &CmdArgs) {
bool DeviceSeen = false;
std::string DeviceArg;
for (StringRef Arg : CmdArgs) {
// -device <arg> comes in as a single arg, split up all potential space
// separated values.
SmallVector<StringRef> SplitArgs;
Arg.split(SplitArgs, ' ');
for (StringRef SplitArg : SplitArgs) {
if (DeviceSeen) {
DeviceArg = SplitArg.str();
break;
}
if (SplitArg == "-device")
DeviceSeen = true;
}
if (DeviceSeen)
break;
}

return DeviceArg;
}

static bool checkPVCDevice(std::string SingleArg, std::string &DevArg) {
// Handle shortened versions.
bool CheckShortVersion = true;
for (auto Char : SingleArg) {
if (!std::isdigit(Char) && Char != '.') {
CheckShortVersion = false;
break;
}
}
// Check for device, version or hex (literal values)
for (unsigned int I = 0; I < std::size(PVCDevices); I++) {
if (StringRef(SingleArg).equals_insensitive(PVCDevices[I].DeviceName) ||
StringRef(SingleArg).equals_insensitive(PVCDevices[I].Version)) {
DevArg = SingleArg;
return true;
}

for (int HexVal : PVCDevices[I].HexValues) {
int Value = 0;
if (!StringRef(SingleArg).getAsInteger(0, Value) && Value == HexVal) {
// TODO: Pass back the hex string to use for -device_options when
// IGC is updated to allow. Currently -device_options only accepts
// the device ID (i.e. pvc) or the version (12.60.7).
return true;
}
}
if (CheckShortVersion &&
StringRef(PVCDevices[I].Version).starts_with(SingleArg)) {
DevArg = SingleArg;
return true;
}
}

return false;
}

SmallVector<std::string, 8>
SYCL::getDeviceLibraries(const Compilation &C, const llvm::Triple &TargetTriple,
bool IsSpirvAOT) {
Expand All @@ -360,6 +438,8 @@ SYCL::getDeviceLibraries(const Compilation &C, const llvm::Triple &TargetTriple,
StringRef DeviceLibOption;
};

enum { JIT = 0, AOT_CPU, AOT_DG2, AOT_PVC };

// Currently, all SYCL device libraries will be linked by default.
llvm::StringMap<bool> DeviceLibLinkInfo = {
{"libc", true}, {"libm-fp32", true}, {"libm-fp64", true},
Expand Down Expand Up @@ -460,8 +540,11 @@ SYCL::getDeviceLibraries(const Compilation &C, const llvm::Triple &TargetTriple,
{"libsycl-itt-compiler-wrappers", "internal"},
{"libsycl-itt-stubs", "internal"}};
#if !defined(_WIN32)
const SYCLDeviceLibsList SYCLDeviceSanitizerLibs = {
{"libsycl-sanitizer", "internal"}};
const SYCLDeviceLibsList SYCLDeviceAsanLibs = {
{"libsycl-asan", "internal"},
{"libsycl-asan-cpu", "internal"},
{"libsycl-asan-dg2", "internal"},
{"libsycl-asan-pvc", "internal"}};
#endif

const SYCLDeviceLibsList SYCLNativeCpuDeviceLibs = {
Expand Down Expand Up @@ -493,6 +576,66 @@ SYCL::getDeviceLibraries(const Compilation &C, const llvm::Triple &TargetTriple,
}
};

auto addSingleLibrary = [&](const DeviceLibOptInfo &Lib) {
if (!DeviceLibLinkInfo[Lib.DeviceLibOption])
return;
SmallString<128> LibName(Lib.DeviceLibName);
llvm::sys::path::replace_extension(LibName, LibSuffix);
LibraryList.push_back(Args.MakeArgString(LibName));
};

// This function is used to check whether there is only one GPU device
// (PVC or DG2) specified in AOT compilation mode. If yes, we can use
// corresponding libsycl-asan-* to improve device sanitizer performance,
// otherwise stick to fallback device sanitizer library used in JIT mode.
auto getSpecificGPUTarget = [](const ArgStringList &CmdArgs) -> size_t {
std::string DeviceArg = getDeviceArg(CmdArgs);
if ((DeviceArg.empty()) || (DeviceArg.find(",") != std::string::npos))
return JIT;

std::string Temp;
if (checkPVCDevice(DeviceArg, Temp))
return AOT_PVC;

if (DeviceArg == "dg2")
return AOT_DG2;

return JIT;
};

auto getSingleBuildTarget = [&]() -> size_t {
if (!IsSpirvAOT)
return JIT;

llvm::opt::Arg *SYCLTarget = Args.getLastArg(options::OPT_fsycl_targets_EQ);
if (!SYCLTarget || (SYCLTarget->getValues().size() != 1))
return JIT;

StringRef SYCLTargetStr = SYCLTarget->getValue();
if (SYCLTargetStr.starts_with("spir64_x86_64"))
return AOT_CPU;

if (SYCLTargetStr == "intel_gpu_pvc")
return AOT_PVC;

if (SYCLTargetStr.starts_with("intel_gpu_dg2"))
return AOT_DG2;

if (SYCLTargetStr.starts_with("spir64_gen")) {
ArgStringList TargArgs;
Args.AddAllArgValues(TargArgs, options::OPT_Xs, options::OPT_Xs_separate);
Args.AddAllArgValues(TargArgs, options::OPT_Xsycl_backend);
llvm::opt::Arg *A = nullptr;
if ((A = Args.getLastArg(options::OPT_Xsycl_backend_EQ)) &&
StringRef(A->getValue()).starts_with("spir64_gen"))
TargArgs.push_back(A->getValue(1));

return getSpecificGPUTarget(TargArgs);
}

return JIT;
};

addLibraries(SYCLDeviceWrapperLibs);
if (IsSpirvAOT)
addLibraries(SYCLDeviceFallbackLibs);
Expand All @@ -512,13 +655,14 @@ SYCL::getDeviceLibraries(const Compilation &C, const llvm::Triple &TargetTriple,
addLibraries(SYCLDeviceAnnotationLibs);

#if !defined(_WIN32)
size_t sanitizer_lib_idx = getSingleBuildTarget();
if (Arg *A = Args.getLastArg(options::OPT_fsanitize_EQ,
options::OPT_fno_sanitize_EQ)) {
if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
A->getValues().size() == 1) {
std::string SanitizeVal = A->getValue();
if (SanitizeVal == "address")
addLibraries(SYCLDeviceSanitizerLibs);
addSingleLibrary(SYCLDeviceAsanLibs[sanitizer_lib_idx]);
}
} else {
// User can pass -fsanitize=address to device compiler via
Expand Down Expand Up @@ -546,7 +690,7 @@ SYCL::getDeviceLibraries(const Compilation &C, const llvm::Triple &TargetTriple,
}

if (IsDeviceAsanEnabled)
addLibraries(SYCLDeviceSanitizerLibs);
addSingleLibrary(SYCLDeviceAsanLibs[sanitizer_lib_idx]);
}
#endif

Expand Down Expand Up @@ -663,7 +807,10 @@ static llvm::SmallVector<StringRef, 16> SYCLDeviceLibList{
#if defined(_WIN32)
"msvc-math",
#else
"sanitizer",
"asan",
"asan-pvc",
"asan-cpu",
"asan-dg2",
#endif
"imf",
"imf-fp64",
Expand Down Expand Up @@ -1131,87 +1278,23 @@ void SYCL::fpga::BackendCompiler::ConstructJob(
C.addCommand(std::move(Cmd));
}

struct OclocInfo {
const char *DeviceName;
const char *PackageName;
const char *Version;
SmallVector<int, 8> HexValues;
};

// The PVCDevices data structure is organized by device name, with the
// corresponding ocloc split release, version and possible Hex representations
// of various PVC devices. This information is gathered from the following:
// https://github.com/intel/compute-runtime/blob/master/shared/source/dll/devices/devices_base.inl
// https://github.com/intel/compute-runtime/blob/master/shared/source/dll/devices/devices_additional.inl
static OclocInfo PVCDevices[] = {
{"pvc-sdv", "gen12+", "12.60.1", {}},
{"pvc",
"gen12+",
"12.60.7",
{0x0BD0, 0x0BD5, 0x0BD6, 0x0BD7, 0x0BD8, 0x0BD9, 0x0BDA, 0x0BDB}}};

// Determine if any of the given arguments contain any PVC based values for
// the -device option.
static bool hasPVCDevice(const ArgStringList &CmdArgs, std::string &DevArg) {
bool DeviceSeen = false;
StringRef DeviceArg;
for (StringRef Arg : CmdArgs) {
// -device <arg> comes in as a single arg, split up all potential space
// separated values.
SmallVector<StringRef> SplitArgs;
Arg.split(SplitArgs, ' ');
for (StringRef SplitArg : SplitArgs) {
if (DeviceSeen) {
DeviceArg = SplitArg;
break;
}
if (SplitArg == "-device")
DeviceSeen = true;
}
if (DeviceSeen)
break;
}
if (DeviceArg.empty())
std::string Res = getDeviceArg(CmdArgs);
if (Res.empty())
return false;

// Go through all of the arguments to '-device' and determine if any of these
// are pvc based. We only match literal values and will not find a match
// when ranges or wildcards are used.
// Here we parse the targets, tokenizing via ','
StringRef DeviceArg(Res.c_str());
SmallVector<StringRef> SplitArgs;
DeviceArg.split(SplitArgs, ",");
for (const auto &SingleArg : SplitArgs) {
StringRef OclocTarget;
// Handle shortened versions.
bool CheckShortVersion = true;
for (auto Char : SingleArg.str()) {
if (!std::isdigit(Char) && Char != '.') {
CheckShortVersion = false;
break;
}
}
// Check for device, version or hex (literal values)
for (unsigned int I = 0; I < std::size(PVCDevices); I++) {
if (SingleArg.equals_insensitive(PVCDevices[I].DeviceName) ||
SingleArg.equals_insensitive(PVCDevices[I].Version)) {
DevArg = SingleArg.str();
return true;
}
for (int HexVal : PVCDevices[I].HexValues) {
int Value = 0;
if (!SingleArg.getAsInteger(0, Value) && Value == HexVal) {
// TODO: Pass back the hex string to use for -device_options when
// IGC is updated to allow. Currently -device_options only accepts
// the device ID (i.e. pvc) or the version (12.60.7).
return true;
}
}
if (CheckShortVersion &&
StringRef(PVCDevices[I].Version).starts_with(SingleArg)) {
DevArg = SingleArg.str();
return true;
}
}
bool IsPVC = checkPVCDevice(SingleArg.str(), DevArg);
if (IsPVC)
return true;
}
return false;
}
Expand Down
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Loading

0 comments on commit 418365d

Please sign in to comment.