diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index e1b29cdab712e..530d1fd3e478b 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -43,7 +43,6 @@ #include "ToolChains/PS4CPU.h" #include "ToolChains/RISCVToolchain.h" #include "ToolChains/SPIRV.h" -#include "ToolChains/SYCL.h" #include "ToolChains/SPIRVOpenMP.h" #include "ToolChains/SYCL.h" #include "ToolChains/Solaris.h" @@ -5993,46 +5992,10 @@ class OffloadingActionBuilder final { // For NVPTX and NativeCPU we need to also link libclc at the same stage // that we link all of the unbundled SYCL libdevice objects together. if (TC->getTriple().isNVPTX() || isNativeCPU) { - std::string LibSpirvFile; - if (Args.hasArg(options::OPT_fsycl_libspirv_path_EQ)) { - auto ProvidedPath = - Args.getLastArgValue(options::OPT_fsycl_libspirv_path_EQ).str(); - if (llvm::sys::fs::exists(ProvidedPath)) - LibSpirvFile = ProvidedPath; - } else { - SmallVector LibraryPaths; - - // Expected path w/out install. - SmallString<256> WithoutInstallPath(C.getDriver().ResourceDir); - llvm::sys::path::append(WithoutInstallPath, Twine("../../clc")); - LibraryPaths.emplace_back(WithoutInstallPath.c_str()); - - // Expected path w/ install. - SmallString<256> WithInstallPath(C.getDriver().ResourceDir); - llvm::sys::path::append(WithInstallPath, Twine("../../../share/clc")); - LibraryPaths.emplace_back(WithInstallPath.c_str()); - - // Select remangled libclc variant - StringRef LibSpirvTargetNamePref = - TC->getAuxTriple()->isOSWindows() - ? "remangled-l32-signed_char.libspirv-" - : "remangled-l64-signed_char.libspirv-"; - - for (StringRef LibraryPath : LibraryPaths) { - SmallString<128> LibSpirvTargetFile(LibraryPath); - llvm::sys::path::append(LibSpirvTargetFile, - LibSpirvTargetNamePref + - TC->getTripleString() + ".bc"); - if (llvm::sys::fs::exists(LibSpirvTargetFile) || - Args.hasArg(options::OPT__HASH_HASH_HASH)) { - LibSpirvFile = std::string(LibSpirvTargetFile.str()); - break; - } - } - } - if (!LibSpirvFile.empty()) { - Arg *LibClcInputArg = MakeInputArg(Args, C.getDriver().getOpts(), - Args.MakeArgString(LibSpirvFile)); + if (const char *LibSpirvFile = SYCLInstallation.findLibspirvPath( + TC->getTriple(), Args, *TC->getAuxTriple())) { + Arg *LibClcInputArg = + MakeInputArg(Args, C.getDriver().getOpts(), LibSpirvFile); auto *SYCLLibClcInputAction = C.MakeAction(*LibClcInputArg, types::TY_LLVM_BC); DeviceLinkObjects.push_back(SYCLLibClcInputAction); diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp index 09cd2e3c3a27f..d9a7689115f83 100644 --- a/clang/lib/Driver/ToolChains/Cuda.cpp +++ b/clang/lib/Driver/ToolChains/Cuda.cpp @@ -861,14 +861,6 @@ NVPTXToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args, return DAL; } -// Select remangled libclc variant. 64-bit longs default, 32-bit longs on -// Windows -static const char *getLibSpirvTargetName(const ToolChain &HostTC) { - if (HostTC.getTriple().isOSWindows()) - return "remangled-l32-signed_char.libspirv-nvptx64-nvidia-cuda.bc"; - return "remangled-l64-signed_char.libspirv-nvptx64-nvidia-cuda.bc"; -} - void NVPTXToolChain::addClangTargetOptions( const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, Action::OffloadKind DeviceOffloadingKind) const {} @@ -970,6 +962,9 @@ void CudaToolChain::addClangTargetOptions( options::OPT_fno_sycl_id_queries_fit_in_int, false)) CC1Args.append( {"-mllvm", "-nvvm-reflect-add=__CUDA_ID_QUERIES_FIT_IN_INT=1"}); + + SYCLInstallation.addLibspirvLinkArgs(getEffectiveTriple(), DriverArgs, + HostTC.getTriple(), CC1Args); } else { CC1Args.append({"-fcuda-is-device", "-mllvm", "-enable-memcpyopt-without-libcalls", @@ -988,53 +983,6 @@ void CudaToolChain::addClangTargetOptions( CC1Args.append({"-std=c++17", "-fsycl-is-host"}); } - auto NoLibSpirv = DriverArgs.hasArg(options::OPT_fno_sycl_libspirv) || - getDriver().offloadDeviceOnly(); - if (DeviceOffloadingKind == Action::OFK_SYCL && !NoLibSpirv) { - std::string LibSpirvFile; - - if (DriverArgs.hasArg(clang::driver::options::OPT_fsycl_libspirv_path_EQ)) { - auto ProvidedPath = - DriverArgs.getLastArgValue(clang::driver::options::OPT_fsycl_libspirv_path_EQ).str(); - if (llvm::sys::fs::exists(ProvidedPath)) - LibSpirvFile = ProvidedPath; - } else { - SmallVector LibraryPaths; - - // Expected path w/out install. - SmallString<256> WithoutInstallPath(getDriver().ResourceDir); - llvm::sys::path::append(WithoutInstallPath, Twine("../../clc")); - LibraryPaths.emplace_back(WithoutInstallPath.c_str()); - - // Expected path w/ install. - SmallString<256> WithInstallPath(getDriver().ResourceDir); - llvm::sys::path::append(WithInstallPath, Twine("../../../share/clc")); - LibraryPaths.emplace_back(WithInstallPath.c_str()); - - // Select remangled libclc variant - std::string LibSpirvTargetName = getLibSpirvTargetName(HostTC); - - for (StringRef LibraryPath : LibraryPaths) { - SmallString<128> LibSpirvTargetFile(LibraryPath); - llvm::sys::path::append(LibSpirvTargetFile, LibSpirvTargetName); - if (llvm::sys::fs::exists(LibSpirvTargetFile) || - DriverArgs.hasArg(options::OPT__HASH_HASH_HASH)) { - LibSpirvFile = std::string(LibSpirvTargetFile.str()); - break; - } - } - } - - if (LibSpirvFile.empty()) { - getDriver().Diag(diag::err_drv_no_sycl_libspirv) - << getLibSpirvTargetName(HostTC); - return; - } - - CC1Args.push_back("-mlink-builtin-bitcode"); - CC1Args.push_back(DriverArgs.MakeArgString(LibSpirvFile)); - } - if (DriverArgs.hasFlag(options::OPT_fcuda_short_ptr, options::OPT_fno_cuda_short_ptr, false)) CC1Args.append({"-mllvm", "--nvptx-short-ptr"}); diff --git a/clang/lib/Driver/ToolChains/HIPAMD.cpp b/clang/lib/Driver/ToolChains/HIPAMD.cpp index 6f7d1d9fcf2a1..bd2c7cadb240f 100644 --- a/clang/lib/Driver/ToolChains/HIPAMD.cpp +++ b/clang/lib/Driver/ToolChains/HIPAMD.cpp @@ -222,10 +222,6 @@ HIPAMDToolChain::HIPAMDToolChain(const Driver &D, const llvm::Triple &Triple, diagnoseUnsupportedSanitizers(Args); } -static const char *getLibSpirvTargetName(const ToolChain &HostTC) { - return "remangled-l64-signed_char.libspirv-amdgcn-amd-amdhsa.bc"; -} - void HIPAMDToolChain::addClangTargetOptions( const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, Action::OffloadKind DeviceOffloadingKind) const { @@ -274,53 +270,8 @@ void HIPAMDToolChain::addClangTargetOptions( if (DeviceOffloadingKind == Action::OFK_SYCL) { SYCLInstallation.addSYCLIncludeArgs(DriverArgs, CC1Args); - } - - auto NoLibSpirv = DriverArgs.hasArg(options::OPT_fno_sycl_libspirv) || - getDriver().offloadDeviceOnly(); - if (DeviceOffloadingKind == Action::OFK_SYCL && !NoLibSpirv) { - std::string LibSpirvFile; - - if (DriverArgs.hasArg(clang::driver::options::OPT_fsycl_libspirv_path_EQ)) { - auto ProvidedPath = - DriverArgs - .getLastArgValue( - clang::driver::options::OPT_fsycl_libspirv_path_EQ) - .str(); - if (llvm::sys::fs::exists(ProvidedPath)) - LibSpirvFile = ProvidedPath; - } else { - SmallVector LibraryPaths; - - // Expected path w/out install. - SmallString<256> WithoutInstallPath(getDriver().ResourceDir); - llvm::sys::path::append(WithoutInstallPath, Twine("../../clc")); - LibraryPaths.emplace_back(WithoutInstallPath.c_str()); - - // Expected path w/ install. - SmallString<256> WithInstallPath(getDriver().ResourceDir); - llvm::sys::path::append(WithInstallPath, Twine("../../../share/clc")); - LibraryPaths.emplace_back(WithInstallPath.c_str()); - - std::string LibSpirvTargetName = getLibSpirvTargetName(HostTC); - for (StringRef LibraryPath : LibraryPaths) { - SmallString<128> LibSpirvTargetFile(LibraryPath); - llvm::sys::path::append(LibSpirvTargetFile, LibSpirvTargetName); - if (llvm::sys::fs::exists(LibSpirvTargetFile)) { - LibSpirvFile = std::string(LibSpirvTargetFile.str()); - break; - } - } - } - - if (LibSpirvFile.empty()) { - getDriver().Diag(diag::err_drv_no_sycl_libspirv) - << getLibSpirvTargetName(HostTC); - return; - } - - CC1Args.push_back("-mlink-builtin-bitcode"); - CC1Args.push_back(DriverArgs.MakeArgString(LibSpirvFile)); + SYCLInstallation.addLibspirvLinkArgs(getEffectiveTriple(), DriverArgs, + HostTC.getTriple(), CC1Args); } for (auto BCFile : getDeviceLibs(DriverArgs, DeviceOffloadingKind)) { diff --git a/clang/lib/Driver/ToolChains/SYCL.cpp b/clang/lib/Driver/ToolChains/SYCL.cpp index 459dfc5d8771b..164a4c297c369 100644 --- a/clang/lib/Driver/ToolChains/SYCL.cpp +++ b/clang/lib/Driver/ToolChains/SYCL.cpp @@ -149,6 +149,82 @@ SYCLInstallationDetector::SYCLInstallationDetector( const llvm::opt::ArgList &Args) : D(D) {} +static llvm::SmallString<64> +getLibSpirvBasename(const llvm::Triple &DeviceTriple, + const llvm::Triple &HostTriple) { + // Select remangled libclc variant. + // Decide long size based on host triple, because offloading targets are going + // to match that. + // All known windows environments except Cygwin use 32-bit long. + llvm::SmallString<64> Result(HostTriple.isOSWindows() && + !HostTriple.isWindowsCygwinEnvironment() + ? "remangled-l32-signed_char.libspirv-" + : "remangled-l64-signed_char.libspirv-"); + + Result.append(DeviceTriple.getTriple()); + Result.append(".bc"); + + return Result; +} + +const char *SYCLInstallationDetector::findLibspirvPath( + const llvm::Triple &DeviceTriple, const llvm::opt::ArgList &Args, + const llvm::Triple &HostTriple) const { + + // If -fsycl-libspirv-path= is specified, try to use that path directly. + if (Arg *A = Args.getLastArg(options::OPT_fsycl_libspirv_path_EQ)) { + if (llvm::sys::fs::exists(A->getValue())) + return A->getValue(); + + return nullptr; + } + + const SmallString<64> Basename = + getLibSpirvBasename(DeviceTriple, HostTriple); + auto searchAt = [&](StringRef Path, const Twine &a = "", const Twine &b = "", + const Twine &c = "", const Twine &d = "", + const Twine &e = "") -> const char * { + SmallString<128> LibraryPath(Path); + llvm::sys::path::append(LibraryPath, a, b, c, d); + llvm::sys::path::append(LibraryPath, e, Basename); + + if (Args.hasArgNoClaim(options::OPT__HASH_HASH_HASH) || + llvm::sys::fs::exists(LibraryPath)) + return Args.MakeArgString(LibraryPath); + + return nullptr; + }; + + // Otherwise, assume libclc is installed at the same prefix as clang + // Expected path w/out install. + if (const char *R = searchAt(D.ResourceDir, "..", "..", "clc")) + return R; + + // Expected path w/ install. + if (const char *R = searchAt(D.ResourceDir, "..", "..", "..", "share", "clc")) + return R; + + return nullptr; +} + +void SYCLInstallationDetector::addLibspirvLinkArgs( + const llvm::Triple &DeviceTriple, const llvm::opt::ArgList &DriverArgs, + const llvm::Triple &HostTriple, llvm::opt::ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_fno_sycl_libspirv) || + D.offloadDeviceOnly()) + return; + + if (const char *LibSpirvFile = + findLibspirvPath(DeviceTriple, DriverArgs, HostTriple)) { + CC1Args.push_back("-mlink-builtin-bitcode"); + CC1Args.push_back(LibSpirvFile); + return; + } + + D.Diag(diag::err_drv_no_sycl_libspirv) + << getLibSpirvBasename(DeviceTriple, HostTriple); +} + void SYCLInstallationDetector::getSYCLDeviceLibPath( llvm::SmallVector, 4> &DeviceLibPaths) const { for (const auto &IC : InstallationCandidates) { diff --git a/clang/lib/Driver/ToolChains/SYCL.h b/clang/lib/Driver/ToolChains/SYCL.h index 234876aec98c5..b08099babb5ce 100644 --- a/clang/lib/Driver/ToolChains/SYCL.h +++ b/clang/lib/Driver/ToolChains/SYCL.h @@ -130,6 +130,19 @@ class SYCLInstallationDetector { SYCLInstallationDetector(const Driver &D); SYCLInstallationDetector(const Driver &D, const llvm::Triple &HostTriple, const llvm::opt::ArgList &Args); + + /// \brief Find and return the path to the libspirv library for the target + /// \return The path to the libspirv library if found, otherwise nullptr. + /// The lifetime of the returned string is managed by \p Args. + const char *findLibspirvPath(const llvm::Triple &DeviceTriple, + const llvm::opt::ArgList &Args, + const llvm::Triple &HostTriple) const; + + void addLibspirvLinkArgs(const llvm::Triple &DeviceTriple, + const llvm::opt::ArgList &DriverArgs, + const llvm::Triple &HostTriple, + llvm::opt::ArgStringList &CC1Args) const; + void getSYCLDeviceLibPath( llvm::SmallVector, 4> &DeviceLibPaths) const; void addSYCLIncludeArgs(const llvm::opt::ArgList &DriverArgs, diff --git a/clang/test/Driver/sycl-libspirv-toolchain.cpp b/clang/test/Driver/sycl-libspirv-toolchain.cpp index 86aca07e0a3c1..1dc2ddf02cbe5 100644 --- a/clang/test/Driver/sycl-libspirv-toolchain.cpp +++ b/clang/test/Driver/sycl-libspirv-toolchain.cpp @@ -5,16 +5,19 @@ // RUN: %clang -### -fsycl -fsycl-targets=nvptx64-nvidia-cuda -nocudalib -target x86_64-unknown-windows-msvc %s 2>&1 \ // RUN: | FileCheck %s --check-prefixes=CHECK-WINDOWS +// RUN: %clang -### -fsycl -fsycl-targets=nvptx64-nvidia-cuda -nocudalib -target x86_64-unknown-windows-gnu %s 2>&1 \ +// RUN: | FileCheck %s --check-prefixes=CHECK-WINDOWS // CHECK-WINDOWS: "-cc1"{{.*}} "-fsycl-is-device"{{.*}} "-mlink-builtin-bitcode" "{{.*[\\/]}}remangled-l32-signed_char.libspirv-nvptx64-nvidia-cuda.bc" // // RUN: %clang -### -fsycl -fsycl-targets=nvptx64-nvidia-cuda -nocudalib -target x86_64-unknown-linux-gnu %s 2>&1 \ // RUN: | FileCheck %s --check-prefixes=CHECK-LINUX +// RUN: %clang -### -fsycl -fsycl-targets=nvptx64-nvidia-cuda -nocudalib -target x86_64-unknown-windows-cygnus %s 2>&1 \ +// RUN: | FileCheck %s --check-prefixes=CHECK-LINUX // CHECK-LINUX: "-cc1"{{.*}} "-fsycl-is-device"{{.*}} "-mlink-builtin-bitcode" "{{.*[\\/]}}remangled-l64-signed_char.libspirv-nvptx64-nvidia-cuda.bc" // -// AMDGCN wrongly uses 32-bit longs on Windows // 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 \ // RUN: | FileCheck %s --check-prefixes=CHECK-AMDGCN-WINDOWS -// CHECK-AMDGCN-WINDOWS: "-cc1"{{.*}} "-fsycl-is-device"{{.*}} "-mlink-builtin-bitcode" "{{.*[\\/]}}remangled-l64-signed_char.libspirv-amdgcn-amd-amdhsa.bc" +// CHECK-AMDGCN-WINDOWS: "-cc1"{{.*}} "-fsycl-is-device"{{.*}} "-mlink-builtin-bitcode" "{{.*[\\/]}}remangled-l32-signed_char.libspirv-amdgcn-amd-amdhsa.bc" // // RUN: %clang -### -fsycl -fsycl-device-only -fsycl-targets=nvptx64-nvidia-cuda -nocudalib %s 2>&1 \ // RUN: | FileCheck %s --check-prefixes=CHECK-DEVICE-ONLY @@ -38,10 +41,9 @@ // RUN: | FileCheck %s -DDIR=%{nonexistent_dir} --check-prefixes=CHECK-HHH-NONEXISTENT // CHECK-HHH-NONEXISTENT: "-cc1"{{.*}} "-fsycl-is-device"{{.*}} "-mlink-builtin-bitcode" "[[DIR]]{{.*[\\/]}}remangled-{{.*}}.libspirv-nvptx64-nvidia-cuda.bc" // -// But not for AMDGCN :^) -// RUN: not %clang -### -resource-dir %{nonexistent_dir} -fsycl -fsycl-targets=amdgcn-amd-amdhsa -Xsycl-target-backend --offload-arch=gfx908 -nogpulib %s 2>&1 \ -// RUN: | FileCheck %s -DDIR=%{nonexistent_dir} --check-prefixes=CHECK-AMDGCN-HHH-NONEXISTENT -// 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 +// RUN: %clang -### -resource-dir %{nonexistent_dir} -fsycl -fsycl-targets=amdgcn-amd-amdhsa -Xsycl-target-backend --offload-arch=gfx908 -nogpulib %s 2>&1 \ +// RUN: | FileCheck %s -DDIR=%{nonexistent_dir} --check-prefixes=CHECK-AMDGCN-HHH-NONEXISTENT +// CHECK-AMDGCN-HHH-NONEXISTENT: "-cc1"{{.*}} "-fsycl-is-device"{{.*}} "-mlink-builtin-bitcode" "[[DIR]]{{.*[\\/]}}remangled-{{.*}}.libspirv-amdgcn-amd-amdhsa.bc" // // `-fdriver-only` has no such special handling, so it will not find the file // RUN: not %clang -fdriver-only -resource-dir %{nonexistent_dir} -fsycl -fsycl-targets=nvptx64-nvidia-cuda -nocudalib %s 2>&1 \