[Clang][NFC] Clean up fetching the offloading toolchain (#125095)
Summary: This patch cleans up how we query the offloading toolchain. We create a single that is more similar to the existing `getToolChain` driver function and make all the offloading handlers use it.
This commit is contained in:
parent
8d925a1c72
commit
6e2f08b2f8
4 changed files with 104 additions and 112 deletions
|
|
@ -797,22 +797,14 @@ private:
|
|||
const ToolChain &getToolChain(const llvm::opt::ArgList &Args,
|
||||
const llvm::Triple &Target) const;
|
||||
|
||||
/// @}
|
||||
|
||||
/// Retrieves a ToolChain for a particular device \p Target triple
|
||||
///
|
||||
/// \param[in] HostTC is the host ToolChain paired with the device
|
||||
///
|
||||
/// \param[in] TargetDeviceOffloadKind (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)
|
||||
/// Retrieves a ToolChain for a particular \p Target triple for offloading.
|
||||
///
|
||||
/// 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;
|
||||
const ToolChain &getOffloadToolChain(const llvm::opt::ArgList &Args,
|
||||
const Action::OffloadKind Kind,
|
||||
const llvm::Triple &Target,
|
||||
const llvm::Triple &AuxTarget) const;
|
||||
|
||||
/// Get bitmasks for which option flags to include and exclude based on
|
||||
/// the driver mode.
|
||||
|
|
|
|||
|
|
@ -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 ||
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ CudaVersion parseCudaHFile(llvm::StringRef Input) {
|
|||
}
|
||||
} // namespace
|
||||
|
||||
void CudaInstallationDetector::WarnIfUnsupportedVersion() {
|
||||
void CudaInstallationDetector::WarnIfUnsupportedVersion() const {
|
||||
if (Version > CudaVersion::PARTIALLY_SUPPORTED) {
|
||||
std::string VersionString = CudaVersionToString(Version);
|
||||
if (!VersionString.empty())
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ public:
|
|||
std::string getLibDeviceFile(StringRef Gpu) const {
|
||||
return LibDeviceMap.lookup(Gpu);
|
||||
}
|
||||
void WarnIfUnsupportedVersion();
|
||||
void WarnIfUnsupportedVersion() const;
|
||||
};
|
||||
|
||||
namespace tools {
|
||||
|
|
|
|||
Loading…
Reference in a new issue