[CUDA] Propagate detected version of CUDA to cc1

..and use it to control that parts of CUDA compilation
that depend on the specific version of CUDA SDK.

This patch has a placeholder for a 'new launch API' support
which is in a separate patch. The list will be further
extended in the upcoming patch to support CUDA-10.1.

Differential Revision: https://reviews.llvm.org/D57487

llvm-svn: 352798
This commit is contained in:
Artem Belevich 2019-01-31 21:32:24 +00:00
parent 4399878082
commit 8fa28a0db0
6 changed files with 104 additions and 6 deletions

View File

@ -11,6 +11,7 @@
namespace llvm {
class StringRef;
class VersionTuple;
} // namespace llvm
namespace clang {
@ -27,9 +28,8 @@ enum class CudaVersion {
LATEST = CUDA_100,
};
const char *CudaVersionToString(CudaVersion V);
// No string -> CudaVersion conversion function because there's no canonical
// spelling of the various CUDA versions.
// Input is "Major.Minor"
CudaVersion CudaStringToVersion(llvm::StringRef S);
enum class CudaArch {
UNKNOWN,
@ -103,6 +103,15 @@ CudaVersion MinVersionForCudaArch(CudaArch A);
/// Get the latest CudaVersion that supports the given CudaArch.
CudaVersion MaxVersionForCudaArch(CudaArch A);
// Various SDK-dependent features that affect CUDA compilation
enum class CudaFeature {
// CUDA-9.2+ uses a new API for launching kernels.
CUDA_USES_NEW_LAUNCH,
};
bool CudaFeatureEnabled(llvm::VersionTuple, CudaFeature);
bool CudaFeatureEnabled(CudaVersion, CudaFeature);
} // namespace clang
#endif

View File

@ -75,6 +75,11 @@ public:
std::string CodeModel;
/// The version of the SDK which was used during the compilation.
/// The option is used for two different purposes:
/// * on darwin the version is propagated to LLVM where it's used
/// to support SDK Version metadata (See D55673).
/// * CUDA compilation uses it to control parts of CUDA compilation
/// in clang that depend on specific version of the CUDA SDK.
llvm::VersionTuple SDKVersion;
};

View File

@ -3,6 +3,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/VersionTuple.h"
namespace clang {
@ -28,6 +29,17 @@ const char *CudaVersionToString(CudaVersion V) {
llvm_unreachable("invalid enum");
}
CudaVersion CudaStringToVersion(llvm::StringRef S) {
return llvm::StringSwitch<CudaVersion>(S)
.Case("7.0", CudaVersion::CUDA_70)
.Case("7.5", CudaVersion::CUDA_75)
.Case("8.0", CudaVersion::CUDA_80)
.Case("9.0", CudaVersion::CUDA_90)
.Case("9.1", CudaVersion::CUDA_91)
.Case("9.2", CudaVersion::CUDA_92)
.Case("10.0", CudaVersion::CUDA_100);
}
const char *CudaArchToString(CudaArch A) {
switch (A) {
case CudaArch::LAST:
@ -322,4 +334,38 @@ CudaVersion MaxVersionForCudaArch(CudaArch A) {
}
}
static CudaVersion ToCudaVersion(llvm::VersionTuple Version) {
int IVer =
Version.getMajor() * 10 + Version.getMinor().getValueOr(0);
switch(IVer) {
case 70:
return CudaVersion::CUDA_70;
case 75:
return CudaVersion::CUDA_75;
case 80:
return CudaVersion::CUDA_80;
case 90:
return CudaVersion::CUDA_90;
case 91:
return CudaVersion::CUDA_91;
case 92:
return CudaVersion::CUDA_92;
case 100:
return CudaVersion::CUDA_100;
default:
return CudaVersion::UNKNOWN;
}
}
bool CudaFeatureEnabled(llvm::VersionTuple Version, CudaFeature Feature) {
return CudaFeatureEnabled(ToCudaVersion(Version), Feature);
}
bool CudaFeatureEnabled(CudaVersion Version, CudaFeature Feature) {
switch (Feature) {
case CudaFeature::CUDA_USES_NEW_LAUNCH:
return Version >= CudaVersion::CUDA_92;
}
llvm_unreachable("Unknown CUDA feature.");
}
} // namespace clang

View File

@ -3464,13 +3464,25 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
NormalizedTriple = C.getSingleOffloadToolChain<Action::OFK_Host>()
->getTriple()
.normalize();
else
else {
// Host-side compilation.
NormalizedTriple =
(IsCuda ? C.getSingleOffloadToolChain<Action::OFK_Cuda>()
: C.getSingleOffloadToolChain<Action::OFK_HIP>())
->getTriple()
.normalize();
if (IsCuda) {
// We need to figure out which CUDA version we're compiling for, as that
// determines how we load and launch GPU kernels.
auto *CTC = static_cast<const toolchains::CudaToolChain *>(
C.getSingleOffloadToolChain<Action::OFK_Cuda>());
assert(CTC && "Expected valid CUDA Toolchain.");
if (CTC && CTC->CudaInstallation.version() != CudaVersion::UNKNOWN)
CmdArgs.push_back(Args.MakeArgString(
Twine("-target-sdk-version=") +
CudaVersionToString(CTC->CudaInstallation.version())));
}
}
CmdArgs.push_back("-aux-triple");
CmdArgs.push_back(Args.MakeArgString(NormalizedTriple));
}

View File

@ -661,9 +661,13 @@ void CudaToolChain::addClangTargetOptions(
options::OPT_fno_cuda_short_ptr, false))
CC1Args.append({"-mllvm", "--nvptx-short-ptr"});
if (CudaInstallation.version() >= CudaVersion::UNKNOWN)
CC1Args.push_back(DriverArgs.MakeArgString(
Twine("-target-sdk-version=") +
CudaVersionToString(CudaInstallation.version())));
if (DeviceOffloadingKind == Action::OFK_OpenMP) {
SmallVector<StringRef, 8> LibraryPaths;
if (const Arg *A = DriverArgs.getLastArg(options::OPT_libomptarget_nvptx_path_EQ))
LibraryPaths.push_back(A->getValue());

View File

@ -137,6 +137,16 @@
// RUN: --gcc-toolchain="" 2>&1 \
// RUN: | FileCheck %s --check-prefix CHECK-CXXINCLUDE
// Verify that CUDA SDK version is propagated to the CC1 compilations.
// RUN: %clang -### -v -target x86_64-linux-gnu --cuda-gpu-arch=sm_50 \
// RUN: --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda %s 2>&1 \
// RUN: | FileCheck %s -check-prefix CUDA80
// Verify that if no version file is found, we report the default of 7.0.
// RUN: %clang -### -v -target x86_64-linux-gnu --cuda-gpu-arch=sm_50 \
// RUN: --cuda-path=%S/Inputs/CUDA/usr/local/cuda %s 2>&1 \
// RUN: | FileCheck %s -check-prefix CUDA70
// CHECK: Found CUDA installation: {{.*}}/Inputs/CUDA/usr/local/cuda
// NO-LIBDEVICE: Found CUDA installation: {{.*}}/Inputs/CUDA-nolibdevice/usr/local/cuda
// NOCUDA-NOT: Found CUDA installation:
@ -167,3 +177,15 @@
// CHECK-CXXINCLUDE: clang{{.*}} "-cc1" "-triple" "x86_64-unknown-linux-gnu"
// CHECK-CXXINCLUDE-SAME: {{.*}}"-internal-isystem" "{{.+}}/include/c++/4.8"
// CHECK-CXXINCLUDE: ld{{.*}}"
// CUDA80: clang{{.*}} "-cc1" "-triple" "nvptx64-nvidia-cuda"
// CUDA80-SAME: -target-sdk-version=8.0
// CUDA80: clang{{.*}} "-cc1" "-triple" "x86_64-unknown-linux-gnu"
// CUDA80-SAME: -target-sdk-version=8.0
// CUDA80: ld{{.*}}"
// CUDA70: clang{{.*}} "-cc1" "-triple" "nvptx64-nvidia-cuda"
// CUDA70-SAME: -target-sdk-version=7.0
// CUDA70: clang{{.*}} "-cc1" "-triple" "x86_64-unknown-linux-gnu"
// CUDA70-SAME: -target-sdk-version=7.0
// CUDA70: ld{{.*}}"