r274781 - [CUDA] Check that our CUDA install supports the requested architectures.

Justin Lebar via cfe-commits cfe-commits at lists.llvm.org
Thu Jul 7 11:17:52 PDT 2016


Author: jlebar
Date: Thu Jul  7 13:17:52 2016
New Revision: 274781

URL: http://llvm.org/viewvc/llvm-project?rev=274781&view=rev
Log:
[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

Added:
    cfe/trunk/test/Driver/Inputs/CUDA_80/
    cfe/trunk/test/Driver/Inputs/CUDA_80/usr/
    cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/
    cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/
    cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/bin/
    cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/bin/.keep
    cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/include/
    cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/include/.keep
    cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/lib/
    cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/lib/.keep
    cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/lib64/
    cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/lib64/.keep
    cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/nvvm/
    cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/nvvm/libdevice/
    cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/nvvm/libdevice/libdevice.compute_20.10.bc
    cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/nvvm/libdevice/libdevice.compute_35.10.bc
    cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/version.txt
    cfe/trunk/test/Driver/cuda-version-check.cu
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td
    cfe/trunk/include/clang/Driver/Options.td
    cfe/trunk/lib/Driver/ToolChains.cpp
    cfe/trunk/lib/Driver/ToolChains.h
    cfe/trunk/lib/Driver/Tools.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td?rev=274781&r1=274780&r2=274781&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td Thu Jul  7 13:17:52 2016
@@ -26,6 +26,10 @@ def err_drv_cuda_bad_gpu_arch : Error<"U
 def err_drv_no_cuda_installation : Error<
   "cannot find CUDA installation.  Provide its path via --cuda-path, or pass "
   "-nocudainc to build without CUDA includes.">;
+def err_drv_cuda_version_too_low : Error<
+  "GPU arch %1 requires CUDA version at least %3, but installation at %0 is %2. "
+  "Use --cuda-path to specify a different CUDA install, or pass "
+  "--no-cuda-version-check.">;
 def err_drv_invalid_thread_model_for_target : Error<
   "invalid thread model '%0' in '%1' for this target">;
 def err_drv_invalid_linker_name : Error<

Modified: cfe/trunk/include/clang/Driver/Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=274781&r1=274780&r2=274781&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Options.td (original)
+++ cfe/trunk/include/clang/Driver/Options.td Thu Jul  7 13:17:52 2016
@@ -410,6 +410,9 @@ def cuda_gpu_arch_EQ : Joined<["--"], "c
   HelpText<"CUDA GPU architecture (e.g. sm_35).  May be specified more than once.">;
 def cuda_noopt_device_debug : Flag<["--"], "cuda-noopt-device-debug">,
   HelpText<"Enable device-side debug info generation. Disables ptxas optimizations.">;
+def no_cuda_version_check : Flag<["--"], "no-cuda-version-check">,
+  HelpText<"Don't error out if the detected version of the CUDA install is "
+           "too low for the requested CUDA gpu architecture.">;
 def no_cuda_noopt_device_debug : Flag<["--"], "no-cuda-noopt-device-debug">;
 def cuda_path_EQ : Joined<["--"], "cuda-path=">, Group<i_Group>,
   HelpText<"CUDA installation path">;

Modified: cfe/trunk/lib/Driver/ToolChains.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains.cpp?rev=274781&r1=274780&r2=274781&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains.cpp (original)
+++ cfe/trunk/lib/Driver/ToolChains.cpp Thu Jul  7 13:17:52 2016
@@ -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::GCCInstallationDetecto
     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::CudaInstallationDetect
       }
     }
 
+    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(con
   }
 }
 
+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 {

Modified: cfe/trunk/lib/Driver/ToolChains.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains.h?rev=274781&r1=274780&r2=274781&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains.h (original)
+++ cfe/trunk/lib/Driver/ToolChains.h Thu Jul  7 13:17:52 2016
@@ -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)

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=274781&r1=274780&r2=274781&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Thu Jul  7 13:17:52 2016
@@ -11146,6 +11146,12 @@ void NVPTX::Assembler::ConstructJob(Comp
   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,

Added: cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/bin/.keep
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/bin/.keep?rev=274781&view=auto
==============================================================================
    (empty)

Added: cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/include/.keep
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/include/.keep?rev=274781&view=auto
==============================================================================
    (empty)

Added: cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/lib/.keep
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/lib/.keep?rev=274781&view=auto
==============================================================================
    (empty)

Added: cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/lib64/.keep
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/lib64/.keep?rev=274781&view=auto
==============================================================================
    (empty)

Added: cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/nvvm/libdevice/libdevice.compute_20.10.bc
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/nvvm/libdevice/libdevice.compute_20.10.bc?rev=274781&view=auto
==============================================================================
    (empty)

Added: cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/nvvm/libdevice/libdevice.compute_35.10.bc
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/nvvm/libdevice/libdevice.compute_35.10.bc?rev=274781&view=auto
==============================================================================
    (empty)

Added: cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/version.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/version.txt?rev=274781&view=auto
==============================================================================
--- cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/version.txt (added)
+++ cfe/trunk/test/Driver/Inputs/CUDA_80/usr/local/cuda/version.txt Thu Jul  7 13:17:52 2016
@@ -0,0 +1 @@
+CUDA Version 8.0.42

Added: cfe/trunk/test/Driver/cuda-version-check.cu
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/cuda-version-check.cu?rev=274781&view=auto
==============================================================================
--- cfe/trunk/test/Driver/cuda-version-check.cu (added)
+++ cfe/trunk/test/Driver/cuda-version-check.cu Thu Jul  7 13:17:52 2016
@@ -0,0 +1,51 @@
+// REQUIRES: clang-driver
+// REQUIRES: x86-registered-target
+// REQUIRES: nvptx-registered-target
+
+// RUN: %clang -v -### --cuda-gpu-arch=sm_20 --sysroot=%S/Inputs/CUDA 2>&1 %s | \
+// RUN:    FileCheck %s --check-prefix=OK
+// RUN: %clang -v -### --cuda-gpu-arch=sm_20 --sysroot=%S/Inputs/CUDA_80 2>&1 %s | \
+// RUN:    FileCheck %s --check-prefix=OK
+// RUN: %clang -v -### --cuda-gpu-arch=sm_60 --sysroot=%S/Inputs/CUDA_80 2>&1 %s | \
+// RUN:    FileCheck %s --check-prefix=OK
+
+// The installation at Inputs/CUDA is CUDA 7.0, which doesn't support sm_60.
+// RUN: %clang -v -### --cuda-gpu-arch=sm_60 --sysroot=%S/Inputs/CUDA 2>&1 %s | \
+// RUN:    FileCheck %s --check-prefix=ERR_SM60
+
+// This should only complain about sm_60, not sm_35.
+// RUN: %clang -v -### --cuda-gpu-arch=sm_60 --cuda-gpu-arch=sm_35 \
+// RUN:    --sysroot=%S/Inputs/CUDA 2>&1 %s | \
+// RUN:    FileCheck %s --check-prefix=ERR_SM60 --check-prefix=OK_SM35
+
+// We should get two errors here, one for sm_60 and one for sm_61.
+// RUN: %clang -v -### --cuda-gpu-arch=sm_60 --cuda-gpu-arch=sm_61 \
+// RUN:    --sysroot=%S/Inputs/CUDA 2>&1 %s | \
+// RUN:    FileCheck %s --check-prefix=ERR_SM60 --check-prefix=ERR_SM61
+
+// We should still get an error if we pass -nocudainc, because this compilation
+// would invoke ptxas, and we do a version check on that, too.
+// RUN: %clang -v -### --cuda-gpu-arch=sm_60 -nocudainc --sysroot=%S/Inputs/CUDA 2>&1 %s | \
+// RUN:    FileCheck %s --check-prefix=ERR_SM60
+
+// If with -nocudainc and -E, we don't touch the CUDA install, so we
+// shouldn't get an error.
+// RUN: %clang -v -### -E --cuda-device-only --cuda-gpu-arch=sm_60 -nocudainc \
+// RUN:    --sysroot=%S/Inputs/CUDA 2>&1 %s | \
+// RUN:    FileCheck %s --check-prefix=OK
+
+// -nocuda-version-check should suppress all of these errors.
+// RUN: %clang -v -### --cuda-gpu-arch=sm_60 --sysroot=%S/Inputs/CUDA 2>&1 \
+// RUN:    -nocuda-version-check %s | \
+// RUN:    FileCheck %s --check-prefix=OK
+
+// OK-NOT: error: GPU arch
+
+// OK_SM35-NOT: error: GPU arch sm_35
+
+// We should only get one error per architecture.
+// ERR_SM60: error: GPU arch sm_60 {{.*}}
+// ERR_SM60-NOT: error: GPU arch sm_60
+
+// ERR_SM61: error: GPU arch sm_61 {{.*}}
+// ERR_SM61-NOT: error: GPU arch sm_61




More information about the cfe-commits mailing list