summaryrefslogtreecommitdiff
path: root/clang/lib/Driver/ToolChains/Cuda.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Driver/ToolChains/Cuda.cpp')
-rw-r--r--clang/lib/Driver/ToolChains/Cuda.cpp242
1 files changed, 121 insertions, 121 deletions
diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp
index 02871d2ce411..110a0bca9bc1 100644
--- a/clang/lib/Driver/ToolChains/Cuda.cpp
+++ b/clang/lib/Driver/ToolChains/Cuda.cpp
@@ -18,9 +18,11 @@
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Host.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
+#include "llvm/Support/TargetParser.h"
#include "llvm/Support/VirtualFileSystem.h"
#include <system_error>
@@ -32,37 +34,33 @@ using namespace llvm::opt;
// Parses the contents of version.txt in an CUDA installation. It should
// contain one line of the from e.g. "CUDA Version 7.5.2".
-static CudaVersion ParseCudaVersionFile(llvm::StringRef V) {
+void CudaInstallationDetector::ParseCudaVersionFile(llvm::StringRef V) {
+ Version = CudaVersion::UNKNOWN;
if (!V.startswith("CUDA Version "))
- return CudaVersion::UNKNOWN;
+ return;
V = V.substr(strlen("CUDA Version "));
- int Major = -1, Minor = -1;
- auto First = V.split('.');
- auto Second = First.second.split('.');
- if (First.first.getAsInteger(10, Major) ||
- Second.first.getAsInteger(10, Minor))
- return CudaVersion::UNKNOWN;
-
- if (Major == 7 && Minor == 0) {
- // This doesn't appear to ever happen -- version.txt doesn't exist in the
- // CUDA 7 installs I've seen. But no harm in checking.
- return CudaVersion::CUDA_70;
+ SmallVector<StringRef,4> VersionParts;
+ V.split(VersionParts, '.');
+ if (VersionParts.size() < 2)
+ return;
+ DetectedVersion = join_items(".", VersionParts[0], VersionParts[1]);
+ Version = CudaStringToVersion(DetectedVersion);
+ if (Version != CudaVersion::UNKNOWN) {
+ // TODO(tra): remove the warning once we have all features of 10.2 and 11.0
+ // implemented.
+ DetectedVersionIsNotSupported = Version > CudaVersion::LATEST_SUPPORTED;
+ return;
}
- if (Major == 7 && Minor == 5)
- return CudaVersion::CUDA_75;
- if (Major == 8 && Minor == 0)
- return CudaVersion::CUDA_80;
- if (Major == 9 && Minor == 0)
- return CudaVersion::CUDA_90;
- if (Major == 9 && Minor == 1)
- return CudaVersion::CUDA_91;
- if (Major == 9 && Minor == 2)
- return CudaVersion::CUDA_92;
- if (Major == 10 && Minor == 0)
- return CudaVersion::CUDA_100;
- if (Major == 10 && Minor == 1)
- return CudaVersion::CUDA_101;
- return CudaVersion::UNKNOWN;
+
+ Version = CudaVersion::LATEST_SUPPORTED;
+ DetectedVersionIsNotSupported = true;
+}
+
+void CudaInstallationDetector::WarnIfUnsupportedVersion() {
+ if (DetectedVersionIsNotSupported)
+ D.Diag(diag::warn_drv_unknown_cuda_version)
+ << DetectedVersion
+ << CudaVersionToString(CudaVersion::LATEST_SUPPORTED);
}
CudaInstallationDetector::CudaInstallationDetector(
@@ -80,6 +78,7 @@ CudaInstallationDetector::CudaInstallationDetector(
// In decreasing order so we prefer newer versions to older versions.
std::initializer_list<const char *> Versions = {"8.0", "7.5", "7.0"};
+ auto &FS = D.getVFS();
if (Args.hasArg(clang::driver::options::OPT_cuda_path_EQ)) {
Candidates.emplace_back(
@@ -106,8 +105,9 @@ CudaInstallationDetector::CudaInstallationDetector(
StringRef ptxasDir = llvm::sys::path::parent_path(ptxasAbsolutePath);
if (llvm::sys::path::filename(ptxasDir) == "bin")
- Candidates.emplace_back(llvm::sys::path::parent_path(ptxasDir),
- /*StrictChecking=*/true);
+ Candidates.emplace_back(
+ std::string(llvm::sys::path::parent_path(ptxasDir)),
+ /*StrictChecking=*/true);
}
}
@@ -115,7 +115,7 @@ CudaInstallationDetector::CudaInstallationDetector(
for (const char *Ver : Versions)
Candidates.emplace_back(D.SysRoot + "/usr/local/cuda-" + Ver);
- Distro Dist(D.getVFS(), llvm::Triple(llvm::sys::getProcessTriple()));
+ Distro Dist(FS, llvm::Triple(llvm::sys::getProcessTriple()));
if (Dist.IsDebian() || Dist.IsUbuntu())
// Special case for Debian to have nvidia-cuda-toolkit work
// out of the box. More info on http://bugs.debian.org/882505
@@ -126,14 +126,13 @@ CudaInstallationDetector::CudaInstallationDetector(
for (const auto &Candidate : Candidates) {
InstallPath = Candidate.Path;
- if (InstallPath.empty() || !D.getVFS().exists(InstallPath))
+ if (InstallPath.empty() || !FS.exists(InstallPath))
continue;
BinPath = InstallPath + "/bin";
IncludePath = InstallPath + "/include";
LibDevicePath = InstallPath + "/nvvm/libdevice";
- auto &FS = D.getVFS();
if (!(FS.exists(IncludePath) && FS.exists(BinPath)))
continue;
bool CheckLibDevice = (!NoCudaLib || Candidate.StrictChecking);
@@ -160,25 +159,26 @@ CudaInstallationDetector::CudaInstallationDetector(
// version.txt isn't present.
Version = CudaVersion::CUDA_70;
} else {
- Version = ParseCudaVersionFile((*VersionFile)->getBuffer());
+ ParseCudaVersionFile((*VersionFile)->getBuffer());
}
if (Version >= CudaVersion::CUDA_90) {
// CUDA-9+ uses single libdevice file for all GPU variants.
std::string FilePath = LibDevicePath + "/libdevice.10.bc";
if (FS.exists(FilePath)) {
- for (const char *GpuArchName :
- {"sm_30", "sm_32", "sm_35", "sm_37", "sm_50", "sm_52", "sm_53",
- "sm_60", "sm_61", "sm_62", "sm_70", "sm_72", "sm_75"}) {
- const CudaArch GpuArch = StringToCudaArch(GpuArchName);
- if (Version >= MinVersionForCudaArch(GpuArch) &&
- Version <= MaxVersionForCudaArch(GpuArch))
- LibDeviceMap[GpuArchName] = FilePath;
+ for (int Arch = (int)CudaArch::SM_30, E = (int)CudaArch::LAST; Arch < E;
+ ++Arch) {
+ CudaArch GpuArch = static_cast<CudaArch>(Arch);
+ if (!IsNVIDIAGpuArch(GpuArch))
+ continue;
+ std::string GpuArchName(CudaArchToString(GpuArch));
+ LibDeviceMap[GpuArchName] = FilePath;
}
}
} else {
std::error_code EC;
- for (llvm::sys::fs::directory_iterator LI(LibDevicePath, EC), LE;
+ for (llvm::vfs::directory_iterator LI = FS.dir_begin(LibDevicePath, EC),
+ LE;
!EC && LI != LE; LI = LI.increment(EC)) {
StringRef FilePath = LI->path();
StringRef FileName = llvm::sys::path::filename(FilePath);
@@ -194,27 +194,27 @@ CudaInstallationDetector::CudaInstallationDetector(
// capability. NVCC's choice of the libdevice library version is
// rather peculiar and depends on the CUDA version.
if (GpuArch == "compute_20") {
- LibDeviceMap["sm_20"] = FilePath;
- LibDeviceMap["sm_21"] = FilePath;
- LibDeviceMap["sm_32"] = FilePath;
+ LibDeviceMap["sm_20"] = std::string(FilePath);
+ LibDeviceMap["sm_21"] = std::string(FilePath);
+ LibDeviceMap["sm_32"] = std::string(FilePath);
} else if (GpuArch == "compute_30") {
- LibDeviceMap["sm_30"] = FilePath;
+ LibDeviceMap["sm_30"] = std::string(FilePath);
if (Version < CudaVersion::CUDA_80) {
- LibDeviceMap["sm_50"] = FilePath;
- LibDeviceMap["sm_52"] = FilePath;
- LibDeviceMap["sm_53"] = FilePath;
+ LibDeviceMap["sm_50"] = std::string(FilePath);
+ LibDeviceMap["sm_52"] = std::string(FilePath);
+ LibDeviceMap["sm_53"] = std::string(FilePath);
}
- LibDeviceMap["sm_60"] = FilePath;
- LibDeviceMap["sm_61"] = FilePath;
- LibDeviceMap["sm_62"] = FilePath;
+ LibDeviceMap["sm_60"] = std::string(FilePath);
+ LibDeviceMap["sm_61"] = std::string(FilePath);
+ LibDeviceMap["sm_62"] = std::string(FilePath);
} else if (GpuArch == "compute_35") {
- LibDeviceMap["sm_35"] = FilePath;
- LibDeviceMap["sm_37"] = FilePath;
+ LibDeviceMap["sm_35"] = std::string(FilePath);
+ LibDeviceMap["sm_37"] = std::string(FilePath);
} else if (GpuArch == "compute_50") {
if (Version >= CudaVersion::CUDA_80) {
- LibDeviceMap["sm_50"] = FilePath;
- LibDeviceMap["sm_52"] = FilePath;
- LibDeviceMap["sm_53"] = FilePath;
+ LibDeviceMap["sm_50"] = std::string(FilePath);
+ LibDeviceMap["sm_52"] = std::string(FilePath);
+ LibDeviceMap["sm_53"] = std::string(FilePath);
}
}
}
@@ -242,7 +242,7 @@ void CudaInstallationDetector::AddCudaIncludeArgs(
CC1Args.push_back(DriverArgs.MakeArgString(P));
}
- if (DriverArgs.hasArg(options::OPT_nocudainc))
+ if (DriverArgs.hasArg(options::OPT_nogpuinc))
return;
if (!isValid()) {
@@ -423,7 +423,11 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
Exec = A->getValue();
else
Exec = Args.MakeArgString(TC.GetProgramPath("ptxas"));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this,
+ ResponseFileSupport{ResponseFileSupport::RF_Full, llvm::sys::WEM_UTF8,
+ "--options-file"},
+ Exec, CmdArgs, Inputs));
}
static bool shouldIncludePTX(const ArgList &Args, const char *gpu_arch) {
@@ -477,10 +481,9 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA,
continue;
// We need to pass an Arch of the form "sm_XX" for cubin files and
// "compute_XX" for ptx.
- const char *Arch =
- (II.getType() == types::TY_PP_Asm)
- ? CudaVirtualArchToString(VirtualArchForCudaArch(gpu_arch))
- : gpu_arch_str;
+ const char *Arch = (II.getType() == types::TY_PP_Asm)
+ ? CudaArchToVirtualArchString(gpu_arch)
+ : gpu_arch_str;
CmdArgs.push_back(Args.MakeArgString(llvm::Twine("--image=profile=") +
Arch + ",file=" + II.getFilename()));
}
@@ -489,7 +492,11 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(A));
const char *Exec = Args.MakeArgString(TC.GetProgramPath("fatbinary"));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this,
+ ResponseFileSupport{ResponseFileSupport::RF_Full, llvm::sys::WEM_UTF8,
+ "--options-file"},
+ Exec, CmdArgs, Inputs));
}
void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -566,7 +573,11 @@ void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("nvlink"));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this,
+ ResponseFileSupport{ResponseFileSupport::RF_Full, llvm::sys::WEM_UTF8,
+ "--options-file"},
+ Exec, CmdArgs, Inputs));
}
/// CUDA toolchain. Our assembler is ptxas, and our "linker" is fatbinary,
@@ -578,8 +589,10 @@ CudaToolChain::CudaToolChain(const Driver &D, const llvm::Triple &Triple,
const Action::OffloadKind OK)
: ToolChain(D, Triple, Args), HostTC(HostTC),
CudaInstallation(D, HostTC.getTriple(), Args), OK(OK) {
- if (CudaInstallation.isValid())
- getProgramPaths().push_back(CudaInstallation.getBinPath());
+ if (CudaInstallation.isValid()) {
+ CudaInstallation.WarnIfUnsupportedVersion();
+ getProgramPaths().push_back(std::string(CudaInstallation.getBinPath()));
+ }
// Lookup binaries into the driver directory, this is used to
// discover the clang-offload-bundler executable.
getProgramPaths().push_back(getDriver().Dir);
@@ -596,7 +609,7 @@ std::string CudaToolChain::getInputFilename(const InputInfo &Input) const {
// these particular file names.
SmallString<256> Filename(ToolChain::getInputFilename(Input));
llvm::sys::path::replace_extension(Filename, "cubin");
- return Filename.str();
+ return std::string(Filename.str());
}
void CudaToolChain::addClangTargetOptions(
@@ -614,10 +627,6 @@ void CudaToolChain::addClangTargetOptions(
if (DeviceOffloadingKind == Action::OFK_Cuda) {
CC1Args.push_back("-fcuda-is-device");
- if (DriverArgs.hasFlag(options::OPT_fcuda_flush_denormals_to_zero,
- options::OPT_fno_cuda_flush_denormals_to_zero, false))
- CC1Args.push_back("-fcuda-flush-denormals-to-zero");
-
if (DriverArgs.hasFlag(options::OPT_fcuda_approx_transcendentals,
options::OPT_fno_cuda_approx_transcendentals, false))
CC1Args.push_back("-fcuda-approx-transcendentals");
@@ -648,24 +657,30 @@ void CudaToolChain::addClangTargetOptions(
// by new PTX version, so we need to raise PTX level to enable them in NVPTX
// back-end.
const char *PtxFeature = nullptr;
- switch(CudaInstallation.version()) {
- case CudaVersion::CUDA_101:
- PtxFeature = "+ptx64";
- break;
- case CudaVersion::CUDA_100:
- PtxFeature = "+ptx63";
- break;
- case CudaVersion::CUDA_92:
- PtxFeature = "+ptx61";
- break;
- case CudaVersion::CUDA_91:
- PtxFeature = "+ptx61";
- break;
- case CudaVersion::CUDA_90:
- PtxFeature = "+ptx60";
- break;
- default:
- PtxFeature = "+ptx42";
+ switch (CudaInstallation.version()) {
+ case CudaVersion::CUDA_110:
+ PtxFeature = "+ptx70";
+ break;
+ case CudaVersion::CUDA_102:
+ PtxFeature = "+ptx65";
+ break;
+ case CudaVersion::CUDA_101:
+ PtxFeature = "+ptx64";
+ break;
+ case CudaVersion::CUDA_100:
+ PtxFeature = "+ptx63";
+ break;
+ case CudaVersion::CUDA_92:
+ PtxFeature = "+ptx61";
+ break;
+ case CudaVersion::CUDA_91:
+ PtxFeature = "+ptx61";
+ break;
+ case CudaVersion::CUDA_90:
+ PtxFeature = "+ptx60";
+ break;
+ default:
+ PtxFeature = "+ptx42";
}
CC1Args.append({"-target-feature", PtxFeature});
if (DriverArgs.hasFlag(options::OPT_fcuda_short_ptr,
@@ -718,6 +733,21 @@ void CudaToolChain::addClangTargetOptions(
}
}
+llvm::DenormalMode CudaToolChain::getDefaultDenormalModeForType(
+ const llvm::opt::ArgList &DriverArgs, const JobAction &JA,
+ const llvm::fltSemantics *FPType) const {
+ if (JA.getOffloadingDeviceKind() == Action::OFK_Cuda) {
+ if (FPType && FPType == &llvm::APFloat::IEEEsingle() &&
+ DriverArgs.hasFlag(options::OPT_fcuda_flush_denormals_to_zero,
+ options::OPT_fno_cuda_flush_denormals_to_zero,
+ false))
+ return llvm::DenormalMode::getPreserveSign();
+ }
+
+ assert(JA.getOffloadingDeviceKind() != Action::OFK_Host);
+ return llvm::DenormalMode::getIEEE();
+}
+
bool CudaToolChain::supportsDebugInfoOption(const llvm::opt::Arg *A) const {
const Option &O = A->getOption();
return (O.matches(options::OPT_gN_Group) &&
@@ -748,7 +778,7 @@ void CudaToolChain::adjustDebugInfoKind(
void CudaToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
// Check our CUDA version if we're going to include the CUDA headers.
- if (!DriverArgs.hasArg(options::OPT_nocudainc) &&
+ if (!DriverArgs.hasArg(options::OPT_nogpuinc) &&
!DriverArgs.hasArg(options::OPT_no_cuda_version_check)) {
StringRef Arch = DriverArgs.getLastArgValue(options::OPT_march_EQ);
assert(!Arch.empty() && "Must have an explicit GPU arch.");
@@ -793,36 +823,6 @@ CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
}
for (Arg *A : Args) {
- if (A->getOption().matches(options::OPT_Xarch__)) {
- // Skip this argument unless the architecture matches BoundArch
- if (BoundArch.empty() || A->getValue(0) != BoundArch)
- continue;
-
- unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
- unsigned Prev = Index;
- std::unique_ptr<Arg> XarchArg(Opts.ParseOneArg(Args, Index));
-
- // If the argument parsing failed or more than one argument was
- // consumed, the -Xarch_ argument's parameter tried to consume
- // extra arguments. Emit an error and ignore.
- //
- // We also want to disallow any options which would alter the
- // driver behavior; that isn't going to work in our model. We
- // use isDriverOption() as an approximation, although things
- // like -O4 are going to slip through.
- if (!XarchArg || Index > Prev + 1) {
- getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args)
- << A->getAsString(Args);
- continue;
- } else if (XarchArg->getOption().hasFlag(options::DriverOption)) {
- getDriver().Diag(diag::err_drv_invalid_Xarch_argument_isdriver)
- << A->getAsString(Args);
- continue;
- }
- XarchArg->setBaseArg(A);
- A = XarchArg.release();
- DAL->AddSynthesizedArg(A);
- }
DAL->append(A);
}