diff --git a/clang/include/clang/Basic/Cuda.h b/clang/include/clang/Basic/Cuda.h --- a/clang/include/clang/Basic/Cuda.h +++ b/clang/include/clang/Basic/Cuda.h @@ -33,8 +33,10 @@ CUDA_112, CUDA_113, CUDA_114, - LATEST = CUDA_114, - LATEST_SUPPORTED = CUDA_101, + FULLY_SUPPORTED = CUDA_101, + PARTIALLY_SUPPORTED = + CUDA_114, // Partially supported. Proceed with a warning. + NEW = 10000, // Too new. Issue a warning, but allow using it. }; const char *CudaVersionToString(CudaVersion V); // Input is "Major.Minor" diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -77,8 +77,11 @@ "but installation at %3 is %4; use '--cuda-path' to specify a different CUDA " "install, pass a different GPU arch with '--cuda-gpu-arch', or pass " "'--no-cuda-version-check'">; -def warn_drv_unknown_cuda_version: Warning< - "unknown CUDA version: %0; assuming the latest supported version %1">, +def warn_drv_new_cuda_version: Warning< + "CUDA version%0 is newer than the latest%select{| partially}1 supported version %2">, + InGroup; +def warn_drv_partially_supported_cuda_version: Warning< + "CUDA version %0 is only partially supported">, InGroup; def err_drv_cuda_host_arch : Error< "unsupported architecture '%0' for host compilation">; diff --git a/clang/lib/Basic/Cuda.cpp b/clang/lib/Basic/Cuda.cpp --- a/clang/lib/Basic/Cuda.cpp +++ b/clang/lib/Basic/Cuda.cpp @@ -40,6 +40,8 @@ return "11.3"; case CudaVersion::CUDA_114: return "11.4"; + case CudaVersion::NEW: + return ""; } llvm_unreachable("invalid enum"); } @@ -192,7 +194,7 @@ CudaVersion MaxVersionForCudaArch(CudaArch A) { // AMD GPUs do not depend on CUDA versions. if (IsAMDGpuArch(A)) - return CudaVersion::LATEST; + return CudaVersion::NEW; switch (A) { case CudaArch::UNKNOWN: @@ -203,7 +205,7 @@ case CudaArch::SM_30: return CudaVersion::CUDA_110; default: - return CudaVersion::LATEST; + return CudaVersion::NEW; } } diff --git a/clang/lib/Driver/ToolChains/Cuda.h b/clang/lib/Driver/ToolChains/Cuda.h --- a/clang/lib/Driver/ToolChains/Cuda.h +++ b/clang/lib/Driver/ToolChains/Cuda.h @@ -30,8 +30,6 @@ const Driver &D; bool IsValid = false; CudaVersion Version = CudaVersion::UNKNOWN; - std::string DetectedVersion; - bool DetectedVersionIsNotSupported = false; std::string InstallPath; std::string BinPath; std::string LibPath; @@ -62,7 +60,10 @@ void print(raw_ostream &OS) const; /// Get the detected Cuda install's version. - CudaVersion version() const { return Version; } + CudaVersion version() const { + return Version == CudaVersion::NEW ? CudaVersion::PARTIALLY_SUPPORTED + : Version; + } /// Get the detected Cuda installation path. StringRef getInstallPath() const { return InstallPath; } /// Get the detected path to Cuda's bin directory. diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp --- a/clang/lib/Driver/ToolChains/Cuda.cpp +++ b/clang/lib/Driver/ToolChains/Cuda.cpp @@ -17,6 +17,7 @@ #include "clang/Driver/InputInfo.h" #include "clang/Driver/Options.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" @@ -34,25 +35,6 @@ using namespace llvm::opt; namespace { -struct CudaVersionInfo { - std::string DetectedVersion; - CudaVersion Version; -}; -// 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". -CudaVersionInfo parseCudaVersionFile(llvm::StringRef V) { - V = V.trim(); - if (!V.startswith("CUDA Version ")) - return {V.str(), CudaVersion::UNKNOWN}; - V = V.substr(strlen("CUDA Version ")); - SmallVector VersionParts; - V.split(VersionParts, '.'); - return {"version.txt: " + V.str() + ".", - VersionParts.size() < 2 - ? CudaVersion::UNKNOWN - : CudaStringToVersion( - join_items(".", VersionParts[0], VersionParts[1]))}; -} CudaVersion getCudaVersion(uint32_t raw_version) { if (raw_version < 7050) @@ -83,10 +65,10 @@ return CudaVersion::CUDA_113; if (raw_version < 11050) return CudaVersion::CUDA_114; - return CudaVersion::LATEST; + return CudaVersion::NEW; } -CudaVersionInfo parseCudaHFile(llvm::StringRef Input) { +CudaVersion parseCudaHFile(llvm::StringRef Input) { // Helper lambda which skips the words if the line starts with them or returns // None otherwise. auto StartsWithWords = @@ -106,21 +88,27 @@ StartsWithWords(Input.ltrim(), {"#", "define", "CUDA_VERSION"})) { uint32_t RawVersion; Line->consumeInteger(10, RawVersion); - return {"cuda.h: CUDA_VERSION=" + Twine(RawVersion).str() + ".", - getCudaVersion(RawVersion)}; + return getCudaVersion(RawVersion); } // Find next non-empty line. Input = Input.drop_front(Input.find_first_of("\n\r")).ltrim(); } - return {"cuda.h: CUDA_VERSION not found.", CudaVersion::UNKNOWN}; + return CudaVersion::UNKNOWN; } } // namespace void CudaInstallationDetector::WarnIfUnsupportedVersion() { - if (DetectedVersionIsNotSupported) - D.Diag(diag::warn_drv_unknown_cuda_version) - << DetectedVersion - << CudaVersionToString(CudaVersion::LATEST_SUPPORTED); + if (Version > CudaVersion::PARTIALLY_SUPPORTED) { + std::string VersionString = CudaVersionToString(Version); + if (!VersionString.empty()) + VersionString.insert(0, " "); + D.Diag(diag::warn_drv_new_cuda_version) + << VersionString + << (CudaVersion::PARTIALLY_SUPPORTED != CudaVersion::FULLY_SUPPORTED) + << CudaVersionToString(CudaVersion::PARTIALLY_SUPPORTED); + } else if (Version > CudaVersion::FULLY_SUPPORTED) + D.Diag(diag::warn_drv_partially_supported_cuda_version) + << CudaVersionToString(Version); } CudaInstallationDetector::CudaInstallationDetector( @@ -212,30 +200,17 @@ else continue; - CudaVersionInfo VersionInfo = {"", CudaVersion::UNKNOWN}; - if (auto VersionFile = FS.getBufferForFile(InstallPath + "/version.txt")) - VersionInfo = parseCudaVersionFile((*VersionFile)->getBuffer()); - // If version file didn't give us the version, try to find it in cuda.h - if (VersionInfo.Version == CudaVersion::UNKNOWN) - if (auto CudaHFile = FS.getBufferForFile(InstallPath + "/include/cuda.h")) - VersionInfo = parseCudaHFile((*CudaHFile)->getBuffer()); - // As the last resort, make an educated guess between CUDA-7.0, (which had - // no version.txt file and had old-style libdevice bitcode ) and an unknown - // recent CUDA version (no version.txt, new style bitcode). - if (VersionInfo.Version == CudaVersion::UNKNOWN) { - VersionInfo.Version = (FS.exists(LibDevicePath + "/libdevice.10.bc")) - ? Version = CudaVersion::LATEST - : Version = CudaVersion::CUDA_70; - VersionInfo.DetectedVersion = "no version found in version.txt or cuda.h"; + Version = CudaVersion::UNKNOWN; + if (auto CudaHFile = FS.getBufferForFile(InstallPath + "/include/cuda.h")) + Version = parseCudaHFile((*CudaHFile)->getBuffer()); + // As the last resort, make an educated guess between CUDA-7.0, which had + // old-style libdevice bitcode, and an unknown recent CUDA version. + if (Version == CudaVersion::UNKNOWN) { + Version = FS.exists(LibDevicePath + "/libdevice.10.bc") + ? CudaVersion::NEW + : CudaVersion::CUDA_70; } - Version = VersionInfo.Version; - DetectedVersion = VersionInfo.DetectedVersion; - - // TODO(tra): remove the warning once we have all features of 10.2 - // and 11.0 implemented. - DetectedVersionIsNotSupported = Version > CudaVersion::LATEST_SUPPORTED; - if (Version >= CudaVersion::CUDA_90) { // CUDA-9+ uses single libdevice file for all GPU variants. std::string FilePath = LibDevicePath + "/libdevice.10.bc"; diff --git a/clang/test/Driver/Inputs/CUDA-new/usr/local/cuda/bin/.keep b/clang/test/Driver/Inputs/CUDA-new/usr/local/cuda/bin/.keep new file mode 100644 diff --git a/clang/test/Driver/Inputs/CUDA-new/usr/local/cuda/include/.keep b/clang/test/Driver/Inputs/CUDA-new/usr/local/cuda/include/.keep new file mode 100644 diff --git a/clang/test/Driver/Inputs/CUDA-new/usr/local/cuda/include/cuda.h b/clang/test/Driver/Inputs/CUDA-new/usr/local/cuda/include/cuda.h new file mode 100644 --- /dev/null +++ b/clang/test/Driver/Inputs/CUDA-new/usr/local/cuda/include/cuda.h @@ -0,0 +1,7 @@ +// +// Placeholder file for testing CUDA version detection +// + +#define CUDA_VERSION 99010 + +// diff --git a/clang/test/Driver/Inputs/CUDA-new/usr/local/cuda/lib/.keep b/clang/test/Driver/Inputs/CUDA-new/usr/local/cuda/lib/.keep new file mode 100644 diff --git a/clang/test/Driver/Inputs/CUDA-new/usr/local/cuda/lib64/.keep b/clang/test/Driver/Inputs/CUDA-new/usr/local/cuda/lib64/.keep new file mode 100644 diff --git a/clang/test/Driver/Inputs/CUDA-new/usr/local/cuda/nvvm/libdevice/libdevice.10.bc b/clang/test/Driver/Inputs/CUDA-new/usr/local/cuda/nvvm/libdevice/libdevice.10.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/CUDA-unknown/usr/local/cuda/version.txt b/clang/test/Driver/Inputs/CUDA-unknown/usr/local/cuda/version.txt deleted file mode 100644 --- a/clang/test/Driver/Inputs/CUDA-unknown/usr/local/cuda/version.txt +++ /dev/null @@ -1 +0,0 @@ -CUDA Version 999.999.999 diff --git a/clang/test/Driver/Inputs/CUDA_80/usr/local/cuda/include/cuda.h b/clang/test/Driver/Inputs/CUDA_80/usr/local/cuda/include/cuda.h new file mode 100644 --- /dev/null +++ b/clang/test/Driver/Inputs/CUDA_80/usr/local/cuda/include/cuda.h @@ -0,0 +1,7 @@ +// +// Placeholder file for testing CUDA version detection +// + +#define CUDA_VERSION 8000 + +// diff --git a/clang/test/Driver/Inputs/CUDA_80/usr/local/cuda/version.txt b/clang/test/Driver/Inputs/CUDA_80/usr/local/cuda/version.txt deleted file mode 100644 --- a/clang/test/Driver/Inputs/CUDA_80/usr/local/cuda/version.txt +++ /dev/null @@ -1 +0,0 @@ -CUDA Version 8.0.42 diff --git a/clang/test/Driver/Inputs/CUDA_90/usr/local/cuda/include/cuda.h b/clang/test/Driver/Inputs/CUDA_90/usr/local/cuda/include/cuda.h new file mode 100644 --- /dev/null +++ b/clang/test/Driver/Inputs/CUDA_90/usr/local/cuda/include/cuda.h @@ -0,0 +1,7 @@ +// +// Placeholder file for testing CUDA version detection +// + +#define CUDA_VERSION 9000 + +// diff --git a/clang/test/Driver/cuda-version-check.cu b/clang/test/Driver/cuda-version-check.cu --- a/clang/test/Driver/cuda-version-check.cu +++ b/clang/test/Driver/cuda-version-check.cu @@ -8,15 +8,12 @@ // RUN: FileCheck %s --check-prefix=OK // RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda 2>&1 %s | \ // RUN: FileCheck %s --check-prefix=OK -// Test version guess when no version.txt or cuda.h are found +// Test version guess when cuda.h has not been found // RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-path=%S/Inputs/CUDA-unknown/usr/local/cuda 2>&1 %s | \ // RUN: FileCheck %s --check-prefix=UNKNOWN_VERSION -// Unknown version with version.txt present -// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-path=%S/Inputs/CUDA_102/usr/local/cuda 2>&1 %s | \ -// RUN: FileCheck %s --check-prefix=UNKNOWN_VERSION_V -// Unknown version with no version.txt but with version info present in cuda.h -// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-path=%S/Inputs/CUDA_111/usr/local/cuda 2>&1 %s | \ -// RUN: FileCheck %s --check-prefix=UNKNOWN_VERSION_H +// Unknown version info present in cuda.h +// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-path=%S/Inputs/CUDA-new/usr/local/cuda 2>&1 %s | \ +// RUN: FileCheck %s --check-prefix=UNKNOWN_VERSION // Make sure that we don't warn about CUDA version during C++ compilation. // RUN: %clang --target=x86_64-linux -v -### -x c++ --cuda-gpu-arch=sm_60 \ // RUN: --cuda-path=%S/Inputs/CUDA-unknown/usr/local/cuda 2>&1 %s | \ @@ -66,13 +63,14 @@ // OK_SM35-NOT: error: GPU arch sm_35 // We should only get one error per architecture. +// ERR_SM20: error: GPU arch sm_20 {{.*}} +// ERR_SM20-NOT: error: GPU arch sm_20 + // 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 -// UNKNOWN_VERSION_V: unknown CUDA version: version.txt:{{.*}}; assuming the latest supported version -// UNKNOWN_VERSION_H: unknown CUDA version: cuda.h: CUDA_VERSION={{.*}}; assuming the latest supported version -// UNKNOWN_VERSION: unknown CUDA version: no version found in version.txt or cuda.h; assuming the latest supported version +// UNKNOWN_VERSION: CUDA version is newer than the latest{{.*}} supported version // UNKNOWN_VERSION_CXX-NOT: unknown CUDA version