summaryrefslogtreecommitdiffstats
path: root/clang/lib/Driver
diff options
context:
space:
mode:
authorJustin Lebar <jlebar@google.com>2016-07-07 18:17:52 +0000
committerJustin Lebar <jlebar@google.com>2016-07-07 18:17:52 +0000
commitc43ad9ee5ac96f3e66cbfd063aa918db4d68b560 (patch)
tree1ed9c59ab95a3f8af604a292c6d2ec3d1bc8d62b /clang/lib/Driver
parent495f1a22af257cbfd484eaadded75de259b307bd (diff)
downloadbcm5719-llvm-c43ad9ee5ac96f3e66cbfd063aa918db4d68b560.tar.gz
bcm5719-llvm-c43ad9ee5ac96f3e66cbfd063aa918db4d68b560.zip
[CUDA] Check that our CUDA install supports the requested architectures.
Summary: Raise an error if you're using a CUDA installation that's too old for the requested architectures. In practice, this means that you need a CUDA 8 install to compile for sm_6*. Reviewers: tra Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D21869 llvm-svn: 274781
Diffstat (limited to 'clang/lib/Driver')
-rw-r--r--clang/lib/Driver/ToolChains.cpp67
-rw-r--r--clang/lib/Driver/ToolChains.h25
-rw-r--r--clang/lib/Driver/Tools.cpp6
3 files changed, 96 insertions, 2 deletions
diff --git a/clang/lib/Driver/ToolChains.cpp b/clang/lib/Driver/ToolChains.cpp
index 4aad388adc8..15e9cf18b63 100644
--- a/clang/lib/Driver/ToolChains.cpp
+++ b/clang/lib/Driver/ToolChains.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "ToolChains.h"
+#include "clang/Basic/Cuda.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
#include "clang/Basic/VirtualFileSystem.h"
@@ -1703,9 +1704,33 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
BiarchTripleAliases.push_back(BiarchTriple.str());
}
+// 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) {
+ if (!V.startswith("CUDA Version "))
+ return CudaVersion::UNKNOWN;
+ 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;
+ }
+ if (Major == 7 && Minor == 5)
+ return CudaVersion::CUDA_75;
+ if (Major == 8 && Minor == 0)
+ return CudaVersion::CUDA_80;
+ return CudaVersion::UNKNOWN;
+}
+
// \brief -- try common CUDA installation paths looking for files we need for
// CUDA compilation.
-
void Generic_GCC::CudaInstallationDetector::init(
const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args) {
SmallVector<std::string, 4> CudaPathCandidates;
@@ -1768,14 +1793,40 @@ void Generic_GCC::CudaInstallationDetector::init(
}
}
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> VersionFile =
+ FS.getBufferForFile(InstallPath + "/version.txt");
+ if (!VersionFile) {
+ // CUDA 7.0 doesn't have a version.txt, so guess that's our version if
+ // version.txt isn't present.
+ Version = CudaVersion::CUDA_70;
+ } else {
+ Version = ParseCudaVersionFile((*VersionFile)->getBuffer());
+ }
+
IsValid = true;
break;
}
}
+void Generic_GCC::CudaInstallationDetector::CheckCudaVersionSupportsArch(
+ CudaArch Arch) const {
+ if (Arch == CudaArch::UNKNOWN || Version == CudaVersion::UNKNOWN ||
+ ArchsWithVersionTooLowErrors.count(Arch) > 0)
+ return;
+
+ auto RequiredVersion = MinVersionForCudaArch(Arch);
+ if (Version < RequiredVersion) {
+ ArchsWithVersionTooLowErrors.insert(Arch);
+ D.Diag(diag::err_drv_cuda_version_too_low)
+ << InstallPath << CudaArchToString(Arch) << CudaVersionToString(Version)
+ << CudaVersionToString(RequiredVersion);
+ }
+}
+
void Generic_GCC::CudaInstallationDetector::print(raw_ostream &OS) const {
if (isValid())
- OS << "Found CUDA installation: " << InstallPath << "\n";
+ OS << "Found CUDA installation: " << InstallPath << ", version "
+ << CudaVersionToString(Version) << "\n";
}
namespace {
@@ -4670,6 +4721,18 @@ CudaToolChain::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
}
}
+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) &&
+ !DriverArgs.hasArg(options::OPT_nocuda_version_check)) {
+ StringRef Arch = DriverArgs.getLastArgValue(options::OPT_march_EQ);
+ assert(!Arch.empty() && "Must have an explicit GPU arch.");
+ CudaInstallation.CheckCudaVersionSupportsArch(StringToCudaArch(Arch));
+ }
+ Linux::AddCudaIncludeArgs(DriverArgs, CC1Args);
+}
+
llvm::opt::DerivedArgList *
CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
const char *BoundArch) const {
diff --git a/clang/lib/Driver/ToolChains.h b/clang/lib/Driver/ToolChains.h
index ed6329c7d1e..4e5c3f7f96a 100644
--- a/clang/lib/Driver/ToolChains.h
+++ b/clang/lib/Driver/ToolChains.h
@@ -11,12 +11,14 @@
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_H
#include "Tools.h"
+#include "clang/Basic/Cuda.h"
#include "clang/Basic/VersionTuple.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Multilib.h"
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/Support/Compiler.h"
#include <set>
#include <vector>
@@ -162,6 +164,7 @@ protected:
private:
const Driver &D;
bool IsValid = false;
+ CudaVersion Version = CudaVersion::UNKNOWN;
std::string InstallPath;
std::string BinPath;
std::string LibPath;
@@ -169,15 +172,27 @@ protected:
std::string IncludePath;
llvm::StringMap<std::string> LibDeviceMap;
+ // CUDA architectures for which we have raised an error in
+ // CheckCudaVersionSupportsArch.
+ mutable llvm::SmallSet<CudaArch, 4> ArchsWithVersionTooLowErrors;
+
public:
CudaInstallationDetector(const Driver &D) : D(D) {}
void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args);
+ /// \brief Emit an error if Version does not support the given Arch.
+ ///
+ /// If either Version or Arch is unknown, does not emit an error. Emits at
+ /// most one error per Arch.
+ void CheckCudaVersionSupportsArch(CudaArch Arch) const;
+
/// \brief Check whether we detected a valid Cuda install.
bool isValid() const { return IsValid; }
/// \brief Print information about the detected CUDA installation.
void print(raw_ostream &OS) const;
+ /// \brief Get the deteced Cuda install's version.
+ CudaVersion version() const { return Version; }
/// \brief Get the detected Cuda installation path.
StringRef getInstallPath() const { return InstallPath; }
/// \brief Get the detected path to Cuda's bin directory.
@@ -852,6 +867,16 @@ public:
// ptxas.
bool useIntegratedAs() const override { return false; }
+ void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+ const Generic_GCC::CudaInstallationDetector &cudaInstallation() const {
+ return CudaInstallation;
+ }
+ Generic_GCC::CudaInstallationDetector &cudaInstallation() {
+ return CudaInstallation;
+ }
+
protected:
Tool *buildAssembler() const override; // ptxas
Tool *buildLinker() const override; // fatbinary (ok, not really a linker)
diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp
index 14ed0d4e3ed..50a35882d9b 100644
--- a/clang/lib/Driver/Tools.cpp
+++ b/clang/lib/Driver/Tools.cpp
@@ -11146,6 +11146,12 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
assert(gpu_archs.size() == 1 && "Exactly one GPU Arch required for ptxas.");
const std::string& gpu_arch = gpu_archs[0];
+ // Check that our installation's ptxas supports gpu_arch.
+ if (!Args.hasArg(options::OPT_nocuda_version_check)) {
+ TC.cudaInstallation().CheckCudaVersionSupportsArch(
+ StringToCudaArch(gpu_arch));
+ }
+
ArgStringList CmdArgs;
CmdArgs.push_back(TC.getTriple().isArch64Bit() ? "-m64" : "-m32");
if (Args.hasFlag(options::OPT_cuda_noopt_device_debug,
OpenPOWER on IntegriCloud