Skip to content

Commit

Permalink
[SYCL][NVPTX] Obey -nocudalib when linking against libdevice (#15378)
Browse files Browse the repository at this point in the history
This commit also makes a clearer distinction in code between what NVPTX
and NativeCPU are required to link against.

It refactors some nearby code which was more complicated than it needed
to be.
  • Loading branch information
frasercrmck committed Sep 19, 2024
1 parent b6286e1 commit a9b870b
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 40 deletions.
67 changes: 27 additions & 40 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5564,7 +5564,7 @@ class OffloadingActionBuilder final {
SYCLDeviceLibLinked = addSYCLDeviceLibs(
TC, SYCLDeviceLibs, UseAOTLink,
C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment(),
IsSYCLNativeCPU, NativeCPULib);
IsSYCLNativeCPU, NativeCPULib, BoundArch);
}
JobAction *LinkSYCLLibs =
C.MakeAction<LinkJobAction>(SYCLDeviceLibs, types::TY_LLVM_BC);
Expand Down Expand Up @@ -5842,7 +5842,7 @@ class OffloadingActionBuilder final {

bool addSYCLDeviceLibs(const ToolChain *TC, ActionList &DeviceLinkObjects,
bool isSpirvAOT, bool isMSVCEnv, bool isNativeCPU,
Action *&NativeCPULib) {
Action *&NativeCPULib, const char *BoundArch) {
int NumOfDeviceLibLinked = 0;
SmallVector<SmallString<128>, 4> LibLocCandidates;
SYCLInstallation.getSYCLDeviceLibPath(LibLocCandidates);
Expand All @@ -5852,14 +5852,10 @@ class OffloadingActionBuilder final {
tools::SYCL::getDeviceLibraries(C, TC->getTriple(), isSpirvAOT);

for (const auto &DeviceLib : DeviceLibraries) {
bool LibLocSelected = false;
for (const auto &LLCandidate : LibLocCandidates) {
if (LibLocSelected)
break;
SmallString<128> LibName(LLCandidate);
llvm::sys::path::append(LibName, DeviceLib);
if (llvm::sys::fs::exists(LibName)) {

// NativeCPU currently only needs libsycl-nativecpu_utils and
// libclc, so temporarily skip other device libs in invocation.
// Todo: remove once NativeCPU tests the other libraries.
Expand Down Expand Up @@ -5897,8 +5893,6 @@ class OffloadingActionBuilder final {
C.MakeAction<InputAction>(*InputArg, types::TY_LLVM_BC);
DeviceLinkObjects.push_back(SYCLDeviceLibsInputAction);
}
if (!LibLocSelected)
LibLocSelected = !LibLocSelected;

// The device link stage may remove symbols not referenced in the
// source code. Since libsycl-nativecpu_utils contains such symbols
Expand All @@ -5909,22 +5903,26 @@ class OffloadingActionBuilder final {
NativeCPULib = DeviceLinkObjects.back();
DeviceLinkObjects.pop_back();
}

break;
}
}
}

// For NVPTX backend we need to also link libclc and CUDA libdevice
// at the same stage that we link all of the unbundled SYCL libdevice
// objects together.
if ((TC->getTriple().isNVPTX() || isNativeCPU) && NumOfDeviceLibLinked) {
if (!NumOfDeviceLibLinked)
return false;

// 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<StringRef, 8> LibraryPaths;
SmallVector<StringRef, 2> LibraryPaths;

// Expected path w/out install.
SmallString<256> WithoutInstallPath(C.getDriver().ResourceDir);
Expand All @@ -5936,22 +5934,17 @@ class OffloadingActionBuilder final {
llvm::sys::path::append(WithInstallPath, Twine("../../../share/clc"));
LibraryPaths.emplace_back(WithInstallPath.c_str());

// TODO: check if the isNVPTX() path can also use
// TC->getTripleString() so that the conditional could be removed
const std::string TrStr =
isNativeCPU ? TC->getTripleString() : "nvptx64-nvidia-cuda";

// Select remangled libclc variant
StringRef LibSpirvTargetNamePref =
TC->getAuxTriple()->isOSWindows()
? "remangled-l32-signed_char.libspirv-"
: "remangled-l64-signed_char.libspirv-";
llvm::Twine LibSpirvTargetNameTemp = LibSpirvTargetNamePref + TrStr;
llvm::Twine LibSpirvTargetName = LibSpirvTargetNameTemp + ".bc";

for (StringRef LibraryPath : LibraryPaths) {
SmallString<128> LibSpirvTargetFile(LibraryPath);
llvm::sys::path::append(LibSpirvTargetFile, LibSpirvTargetName);
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());
Expand All @@ -5966,30 +5959,24 @@ class OffloadingActionBuilder final {
C.MakeAction<InputAction>(*LibClcInputArg, types::TY_LLVM_BC);
DeviceLinkObjects.push_back(SYCLLibClcInputAction);
}
}

if (isNativeCPU) {
// return here to not generate cuda actions
return NumOfDeviceLibLinked != 0;
}

// For NVPTX we also need to link with the CUDA libdevice
if (TC->getTriple().isNVPTX() && !Args.hasArg(options::OPT_nogpulib)) {
const toolchains::CudaToolChain *CudaTC =
static_cast<const toolchains::CudaToolChain *>(TC);
for (const auto &LinkInputEnum : enumerate(DeviceLinkerInputs)) {
const char *BoundArch =
SYCLTargetInfoList[LinkInputEnum.index()].BoundArch;
std::string LibDeviceFile =
CudaTC->CudaInstallation.getLibDeviceFile(BoundArch);
if (!LibDeviceFile.empty()) {
Arg *CudaDeviceLibInputArg =
MakeInputArg(Args, C.getDriver().getOpts(),
Args.MakeArgString(LibDeviceFile));
auto *SYCLDeviceLibInputAction = C.MakeAction<InputAction>(
*CudaDeviceLibInputArg, types::TY_LLVM_BC);
DeviceLinkObjects.push_back(SYCLDeviceLibInputAction);
}
std::string LibDeviceFile =
CudaTC->CudaInstallation.getLibDeviceFile(BoundArch);
if (!LibDeviceFile.empty()) {
Arg *CudaDeviceLibInputArg = MakeInputArg(
Args, C.getDriver().getOpts(), Args.MakeArgString(LibDeviceFile));
auto *SYCLDeviceLibInputAction = C.MakeAction<InputAction>(
*CudaDeviceLibInputArg, types::TY_LLVM_BC);
DeviceLinkObjects.push_back(SYCLDeviceLibInputAction);
}
}
return NumOfDeviceLibLinked != 0;

return true;
}

void appendLinkDependences(OffloadAction::DeviceDependences &DA) override {
Expand Down
7 changes: 7 additions & 0 deletions clang/test/Driver/sycl-nvptx-link.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@
// RUN: --sysroot=%S/Inputs/SYCL --cuda-path=%S/Inputs/CUDA_90/usr/local/cuda %s 2>&1 \
// RUN: | FileCheck %s --check-prefixes=CHECK,LIBDEVICE10

// Check also that -nocudalib is obeyed
// RUN: %clang -### -fsycl -fsycl-targets=nvptx64-nvidia-cuda -nocudalib \
// RUN: -Xsycl-target-backend --cuda-gpu-arch=sm_35 \
// RUN: --sysroot=%S/Inputs/SYCL --cuda-path=%S/Inputs/CUDA_90/usr/local/cuda %s 2>&1 \
// RUN: | FileCheck %s --check-prefixes=CHECK,NOLIBDEVICE

// First link command: ignored
// CHECK: llvm-link

Expand All @@ -39,3 +45,4 @@
// LIBDEVICE30-SAME: libdevice.compute_30.10.bc
// LIBDEVICE35-SAME: libdevice.compute_35.10.bc
// LIBDEVICE50-SAME: libdevice.compute_50.10.bc
// NOLIBDEVICE-NOT: libdevice.{{.*}}.10.bc

0 comments on commit a9b870b

Please sign in to comment.