Skip to content

[Driver][Offloader] Add getOffloadingDeviceToolChain function #176

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions clang/include/clang/Driver/Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,22 @@ class Driver {

/// @}

/// Retrieves a ToolChain for a particular device \p Target triple
///
/// \param[in] HostTC is the host ToolChain paired with the device
///
/// \param[in] Action (e.g. OFK_Cuda/OFK_OpenMP/OFK_SYCL) is an Offloading
/// action that is optionally passed to a ToolChain (used by CUDA, to specify
/// if it's used in conjunction with OpenMP)
///
/// Will cache ToolChains for the life of the driver object, and create them
/// on-demand.
const ToolChain &getOffloadingDeviceToolChain(const llvm::opt::ArgList &Args,
const llvm::Triple &Target,
const ToolChain &HostTC,
const Action::OffloadKind
&TargetDeviceOffloadKind) const;

/// Get bitmasks for which option flags to include and exclude based on
/// the driver mode.
std::pair<unsigned, unsigned> getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const;
Expand Down
116 changes: 73 additions & 43 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -621,29 +621,24 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
DeviceTripleStr =
HostTriple.isArch64Bit() ? "nvptx64-nvidia-cuda" : "nvptx-nvidia-cuda";
llvm::Triple CudaTriple(DeviceTripleStr);
// Use the CUDA and host triples as the key into the ToolChains map,
// because the device toolchain we create depends on both.
auto &CudaTC = ToolChains[CudaTriple.str() + "/" + HostTriple.str()];
if (!CudaTC) {
CudaTC = llvm::make_unique<toolchains::CudaToolChain>(
*this, CudaTriple, *HostTC, C.getInputArgs(), OFK);
}
C.addOffloadDeviceToolChain(CudaTC.get(), OFK);
// Use the CUDA and host triples as the key into the
// getOffloadingDeviceToolChain, because the device toolchain we
// create depends on both.
auto CudaTC = &getOffloadingDeviceToolChain(C.getInputArgs(), CudaTriple,
*HostTC, OFK);
C.addOffloadDeviceToolChain(CudaTC, OFK);
} else if (IsHIP) {
const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
const llvm::Triple &HostTriple = HostTC->getTriple();
StringRef DeviceTripleStr;
auto OFK = Action::OFK_HIP;
DeviceTripleStr = "amdgcn-amd-amdhsa";
llvm::Triple HIPTriple(DeviceTripleStr);
// Use the HIP and host triples as the key into the ToolChains map,
// because the device toolchain we create depends on both.
auto &HIPTC = ToolChains[HIPTriple.str() + "/" + HostTriple.str()];
if (!HIPTC) {
HIPTC = llvm::make_unique<toolchains::HIPToolChain>(
*this, HIPTriple, *HostTC, C.getInputArgs());
}
C.addOffloadDeviceToolChain(HIPTC.get(), OFK);
// Use the HIP and host triples as the key into
// getOffloadingDeviceToolChain, because the device toolchain we create
// depends on both.
auto HIPTC = &getOffloadingDeviceToolChain(C.getInputArgs(), HIPTriple,
*HostTC, OFK);
C.addOffloadDeviceToolChain(HIPTC, OFK);
}

//
Expand Down Expand Up @@ -695,12 +690,8 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
const ToolChain *HostTC =
C.getSingleOffloadToolChain<Action::OFK_Host>();
assert(HostTC && "Host toolchain should be always defined.");
auto &CudaTC =
ToolChains[TT.str() + "/" + HostTC->getTriple().normalize()];
if (!CudaTC)
CudaTC = llvm::make_unique<toolchains::CudaToolChain>(
*this, TT, *HostTC, C.getInputArgs(), Action::OFK_OpenMP);
TC = CudaTC.get();
TC = &getOffloadingDeviceToolChain(C.getInputArgs(), TT, *HostTC,
Action::OFK_OpenMP);
} else
TC = &getToolChain(C.getInputArgs(), TT);
C.addOffloadDeviceToolChain(TC, Action::OFK_OpenMP);
Expand Down Expand Up @@ -776,20 +767,20 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
FoundNormalizedTriples[NormalizedName] = Val;

// If the specified target is invalid, emit a diagnostic.
if (TT.getArch() == llvm::Triple::UnknownArch)
if (TT.getArch() == llvm::Triple::UnknownArch ||
!(TT.getArch() == llvm::Triple::spir ||
TT.getArch() == llvm::Triple::spir64))
Diag(clang::diag::err_drv_invalid_sycl_target) << Val;
else {
const ToolChain *HostTC =
C.getSingleOffloadToolChain<Action::OFK_Host>();
const llvm::Triple &HostTriple = HostTC->getTriple();
// Use the SYCL and host triples as the key into the ToolChains map,
// because the device toolchain we create depends on both.
auto &SYCLTC = ToolChains[TT.str() + "/" + HostTriple.str()];
if (!SYCLTC) {
SYCLTC = llvm::make_unique<toolchains::SYCLToolChain>(
*this, TT, *HostTC, C.getInputArgs());
}
C.addOffloadDeviceToolChain(SYCLTC.get(), Action::OFK_SYCL);
// Use the SYCL and host triples as the key into
// getOffloadingDeviceToolChain, because the device toolchain we
// create depends on both.
auto SYCLTC = &getOffloadingDeviceToolChain(C.getInputArgs(), TT,
*HostTC,
Action::OFK_SYCL);
C.addOffloadDeviceToolChain(SYCLTC, Action::OFK_SYCL);
}
}
} else {
Expand All @@ -805,21 +796,17 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
if (HasValidSYCLRuntime) {
const ToolChain *HostTC =
C.getSingleOffloadToolChain<Action::OFK_Host>();
const llvm::Triple &HostTriple = HostTC->getTriple();
llvm::Triple TT(TargetTriple);
TT.setArch(llvm::Triple::spir64);
TT.setVendor(llvm::Triple::UnknownVendor);
TT.setOS(llvm::Triple(llvm::sys::getProcessTriple()).getOS());
TT.setEnvironment(llvm::Triple::SYCLDevice);
// Use the SYCL and host triples as the key into the ToolChains map,
// because the device toolchain we create depends on both.
auto &SYCLTC = ToolChains[(TT.normalize() + Twine("/") +
HostTriple.normalize()).str()];
if (!SYCLTC) {
SYCLTC = llvm::make_unique<toolchains::SYCLToolChain>(
*this, TT, *HostTC, C.getInputArgs());
}
C.addOffloadDeviceToolChain(SYCLTC.get(), Action::OFK_SYCL);
// Use the SYCL and host triples as the key into
// getOffloadingDeviceToolChain, because the device toolchain we create
// depends on both.
auto SYCLTC = &getOffloadingDeviceToolChain(C.getInputArgs(), TT, *HostTC,
Action::OFK_SYCL);
C.addOffloadDeviceToolChain(SYCLTC, Action::OFK_SYCL);
}
}

Expand Down Expand Up @@ -5134,6 +5121,49 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
return *TC;
}

const ToolChain &Driver::getOffloadingDeviceToolChain(const ArgList &Args,
const llvm::Triple &Target, const ToolChain &HostTC,
const Action::OffloadKind &TargetDeviceOffloadKind) const {
// Use device / host triples as the key into the ToolChains map because the
// device ToolChain we create depends on both.
auto &TC = ToolChains[Target.str() + "/" + HostTC.getTriple().str()];
if (!TC) {
// Categorized by offload kind > arch rather than OS > arch like
// the normal getToolChain call, as it seems a reasonable way to categorize
// things.
switch (TargetDeviceOffloadKind) {
case Action::OFK_Cuda:
TC = llvm::make_unique<toolchains::CudaToolChain>(
*this, Target, HostTC, Args, TargetDeviceOffloadKind);
break;
case Action::OFK_HIP:
TC = llvm::make_unique<toolchains::HIPToolChain>(
*this, Target, HostTC, Args);
break;
case Action::OFK_OpenMP:
// omp + nvptx
TC = llvm::make_unique<toolchains::CudaToolChain>(
*this, Target, HostTC, Args, TargetDeviceOffloadKind);
break;
case Action::OFK_SYCL:
switch (Target.getArch()) {
case llvm::Triple::spir:
case llvm::Triple::spir64:
TC = llvm::make_unique<toolchains::SYCLToolChain>(
*this, Target, HostTC, Args);
break;
default:
break;
}
break;
default:
break;
}
}

return *TC;
}

bool Driver::ShouldUseClangCompiler(const JobAction &JA) const {
// Say "no" if there is not exactly one input of a type clang understands.
if (JA.size() != 1 ||
Expand Down
7 changes: 7 additions & 0 deletions clang/test/Driver/sycl-offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@

/// ###########################################################################

/// Check whether an invalid SYCL target is specified:
// RUN: %clang -### -fsycl -fsycl-targets=x86_64 %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHK-INVALID-REAL-TARGET %s
// CHK-INVALID-REAL-TARGET: error: SYCL target is invalid: 'x86_64'

/// ###########################################################################

/// Check warning for empty -fsycl-targets
// RUN: %clang -### -fsycl -fsycl-targets= %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHK-EMPTY-SYCLTARGETS %s
Expand Down