|
|
|
|
@@ -886,27 +886,21 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (IsCuda && !UseLLVMOffload) {
|
|
|
|
|
const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
|
|
|
|
|
const llvm::Triple &HostTriple = HostTC->getTriple();
|
|
|
|
|
auto OFK = Action::OFK_Cuda;
|
|
|
|
|
auto CudaTriple =
|
|
|
|
|
getNVIDIAOffloadTargetTriple(*this, C.getInputArgs(), HostTriple);
|
|
|
|
|
auto CudaTriple = getNVIDIAOffloadTargetTriple(
|
|
|
|
|
*this, C.getInputArgs(), C.getDefaultToolChain().getTriple());
|
|
|
|
|
if (!CudaTriple)
|
|
|
|
|
return;
|
|
|
|
|
// 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 = std::make_unique<toolchains::CudaToolChain>(
|
|
|
|
|
*this, *CudaTriple, *HostTC, C.getInputArgs());
|
|
|
|
|
|
|
|
|
|
// Emit a warning if the detected CUDA version is too new.
|
|
|
|
|
CudaInstallationDetector &CudaInstallation =
|
|
|
|
|
static_cast<toolchains::CudaToolChain &>(*CudaTC).CudaInstallation;
|
|
|
|
|
if (CudaInstallation.isValid())
|
|
|
|
|
CudaInstallation.WarnIfUnsupportedVersion();
|
|
|
|
|
}
|
|
|
|
|
C.addOffloadDeviceToolChain(CudaTC.get(), OFK);
|
|
|
|
|
auto &TC =
|
|
|
|
|
getOffloadToolChain(C.getInputArgs(), Action::OFK_Cuda, *CudaTriple,
|
|
|
|
|
C.getDefaultToolChain().getTriple());
|
|
|
|
|
|
|
|
|
|
// Emit a warning if the detected CUDA version is too new.
|
|
|
|
|
const CudaInstallationDetector &CudaInstallation =
|
|
|
|
|
static_cast<const toolchains::CudaToolChain &>(TC).CudaInstallation;
|
|
|
|
|
if (CudaInstallation.isValid())
|
|
|
|
|
CudaInstallation.WarnIfUnsupportedVersion();
|
|
|
|
|
C.addOffloadDeviceToolChain(&TC, Action::OFK_Cuda);
|
|
|
|
|
} else if (IsHIP && !UseLLVMOffload) {
|
|
|
|
|
if (auto *OMPTargetArg =
|
|
|
|
|
C.getInputArgs().getLastArg(options::OPT_fopenmp_targets_EQ)) {
|
|
|
|
|
@@ -914,14 +908,15 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
|
|
|
|
|
<< OMPTargetArg->getSpelling() << "HIP";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
|
|
|
|
|
auto OFK = Action::OFK_HIP;
|
|
|
|
|
|
|
|
|
|
auto HIPTriple = getHIPOffloadTargetTriple(*this, C.getInputArgs());
|
|
|
|
|
if (!HIPTriple)
|
|
|
|
|
return;
|
|
|
|
|
auto *HIPTC = &getOffloadingDeviceToolChain(C.getInputArgs(), *HIPTriple,
|
|
|
|
|
*HostTC, OFK);
|
|
|
|
|
C.addOffloadDeviceToolChain(HIPTC, OFK);
|
|
|
|
|
|
|
|
|
|
auto &TC =
|
|
|
|
|
getOffloadToolChain(C.getInputArgs(), Action::OFK_HIP, *HIPTriple,
|
|
|
|
|
C.getDefaultToolChain().getTriple());
|
|
|
|
|
C.addOffloadDeviceToolChain(&TC, Action::OFK_HIP);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (IsCuda || IsHIP)
|
|
|
|
|
@@ -1038,40 +1033,17 @@ 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) {
|
|
|
|
|
Diag(clang::diag::err_drv_invalid_omp_target) << Val;
|
|
|
|
|
else {
|
|
|
|
|
const ToolChain *TC;
|
|
|
|
|
// Device toolchains have to be selected differently. They pair host
|
|
|
|
|
// and device in their implementation.
|
|
|
|
|
if (TT.isNVPTX() || TT.isAMDGCN() || TT.isSPIRV()) {
|
|
|
|
|
const ToolChain *HostTC =
|
|
|
|
|
C.getSingleOffloadToolChain<Action::OFK_Host>();
|
|
|
|
|
assert(HostTC && "Host toolchain should be always defined.");
|
|
|
|
|
auto &DeviceTC =
|
|
|
|
|
ToolChains[TT.str() + "/" + HostTC->getTriple().normalize()];
|
|
|
|
|
if (!DeviceTC) {
|
|
|
|
|
if (TT.isNVPTX())
|
|
|
|
|
DeviceTC = std::make_unique<toolchains::CudaToolChain>(
|
|
|
|
|
*this, TT, *HostTC, C.getInputArgs());
|
|
|
|
|
else if (TT.isAMDGCN())
|
|
|
|
|
DeviceTC = std::make_unique<toolchains::AMDGPUOpenMPToolChain>(
|
|
|
|
|
*this, TT, *HostTC, C.getInputArgs());
|
|
|
|
|
else if (TT.isSPIRV())
|
|
|
|
|
DeviceTC = std::make_unique<toolchains::SPIRVOpenMPToolChain>(
|
|
|
|
|
*this, TT, *HostTC, C.getInputArgs());
|
|
|
|
|
else
|
|
|
|
|
assert(DeviceTC && "Device toolchain not defined.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TC = DeviceTC.get();
|
|
|
|
|
} else
|
|
|
|
|
TC = &getToolChain(C.getInputArgs(), TT);
|
|
|
|
|
C.addOffloadDeviceToolChain(TC, Action::OFK_OpenMP);
|
|
|
|
|
auto It = DerivedArchs.find(TT.getTriple());
|
|
|
|
|
if (It != DerivedArchs.end())
|
|
|
|
|
KnownArchs[TC] = It->second;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto &TC = getOffloadToolChain(C.getInputArgs(), Action::OFK_OpenMP, TT,
|
|
|
|
|
C.getDefaultToolChain().getTriple());
|
|
|
|
|
C.addOffloadDeviceToolChain(&TC, Action::OFK_OpenMP);
|
|
|
|
|
auto It = DerivedArchs.find(TT.getTriple());
|
|
|
|
|
if (It != DerivedArchs.end())
|
|
|
|
|
KnownArchs[&TC] = It->second;
|
|
|
|
|
}
|
|
|
|
|
} else if (C.getInputArgs().hasArg(options::OPT_fopenmp_targets_EQ)) {
|
|
|
|
|
Diag(clang::diag::err_drv_expecting_fopenmp_with_fopenmp_targets);
|
|
|
|
|
@@ -1103,9 +1075,9 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
|
|
|
|
|
// getOffloadingDeviceToolChain, because the device toolchains we're
|
|
|
|
|
// going to create will depend on both.
|
|
|
|
|
const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
|
|
|
|
|
for (const auto &TargetTriple : UniqueSYCLTriplesVec) {
|
|
|
|
|
auto SYCLTC = &getOffloadingDeviceToolChain(
|
|
|
|
|
C.getInputArgs(), TargetTriple, *HostTC, Action::OFK_SYCL);
|
|
|
|
|
for (const auto &TT : UniqueSYCLTriplesVec) {
|
|
|
|
|
auto SYCLTC = &getOffloadToolChain(C.getInputArgs(), Action::OFK_SYCL, TT,
|
|
|
|
|
HostTC->getTriple());
|
|
|
|
|
C.addOffloadDeviceToolChain(SYCLTC, Action::OFK_SYCL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -6605,6 +6577,73 @@ std::string Driver::GetClPchPath(Compilation &C, StringRef BaseName) const {
|
|
|
|
|
return std::string(Output);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const ToolChain &Driver::getOffloadToolChain(
|
|
|
|
|
const llvm::opt::ArgList &Args, const Action::OffloadKind Kind,
|
|
|
|
|
const llvm::Triple &Target, const llvm::Triple &AuxTarget) const {
|
|
|
|
|
std::unique_ptr<ToolChain> &TC =
|
|
|
|
|
ToolChains[Target.str() + "/" + AuxTarget.str()];
|
|
|
|
|
std::unique_ptr<ToolChain> &HostTC = ToolChains[AuxTarget.str()];
|
|
|
|
|
|
|
|
|
|
assert(HostTC && "Host toolchain for offloading doesn't exit?");
|
|
|
|
|
if (!TC) {
|
|
|
|
|
// Detect the toolchain based off of the target operating system.
|
|
|
|
|
switch (Target.getOS()) {
|
|
|
|
|
case llvm::Triple::CUDA:
|
|
|
|
|
TC = std::make_unique<toolchains::CudaToolChain>(*this, Target, *HostTC,
|
|
|
|
|
Args);
|
|
|
|
|
break;
|
|
|
|
|
case llvm::Triple::AMDHSA:
|
|
|
|
|
if (Kind == Action::OFK_HIP)
|
|
|
|
|
TC = std::make_unique<toolchains::HIPAMDToolChain>(*this, Target,
|
|
|
|
|
*HostTC, Args);
|
|
|
|
|
else if (Kind == Action::OFK_OpenMP)
|
|
|
|
|
TC = std::make_unique<toolchains::AMDGPUOpenMPToolChain>(*this, Target,
|
|
|
|
|
*HostTC, Args);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!TC) {
|
|
|
|
|
// Detect the toolchain based off of the target architecture if that failed.
|
|
|
|
|
switch (Target.getArch()) {
|
|
|
|
|
case llvm::Triple::spir:
|
|
|
|
|
case llvm::Triple::spir64:
|
|
|
|
|
case llvm::Triple::spirv:
|
|
|
|
|
case llvm::Triple::spirv32:
|
|
|
|
|
case llvm::Triple::spirv64:
|
|
|
|
|
switch (Kind) {
|
|
|
|
|
case Action::OFK_SYCL:
|
|
|
|
|
TC = std::make_unique<toolchains::SYCLToolChain>(*this, Target, *HostTC,
|
|
|
|
|
Args);
|
|
|
|
|
break;
|
|
|
|
|
case Action::OFK_HIP:
|
|
|
|
|
TC = std::make_unique<toolchains::HIPSPVToolChain>(*this, Target,
|
|
|
|
|
*HostTC, Args);
|
|
|
|
|
break;
|
|
|
|
|
case Action::OFK_OpenMP:
|
|
|
|
|
TC = std::make_unique<toolchains::SPIRVOpenMPToolChain>(*this, Target,
|
|
|
|
|
*HostTC, Args);
|
|
|
|
|
break;
|
|
|
|
|
case Action::OFK_Cuda:
|
|
|
|
|
TC = std::make_unique<toolchains::CudaToolChain>(*this, Target, *HostTC,
|
|
|
|
|
Args);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If all else fails, just look up the normal toolchain for the target.
|
|
|
|
|
if (!TC)
|
|
|
|
|
return getToolChain(Args, Target);
|
|
|
|
|
return *TC;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const ToolChain &Driver::getToolChain(const ArgList &Args,
|
|
|
|
|
const llvm::Triple &Target) const {
|
|
|
|
|
|
|
|
|
|
@@ -6798,45 +6837,6 @@ 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_HIP: {
|
|
|
|
|
if (((Target.getArch() == llvm::Triple::amdgcn ||
|
|
|
|
|
Target.getArch() == llvm::Triple::spirv64) &&
|
|
|
|
|
Target.getVendor() == llvm::Triple::AMD &&
|
|
|
|
|
Target.getOS() == llvm::Triple::AMDHSA) ||
|
|
|
|
|
!Args.hasArgNoClaim(options::OPT_offload_EQ))
|
|
|
|
|
TC = std::make_unique<toolchains::HIPAMDToolChain>(*this, Target,
|
|
|
|
|
HostTC, Args);
|
|
|
|
|
else if (Target.getArch() == llvm::Triple::spirv64 &&
|
|
|
|
|
Target.getVendor() == llvm::Triple::UnknownVendor &&
|
|
|
|
|
Target.getOS() == llvm::Triple::UnknownOS)
|
|
|
|
|
TC = std::make_unique<toolchains::HIPSPVToolChain>(*this, Target,
|
|
|
|
|
HostTC, Args);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case Action::OFK_SYCL:
|
|
|
|
|
if (Target.isSPIROrSPIRV())
|
|
|
|
|
TC = std::make_unique<toolchains::SYCLToolChain>(*this, Target, HostTC,
|
|
|
|
|
Args);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
assert(TC && "Could not create offloading device tool chain.");
|
|
|
|
|
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 ||
|
|
|
|
|
|