Skip to content

Commit

Permalink
[CUDA] Propagate detected version of CUDA to cc1
Browse files Browse the repository at this point in the history
..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
  • Loading branch information
Artem-B committed Jan 31, 2019
1 parent 4399878 commit 8fa28a0
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 6 deletions.
15 changes: 12 additions & 3 deletions clang/include/clang/Basic/Cuda.h
Expand Up @@ -11,6 +11,7 @@

namespace llvm {
class StringRef;
class VersionTuple;
} // namespace llvm

namespace clang {
Expand All @@ -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,
Expand Down Expand Up @@ -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
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/TargetOptions.h
Expand Up @@ -75,6 +75,11 @@ class TargetOptions {
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;
};

Expand Down
46 changes: 46 additions & 0 deletions clang/lib/Basic/Cuda.cpp
Expand Up @@ -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 {

Expand All @@ -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:
Expand Down Expand Up @@ -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
16 changes: 14 additions & 2 deletions clang/lib/Driver/ToolChains/Clang.cpp
Expand Up @@ -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));
}
Expand Down
6 changes: 5 additions & 1 deletion clang/lib/Driver/ToolChains/Cuda.cpp
Expand Up @@ -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());

Expand Down
22 changes: 22 additions & 0 deletions clang/test/Driver/cuda-detect.cu
Expand Up @@ -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:
Expand Down Expand Up @@ -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{{.*}}"

0 comments on commit 8fa28a0

Please sign in to comment.