Index: include/clang/Driver/Action.h =================================================================== --- include/clang/Driver/Action.h +++ include/clang/Driver/Action.h @@ -146,6 +146,10 @@ CudaDeviceAction(Action *Input, const char *ArchName, bool AtTopLevel); const char *getGpuArchName() const { return GpuArchName; } + + /// Gets the compute_XX that corresponds to getGpuArchName(). + const char *getComputeArchName() const; + bool isAtTopLevel() const { return AtTopLevel; } static bool IsValidGpuArchName(llvm::StringRef ArchName); Index: lib/Driver/Action.cpp =================================================================== --- lib/Driver/Action.cpp +++ lib/Driver/Action.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "clang/Driver/Action.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Regex.h" #include @@ -50,6 +51,24 @@ BindArchAction::BindArchAction(Action *Input, const char *_ArchName) : Action(BindArchClass, Input), ArchName(_ArchName) {} +// Converts CUDA GPU architecture, e.g. "sm_21", to its corresponding virtual +// compute arch, e.g. "compute_20". Returns null if the input arch is null or +// doesn't match an existing arch. +static const char* GpuArchToComputeName(const char *ArchName) { + if (!ArchName) + return nullptr; + return llvm::StringSwitch(ArchName) + .Cases("sm_20", "sm_21", "compute_20") + .Case("sm_30", "compute_30") + .Case("sm_32", "compute_32") + .Case("sm_35", "compute_35") + .Case("sm_37", "compute_37") + .Case("sm_50", "compute_50") + .Case("sm_52", "compute_52") + .Case("sm_53", "compute_53") + .Default(nullptr); +} + void CudaDeviceAction::anchor() {} CudaDeviceAction::CudaDeviceAction(Action *Input, const char *ArchName, @@ -59,9 +78,12 @@ assert(IsValidGpuArchName(GpuArchName)); } +const char *CudaDeviceAction::getComputeArchName() const { + return GpuArchToComputeName(GpuArchName); +} + bool CudaDeviceAction::IsValidGpuArchName(llvm::StringRef ArchName) { - static llvm::Regex RE("^sm_[0-9]+$"); - return RE.match(ArchName); + return GpuArchToComputeName(ArchName.data()) != nullptr; } void CudaHostAction::anchor() {} Index: test/Driver/cuda-bad-arch.cu =================================================================== --- test/Driver/cuda-bad-arch.cu +++ test/Driver/cuda-bad-arch.cu @@ -5,28 +5,16 @@ // RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=compute_20 -c %s 2>&1 \ // RUN: | FileCheck -check-prefix BAD %s -// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=foo_20 -c %s 2>&1 \ -// RUN: | FileCheck -check-prefix BAD %s // RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm20 -c %s 2>&1 \ // RUN: | FileCheck -check-prefix BAD %s -// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_abc -c %s 2>&1 \ -// RUN: | FileCheck -check-prefix BAD %s -// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_20a -c %s 2>&1 \ -// RUN: | FileCheck -check-prefix BAD %s -// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_a20 -c %s 2>&1 \ -// RUN: | FileCheck -check-prefix BAD %s -// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=ssm_20 -c %s 2>&1 \ -// RUN: | FileCheck -check-prefix BAD %s -// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_ -c %s 2>&1 \ +// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_19 -c %s 2>&1 \ // RUN: | FileCheck -check-prefix BAD %s // BAD: error: Unsupported CUDA gpu architecture -// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_2 -c %s 2>&1 \ -// RUN: | FileCheck -check-prefix OK %s // RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_20 -c %s 2>&1 \ // RUN: | FileCheck -check-prefix OK %s -// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_999 -c %s 2>&1 \ +// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_52 -c %s 2>&1 \ // RUN: | FileCheck -check-prefix OK %s // RUN: %clang -### -target x86_64-linux-gnu -c %s 2>&1 \ // RUN: | FileCheck -check-prefix OK %s