Skip to content

Commit 830c773

Browse files
committed
[SYCL][Driver] Deduplicate libspirv logic
Move the logic for finding and linking libspirv into SYCLInstallationDetector. This code was basically duplicated between the CUDA and HIP toolchains, and was also present in the Driver sources. This is NFC, aside from the fact that the code in the HIP toolchain lacked the special handling for the `-###` driver option present in the other two places.
1 parent 8f4ea47 commit 830c773

File tree

6 files changed

+96
-152
lines changed

6 files changed

+96
-152
lines changed

clang/lib/Driver/Driver.cpp

Lines changed: 4 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
#include "ToolChains/PS4CPU.h"
4444
#include "ToolChains/RISCVToolchain.h"
4545
#include "ToolChains/SPIRV.h"
46-
#include "ToolChains/SYCL.h"
4746
#include "ToolChains/SPIRVOpenMP.h"
4847
#include "ToolChains/SYCL.h"
4948
#include "ToolChains/Solaris.h"
@@ -5993,46 +5992,10 @@ class OffloadingActionBuilder final {
59935992
// For NVPTX and NativeCPU we need to also link libclc at the same stage
59945993
// that we link all of the unbundled SYCL libdevice objects together.
59955994
if (TC->getTriple().isNVPTX() || isNativeCPU) {
5996-
std::string LibSpirvFile;
5997-
if (Args.hasArg(options::OPT_fsycl_libspirv_path_EQ)) {
5998-
auto ProvidedPath =
5999-
Args.getLastArgValue(options::OPT_fsycl_libspirv_path_EQ).str();
6000-
if (llvm::sys::fs::exists(ProvidedPath))
6001-
LibSpirvFile = ProvidedPath;
6002-
} else {
6003-
SmallVector<StringRef, 2> LibraryPaths;
6004-
6005-
// Expected path w/out install.
6006-
SmallString<256> WithoutInstallPath(C.getDriver().ResourceDir);
6007-
llvm::sys::path::append(WithoutInstallPath, Twine("../../clc"));
6008-
LibraryPaths.emplace_back(WithoutInstallPath.c_str());
6009-
6010-
// Expected path w/ install.
6011-
SmallString<256> WithInstallPath(C.getDriver().ResourceDir);
6012-
llvm::sys::path::append(WithInstallPath, Twine("../../../share/clc"));
6013-
LibraryPaths.emplace_back(WithInstallPath.c_str());
6014-
6015-
// Select remangled libclc variant
6016-
StringRef LibSpirvTargetNamePref =
6017-
TC->getAuxTriple()->isOSWindows()
6018-
? "remangled-l32-signed_char.libspirv-"
6019-
: "remangled-l64-signed_char.libspirv-";
6020-
6021-
for (StringRef LibraryPath : LibraryPaths) {
6022-
SmallString<128> LibSpirvTargetFile(LibraryPath);
6023-
llvm::sys::path::append(LibSpirvTargetFile,
6024-
LibSpirvTargetNamePref +
6025-
TC->getTripleString() + ".bc");
6026-
if (llvm::sys::fs::exists(LibSpirvTargetFile) ||
6027-
Args.hasArg(options::OPT__HASH_HASH_HASH)) {
6028-
LibSpirvFile = std::string(LibSpirvTargetFile.str());
6029-
break;
6030-
}
6031-
}
6032-
}
6033-
if (!LibSpirvFile.empty()) {
6034-
Arg *LibClcInputArg = MakeInputArg(Args, C.getDriver().getOpts(),
6035-
Args.MakeArgString(LibSpirvFile));
5995+
if (const char *LibSpirvFile = SYCLInstallation.findLibspirvPath(
5996+
TC->getTriple(), Args, *TC->getAuxTriple())) {
5997+
Arg *LibClcInputArg =
5998+
MakeInputArg(Args, C.getDriver().getOpts(), LibSpirvFile);
60365999
auto *SYCLLibClcInputAction =
60376000
C.MakeAction<InputAction>(*LibClcInputArg, types::TY_LLVM_BC);
60386001
DeviceLinkObjects.push_back(SYCLLibClcInputAction);

clang/lib/Driver/ToolChains/Cuda.cpp

Lines changed: 3 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -861,14 +861,6 @@ NVPTXToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
861861
return DAL;
862862
}
863863

864-
// Select remangled libclc variant. 64-bit longs default, 32-bit longs on
865-
// Windows
866-
static const char *getLibSpirvTargetName(const ToolChain &HostTC) {
867-
if (HostTC.getTriple().isOSWindows())
868-
return "remangled-l32-signed_char.libspirv-nvptx64-nvidia-cuda.bc";
869-
return "remangled-l64-signed_char.libspirv-nvptx64-nvidia-cuda.bc";
870-
}
871-
872864
void NVPTXToolChain::addClangTargetOptions(
873865
const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
874866
Action::OffloadKind DeviceOffloadingKind) const {}
@@ -970,6 +962,9 @@ void CudaToolChain::addClangTargetOptions(
970962
options::OPT_fno_sycl_id_queries_fit_in_int, false))
971963
CC1Args.append(
972964
{"-mllvm", "-nvvm-reflect-add=__CUDA_ID_QUERIES_FIT_IN_INT=1"});
965+
966+
SYCLInstallation.addLibspirvLinkArgs(getEffectiveTriple(), DriverArgs,
967+
HostTC.getTriple(), CC1Args);
973968
} else {
974969
CC1Args.append({"-fcuda-is-device", "-mllvm",
975970
"-enable-memcpyopt-without-libcalls",
@@ -988,53 +983,6 @@ void CudaToolChain::addClangTargetOptions(
988983
CC1Args.append({"-std=c++17", "-fsycl-is-host"});
989984
}
990985

991-
auto NoLibSpirv = DriverArgs.hasArg(options::OPT_fno_sycl_libspirv) ||
992-
getDriver().offloadDeviceOnly();
993-
if (DeviceOffloadingKind == Action::OFK_SYCL && !NoLibSpirv) {
994-
std::string LibSpirvFile;
995-
996-
if (DriverArgs.hasArg(clang::driver::options::OPT_fsycl_libspirv_path_EQ)) {
997-
auto ProvidedPath =
998-
DriverArgs.getLastArgValue(clang::driver::options::OPT_fsycl_libspirv_path_EQ).str();
999-
if (llvm::sys::fs::exists(ProvidedPath))
1000-
LibSpirvFile = ProvidedPath;
1001-
} else {
1002-
SmallVector<StringRef, 8> LibraryPaths;
1003-
1004-
// Expected path w/out install.
1005-
SmallString<256> WithoutInstallPath(getDriver().ResourceDir);
1006-
llvm::sys::path::append(WithoutInstallPath, Twine("../../clc"));
1007-
LibraryPaths.emplace_back(WithoutInstallPath.c_str());
1008-
1009-
// Expected path w/ install.
1010-
SmallString<256> WithInstallPath(getDriver().ResourceDir);
1011-
llvm::sys::path::append(WithInstallPath, Twine("../../../share/clc"));
1012-
LibraryPaths.emplace_back(WithInstallPath.c_str());
1013-
1014-
// Select remangled libclc variant
1015-
std::string LibSpirvTargetName = getLibSpirvTargetName(HostTC);
1016-
1017-
for (StringRef LibraryPath : LibraryPaths) {
1018-
SmallString<128> LibSpirvTargetFile(LibraryPath);
1019-
llvm::sys::path::append(LibSpirvTargetFile, LibSpirvTargetName);
1020-
if (llvm::sys::fs::exists(LibSpirvTargetFile) ||
1021-
DriverArgs.hasArg(options::OPT__HASH_HASH_HASH)) {
1022-
LibSpirvFile = std::string(LibSpirvTargetFile.str());
1023-
break;
1024-
}
1025-
}
1026-
}
1027-
1028-
if (LibSpirvFile.empty()) {
1029-
getDriver().Diag(diag::err_drv_no_sycl_libspirv)
1030-
<< getLibSpirvTargetName(HostTC);
1031-
return;
1032-
}
1033-
1034-
CC1Args.push_back("-mlink-builtin-bitcode");
1035-
CC1Args.push_back(DriverArgs.MakeArgString(LibSpirvFile));
1036-
}
1037-
1038986
if (DriverArgs.hasFlag(options::OPT_fcuda_short_ptr,
1039987
options::OPT_fno_cuda_short_ptr, false))
1040988
CC1Args.append({"-mllvm", "--nvptx-short-ptr"});

clang/lib/Driver/ToolChains/HIPAMD.cpp

Lines changed: 2 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -222,10 +222,6 @@ HIPAMDToolChain::HIPAMDToolChain(const Driver &D, const llvm::Triple &Triple,
222222
diagnoseUnsupportedSanitizers(Args);
223223
}
224224

225-
static const char *getLibSpirvTargetName(const ToolChain &HostTC) {
226-
return "remangled-l64-signed_char.libspirv-amdgcn-amd-amdhsa.bc";
227-
}
228-
229225
void HIPAMDToolChain::addClangTargetOptions(
230226
const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
231227
Action::OffloadKind DeviceOffloadingKind) const {
@@ -274,53 +270,8 @@ void HIPAMDToolChain::addClangTargetOptions(
274270

275271
if (DeviceOffloadingKind == Action::OFK_SYCL) {
276272
SYCLInstallation.addSYCLIncludeArgs(DriverArgs, CC1Args);
277-
}
278-
279-
auto NoLibSpirv = DriverArgs.hasArg(options::OPT_fno_sycl_libspirv) ||
280-
getDriver().offloadDeviceOnly();
281-
if (DeviceOffloadingKind == Action::OFK_SYCL && !NoLibSpirv) {
282-
std::string LibSpirvFile;
283-
284-
if (DriverArgs.hasArg(clang::driver::options::OPT_fsycl_libspirv_path_EQ)) {
285-
auto ProvidedPath =
286-
DriverArgs
287-
.getLastArgValue(
288-
clang::driver::options::OPT_fsycl_libspirv_path_EQ)
289-
.str();
290-
if (llvm::sys::fs::exists(ProvidedPath))
291-
LibSpirvFile = ProvidedPath;
292-
} else {
293-
SmallVector<StringRef, 8> LibraryPaths;
294-
295-
// Expected path w/out install.
296-
SmallString<256> WithoutInstallPath(getDriver().ResourceDir);
297-
llvm::sys::path::append(WithoutInstallPath, Twine("../../clc"));
298-
LibraryPaths.emplace_back(WithoutInstallPath.c_str());
299-
300-
// Expected path w/ install.
301-
SmallString<256> WithInstallPath(getDriver().ResourceDir);
302-
llvm::sys::path::append(WithInstallPath, Twine("../../../share/clc"));
303-
LibraryPaths.emplace_back(WithInstallPath.c_str());
304-
305-
std::string LibSpirvTargetName = getLibSpirvTargetName(HostTC);
306-
for (StringRef LibraryPath : LibraryPaths) {
307-
SmallString<128> LibSpirvTargetFile(LibraryPath);
308-
llvm::sys::path::append(LibSpirvTargetFile, LibSpirvTargetName);
309-
if (llvm::sys::fs::exists(LibSpirvTargetFile)) {
310-
LibSpirvFile = std::string(LibSpirvTargetFile.str());
311-
break;
312-
}
313-
}
314-
}
315-
316-
if (LibSpirvFile.empty()) {
317-
getDriver().Diag(diag::err_drv_no_sycl_libspirv)
318-
<< getLibSpirvTargetName(HostTC);
319-
return;
320-
}
321-
322-
CC1Args.push_back("-mlink-builtin-bitcode");
323-
CC1Args.push_back(DriverArgs.MakeArgString(LibSpirvFile));
273+
SYCLInstallation.addLibspirvLinkArgs(getEffectiveTriple(), DriverArgs,
274+
HostTC.getTriple(), CC1Args);
324275
}
325276

326277
for (auto BCFile : getDeviceLibs(DriverArgs, DeviceOffloadingKind)) {

clang/lib/Driver/ToolChains/SYCL.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,77 @@ SYCLInstallationDetector::SYCLInstallationDetector(
149149
const llvm::opt::ArgList &Args)
150150
: D(D) {}
151151

152+
static llvm::SmallString<64>
153+
getLibSpirvBasename(const llvm::Triple &DeviceTriple,
154+
const llvm::Triple &HostTriple) {
155+
// Select remangled libclc variant
156+
llvm::SmallString<64> Result(HostTriple.isWindowsMSVCEnvironment()
157+
? "remangled-l32-signed_char.libspirv-"
158+
: "remangled-l64-signed_char.libspirv-");
159+
160+
Result.append(DeviceTriple.getTriple());
161+
Result.append(".bc");
162+
163+
return Result;
164+
}
165+
166+
const char *SYCLInstallationDetector::findLibspirvPath(
167+
const llvm::Triple &DeviceTriple, const llvm::opt::ArgList &Args,
168+
const llvm::Triple &HostTriple) const {
169+
170+
// If -fsycl-libspirv-path= is specified, try to use that path directly.
171+
if (Arg *A = Args.getLastArg(options::OPT_fsycl_libspirv_path_EQ)) {
172+
if (llvm::sys::fs::exists(A->getValue()))
173+
return A->getValue();
174+
175+
return nullptr;
176+
}
177+
178+
const SmallString<64> Basename = getLibSpirvBasename(DeviceTriple, HostTriple);
179+
auto searchAt = [&](StringRef Path, const Twine &a = "", const Twine &b = "",
180+
const Twine &c = "", const Twine &d = "",
181+
const Twine &e = "") -> const char * {
182+
SmallString<128> LibraryPath(Path);
183+
llvm::sys::path::append(LibraryPath, a, b, c, d);
184+
llvm::sys::path::append(LibraryPath, e, Basename);
185+
186+
if (Args.hasArgNoClaim(options::OPT__HASH_HASH_HASH) ||
187+
llvm::sys::fs::exists(LibraryPath))
188+
return Args.MakeArgString(LibraryPath);
189+
190+
return nullptr;
191+
};
192+
193+
// Otherwise, assume libclc is installed at the same prefix as clang
194+
// Expected path w/out install.
195+
if (const char *R = searchAt(D.ResourceDir, "..", "..", "clc"))
196+
return R;
197+
198+
// Expected path w/ install.
199+
if (const char *R = searchAt(D.ResourceDir, "..", "..", "..", "share", "clc"))
200+
return R;
201+
202+
return nullptr;
203+
}
204+
205+
void SYCLInstallationDetector::addLibspirvLinkArgs(
206+
const llvm::Triple &DeviceTriple, const llvm::opt::ArgList &DriverArgs,
207+
const llvm::Triple &HostTriple, llvm::opt::ArgStringList &CC1Args) const {
208+
if (DriverArgs.hasArg(options::OPT_fno_sycl_libspirv) ||
209+
D.offloadDeviceOnly())
210+
return;
211+
212+
if (const char *LibSpirvFile =
213+
findLibspirvPath(DeviceTriple, DriverArgs, HostTriple)) {
214+
CC1Args.push_back("-mlink-builtin-bitcode");
215+
CC1Args.push_back(LibSpirvFile);
216+
return;
217+
}
218+
219+
D.Diag(diag::err_drv_no_sycl_libspirv)
220+
<< getLibSpirvBasename(DeviceTriple, HostTriple);
221+
}
222+
152223
void SYCLInstallationDetector::getSYCLDeviceLibPath(
153224
llvm::SmallVector<llvm::SmallString<128>, 4> &DeviceLibPaths) const {
154225
for (const auto &IC : InstallationCandidates) {

clang/lib/Driver/ToolChains/SYCL.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,19 @@ class SYCLInstallationDetector {
130130
SYCLInstallationDetector(const Driver &D);
131131
SYCLInstallationDetector(const Driver &D, const llvm::Triple &HostTriple,
132132
const llvm::opt::ArgList &Args);
133+
134+
/// \brief Find and return the path to the libspirv library for the target
135+
/// \return The path to the libspirv library if found, otherwise nullptr.
136+
/// The lifetime of the returned string is managed by \p Args.
137+
const char *findLibspirvPath(const llvm::Triple &DeviceTriple,
138+
const llvm::opt::ArgList &Args,
139+
const llvm::Triple &HostTriple) const;
140+
141+
void addLibspirvLinkArgs(const llvm::Triple &DeviceTriple,
142+
const llvm::opt::ArgList &DriverArgs,
143+
const llvm::Triple &HostTriple,
144+
llvm::opt::ArgStringList &CC1Args) const;
145+
133146
void getSYCLDeviceLibPath(
134147
llvm::SmallVector<llvm::SmallString<128>, 4> &DeviceLibPaths) const;
135148
void addSYCLIncludeArgs(const llvm::opt::ArgList &DriverArgs,

clang/test/Driver/sycl-libspirv-toolchain.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@
1111
// RUN: | FileCheck %s --check-prefixes=CHECK-LINUX
1212
// CHECK-LINUX: "-cc1"{{.*}} "-fsycl-is-device"{{.*}} "-mlink-builtin-bitcode" "{{.*[\\/]}}remangled-l64-signed_char.libspirv-nvptx64-nvidia-cuda.bc"
1313
//
14-
// AMDGCN wrongly uses 32-bit longs on Windows
1514
// RUN: %clang -### -resource-dir %{resource_dir} -fsycl -fsycl-targets=amdgcn-amd-amdhsa -Xsycl-target-backend --offload-arch=gfx908 -nogpulib -target x86_64-unknown-windows-msvc %s 2>&1 \
1615
// RUN: | FileCheck %s --check-prefixes=CHECK-AMDGCN-WINDOWS
17-
// CHECK-AMDGCN-WINDOWS: "-cc1"{{.*}} "-fsycl-is-device"{{.*}} "-mlink-builtin-bitcode" "{{.*[\\/]}}remangled-l64-signed_char.libspirv-amdgcn-amd-amdhsa.bc"
16+
// CHECK-AMDGCN-WINDOWS: "-cc1"{{.*}} "-fsycl-is-device"{{.*}} "-mlink-builtin-bitcode" "{{.*[\\/]}}remangled-l32-signed_char.libspirv-amdgcn-amd-amdhsa.bc"
1817
//
1918
// RUN: %clang -### -fsycl -fsycl-device-only -fsycl-targets=nvptx64-nvidia-cuda -nocudalib %s 2>&1 \
2019
// RUN: | FileCheck %s --check-prefixes=CHECK-DEVICE-ONLY
@@ -38,10 +37,9 @@
3837
// RUN: | FileCheck %s -DDIR=%{nonexistent_dir} --check-prefixes=CHECK-HHH-NONEXISTENT
3938
// CHECK-HHH-NONEXISTENT: "-cc1"{{.*}} "-fsycl-is-device"{{.*}} "-mlink-builtin-bitcode" "[[DIR]]{{.*[\\/]}}remangled-{{.*}}.libspirv-nvptx64-nvidia-cuda.bc"
4039
//
41-
// But not for AMDGCN :^)
42-
// RUN: not %clang -### -resource-dir %{nonexistent_dir} -fsycl -fsycl-targets=amdgcn-amd-amdhsa -Xsycl-target-backend --offload-arch=gfx908 -nogpulib %s 2>&1 \
40+
// RUN: %clang -### -resource-dir %{nonexistent_dir} -fsycl -fsycl-targets=amdgcn-amd-amdhsa -Xsycl-target-backend --offload-arch=gfx908 -nogpulib %s 2>&1 \
4341
// RUN: | FileCheck %s -DDIR=%{nonexistent_dir} --check-prefixes=CHECK-AMDGCN-HHH-NONEXISTENT
44-
// CHECK-AMDGCN-HHH-NONEXISTENT: error: cannot find 'remangled-{{.*}}.libspirv-amdgcn-amd-amdhsa.bc'; provide path to libspirv library via '-fsycl-libspirv-path', or pass '-fno-sycl-libspirv' to build without linking with libspirv
42+
// CHECK-AMDGCN-HHH-NONEXISTENT: "-cc1"{{.*}} "-fsycl-is-device"{{.*}} "-mlink-builtin-bitcode" "[[DIR]]{{.*[\\/]}}remangled-{{.*}}.libspirv-amdgcn-amd-amdhsa.bc"
4543
//
4644
// `-fdriver-only` has no such special handling, so it will not find the file
4745
// RUN: not %clang -fdriver-only -resource-dir %{nonexistent_dir} -fsycl -fsycl-targets=nvptx64-nvidia-cuda -nocudalib %s 2>&1 \

0 commit comments

Comments
 (0)