[cuda] Ignore "TLS unsupported by target" errors for host variables during device compilation.

During device-side CUDA compilation clang currently complains about
all TLS variables, regardless of whether they are __host__ or
__device__.

This patch suppresses "TLS unsupported" errors for host variables
during device compilation and for device variables during host
compilation.

Differential Revision: http://reviews.llvm.org/D9269

llvm-svn: 235907
This commit is contained in:
Artem Belevich 2015-04-27 19:37:53 +00:00
parent 0eafe5df71
commit fa62ad4087
4 changed files with 45 additions and 15 deletions

View File

@ -48,6 +48,18 @@ inline bool IsVariableAConstantExpression(VarDecl *Var, ASTContext &Context) {
Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE();
}
// Helper function to check whether D's attributes match current CUDA mode.
// Decls with mismatched attributes and related diagnostics may have to be
// ignored during this CUDA compilation pass.
inline bool DeclAttrsMatchCUDAMode(const LangOptions &LangOpts, Decl *D) {
if (!LangOpts.CUDA || !D)
return true;
bool isDeviceSideDecl = D->hasAttr<CUDADeviceAttr>() ||
D->hasAttr<CUDASharedAttr>() ||
D->hasAttr<CUDAGlobalAttr>();
return isDeviceSideDecl == LangOpts.CUDAIsDevice;
}
// Directly mark a variable odr-used. Given a choice, prefer to use
// MarkVariableReferenced since it does additional checks and then
// calls MarkVarDeclODRUsed.

View File

@ -5753,6 +5753,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (IsLocalExternDecl)
NewVD->setLocalExternDecl();
bool EmitTLSUnsupportedError = false;
if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec()) {
// C++11 [dcl.stc]p4:
// When thread_local is applied to a variable of block scope the
@ -5767,10 +5768,16 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_thread_non_global)
<< DeclSpec::getSpecifierName(TSCS);
else if (!Context.getTargetInfo().isTLSSupported())
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_thread_unsupported);
else
else if (!Context.getTargetInfo().isTLSSupported()) {
if (getLangOpts().CUDA)
// Postpone error emission until we've collected attributes required to
// figure out whether it's a host or device variable and whether the
// error should be ignored.
EmitTLSUnsupportedError = true;
else
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_thread_unsupported);
} else
NewVD->setTSCSpec(TSCS);
}
@ -5819,6 +5826,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
ProcessDeclAttributes(S, NewVD, D);
if (getLangOpts().CUDA) {
if (EmitTLSUnsupportedError && DeclAttrsMatchCUDAMode(getLangOpts(), NewVD))
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_thread_unsupported);
// CUDA B.2.5: "__shared__ and __constant__ variables have implied static
// storage [duration]."
if (SC == SC_None && S->getFnParent() != nullptr &&

View File

@ -124,16 +124,8 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
// The parser verifies that there is a string literal here.
assert(AsmString->isAscii());
bool ValidateConstraints = true;
if (getLangOpts().CUDA) {
// In CUDA mode don't verify asm constraints in device functions during host
// compilation and vice versa.
bool InDeviceMode = getLangOpts().CUDAIsDevice;
FunctionDecl *FD = getCurFunctionDecl();
bool IsDeviceFunction =
FD && (FD->hasAttr<CUDADeviceAttr>() || FD->hasAttr<CUDAGlobalAttr>());
ValidateConstraints = IsDeviceFunction == InDeviceMode;
}
bool ValidateConstraints =
DeclAttrsMatchCUDAMode(getLangOpts(), getCurFunctionDecl());
for (unsigned i = 0; i != NumOutputs; i++) {
StringLiteral *Literal = Constraints[i];

View File

@ -1,7 +1,23 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s
// RUN: %clang_cc1 -triple nvptx-unknown-cuda -fsyntax-only -verify -fcuda-is-device %s
#include "Inputs/cuda.h"
// Host (x86) supports TLS and device-side compilation should ignore
// host variables. No errors in either case.
int __thread host_tls_var;
#if defined(__CUDA_ARCH__)
// NVPTX does not support TLS
__device__ int __thread device_tls_var; // expected-error {{thread-local storage is not supported for the current target}}
__shared__ int __thread shared_tls_var; // expected-error {{thread-local storage is not supported for the current target}}
#else
// Device-side vars should not produce any errors during host-side
// compilation.
__device__ int __thread device_tls_var;
__shared__ int __thread shared_tls_var;
#endif
__global__ void g1(int x) {}
__global__ int g2(int x) { // expected-error {{must have void return type}}
return 1;