diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1139,8 +1139,7 @@ // languages and accept other values such as CPU/GPU architectures, // offload kinds and target aliases. def offload_EQ : CommaJoined<["--"], "offload=">, Flags<[NoXarchOption]>, - HelpText<"Specify comma-separated list of offloading target triples" - " (HIP only)">; + HelpText<"Specify comma-separated list of offloading target triples">; // C++ Coroutines TS defm coroutines_ts : BoolFOption<"coroutines-ts", diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -102,39 +102,59 @@ using namespace llvm::opt; static llvm::Optional -getHIPOffloadTargetTriple(const Driver &D, const ArgList &Args) { - if (Args.hasArg(options::OPT_offload_EQ)) { - auto HIPOffloadTargets = Args.getAllArgValues(options::OPT_offload_EQ); - - // HIP compilation flow does not support multiple targets for now. We need - // the HIPActionBuilder (and possibly the CudaActionBuilder{,Base}too) to - // support multiple tool chains first. - switch (HIPOffloadTargets.size()) { +getOffloadTargetTriple(const Driver &D, const ArgList &Args) { + auto OffloadTargets = Args.getAllArgValues(options::OPT_offload_EQ); + // Offload compilation flow does not support multiple targets for now. We + // need the HIPActionBuilder (and possibly the CudaActionBuilder{,Base}too) + // to support multiple tool chains first. + switch (OffloadTargets.size()) { default: - D.Diag(diag::err_drv_only_one_offload_target_supported_in) << "HIP"; + D.Diag(diag::err_drv_only_one_offload_target_supported_in) << ""; return llvm::None; case 0: D.Diag(diag::err_drv_invalid_or_unsupported_offload_target) << ""; return llvm::None; case 1: break; - } - llvm::Triple TT(HIPOffloadTargets[0]); - if (TT.getArch() == llvm::Triple::amdgcn && - TT.getVendor() == llvm::Triple::AMD && - TT.getOS() == llvm::Triple::AMDHSA) - return TT; - if (TT.getArch() == llvm::Triple::spirv64 && - TT.getVendor() == llvm::Triple::UnknownVendor && - TT.getOS() == llvm::Triple::UnknownOS) - return TT; - D.Diag(diag::err_drv_invalid_or_unsupported_offload_target) - << HIPOffloadTargets[0]; - return llvm::None; } + return llvm::Triple(OffloadTargets[0]); +} - static const llvm::Triple T("amdgcn-amd-amdhsa"); // Default HIP triple. - return T; +static llvm::Optional +getNVIDIAOffloadTargetTriple(const Driver &D, const ArgList &Args, const llvm::Triple &HostTriple) { + if (!Args.hasArg(options::OPT_offload_EQ)) { + return llvm::Triple(HostTriple.isArch64Bit() ? "nvptx64-nvidia-cuda" : "nvptx-nvidia-cuda"); + } + auto TT = getOffloadTargetTriple(D, Args); + if (TT && + (TT->getArch() == llvm::Triple::spirv32 || + TT->getArch() == llvm::Triple::spirv64)) { + return TT; + } + D.Diag(diag::err_drv_invalid_or_unsupported_offload_target) + << TT->str(); + return llvm::None; +} +static llvm::Optional +getHIPOffloadTargetTriple(const Driver &D, const ArgList &Args) { + if (!Args.hasArg(options::OPT_offload_EQ)) { + static const llvm::Triple T("amdgcn-amd-amdhsa"); // Default HIP triple. + return T; + } + auto TT = getOffloadTargetTriple(D, Args); + if (!TT) + return llvm::None; + if (TT->getArch() == llvm::Triple::amdgcn && + TT->getVendor() == llvm::Triple::AMD && + TT->getOS() == llvm::Triple::AMDHSA) + return TT; + if (TT->getArch() == llvm::Triple::spirv64 && + TT->getVendor() == llvm::Triple::UnknownVendor && + TT->getOS() == llvm::Triple::UnknownOS) + return TT; + D.Diag(diag::err_drv_invalid_or_unsupported_offload_target) + << TT->str(); + return llvm::None; } // static @@ -704,17 +724,17 @@ if (IsCuda) { const ToolChain *HostTC = C.getSingleOffloadToolChain(); const llvm::Triple &HostTriple = HostTC->getTriple(); - StringRef DeviceTripleStr; auto OFK = Action::OFK_Cuda; - DeviceTripleStr = - HostTriple.isArch64Bit() ? "nvptx64-nvidia-cuda" : "nvptx-nvidia-cuda"; - llvm::Triple CudaTriple(DeviceTripleStr); + auto CudaTriple = + getNVIDIAOffloadTargetTriple(*this, C.getInputArgs(), HostTriple); + 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()]; + auto &CudaTC = ToolChains[CudaTriple->str() + "/" + HostTriple.str()]; if (!CudaTC) { CudaTC = std::make_unique( - *this, CudaTriple, *HostTC, C.getInputArgs(), OFK); + *this, *CudaTriple, *HostTC, C.getInputArgs(), OFK); } C.addOffloadDeviceToolChain(CudaTC.get(), OFK); } else if (IsHIP) { diff --git a/clang/test/Driver/cuda-device-triple.cu b/clang/test/Driver/cuda-device-triple.cu new file mode 100644 --- /dev/null +++ b/clang/test/Driver/cuda-device-triple.cu @@ -0,0 +1,8 @@ +// REQUIRES: clang-driver + +// RUN: %clang -### -emit-llvm --cuda-device-only \ +// RUN: -nocudalib -nocudainc --offload=spirv32-unknown-unknown -c %s 2>&1 | FileCheck %s + +// CHECK: clang{{.*}}" "-cc1" "-triple" "spirv32-unknown-unknown" {{.*}} "-fcuda-is-device" {{.*}} + +