From a4455785ca585a71e4ccdbfe206074f9f95999b5 Mon Sep 17 00:00:00 2001 From: Konstantin S Bobrovsky Date: Mon, 25 May 2020 22:04:08 -0700 Subject: [PATCH 1/4] [SYCL][ESIMD] Implement "private globals" (file scope private vars) in Front End. "private globals" are essentially private variables in a global scope. Marked with __attribute__((opencl_private)). Additionally can be marked with __attribute__((register_num(n))) to bind to a specific register. Signed-off-by: Konstantin S Bobrovsky --- clang/include/clang/Basic/Attr.td | 22 +++++++++++++++++ clang/include/clang/Basic/AttrDocs.td | 24 +++++++++++++++++++ clang/lib/CodeGen/CGSYCLRuntime.cpp | 21 +++++++++++++--- clang/lib/CodeGen/CGSYCLRuntime.h | 2 ++ clang/lib/CodeGen/CodeGenModule.cpp | 13 +++++++++- clang/lib/Sema/SemaDecl.cpp | 8 +++++++ clang/lib/Sema/SemaDeclAttr.cpp | 18 ++++++++++++++ clang/lib/Sema/SemaExpr.cpp | 4 +++- .../test/CodeGenSYCL/esimd-private-global.cpp | 14 +++++++++++ .../test/SemaSYCL/esimd-register-num-attr.cpp | 13 ++++++++++ 10 files changed, 134 insertions(+), 5 deletions(-) create mode 100644 clang/test/CodeGenSYCL/esimd-private-global.cpp create mode 100644 clang/test/SemaSYCL/esimd-register-num-attr.cpp diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index b65c2697dd1a1..2d48c2643af30 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1135,6 +1135,28 @@ def SYCLKernel : InheritableAttr { let Documentation = [SYCLKernelDocs]; } +// Marks functions which must not be vectorized via horizontal SIMT widening, +// e.g. because the function is already vectorized. Used to mark SYCL +// explicit SIMD kernels and functions. +def SYCLSimd : InheritableAttr { + let Spellings = [GNU<"sycl_explicit_simd">]; + let Subjects = SubjectList<[Function]>; + let LangOpts = [SYCLIsDevice]; + let Documentation = [SYCLSimdDocs]; +} + +// Available in SYCL explicit SIMD extension. Binds a file scope private +// variable to a specific register. +def SYCLRegisterNum : InheritableAttr { + let Spellings = [GNU<"register_num">, Declspec<"register_num">]; + let Args = [UnsignedArgument<"Number">]; + let Subjects = SubjectList<[GlobalVar]>; + // This attribute is applied to file-scope variables and must be compilable + // for the host device as well + let LangOpts = [SYCLExplicitSIMD]; + let Documentation = [SYCLRegisterNumDocs]; +} + def SYCLScope : Attr { // No spelling, as this attribute can't be created in the source code. let Spellings = []; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 1a7bca252912b..2f130ef311bb0 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -330,6 +330,30 @@ The SYCL kernel in the previous code sample meets these expectations. }]; } +def SYCLSimdDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ + The ``__attribute__((sycl_explicit_simd))`` attribute is used by the device + compiler front end to mark kernels and functions to be compiled and executed + in the explicit SIMD mode. In this mode subgroup size is always 1 and + explicit SIMD extensions - such as manual vectorization using wide vector + data types and operations can be used. Compiler may decide to compile such + functions using different different optimization and code generation + pipeline. + }]; +} + +def SYCLRegisterNumDocs : Documentation { + let Category = DocCatVariable; + let Content = [{ + The ``__attribute__((register_num(n)))`` attribute can be used to bind + "private globals" (SYCL private address space variables declared in the file + scope) to a particular register with number 'n'. Actual mapping of registers + to numbers is target-specific. For Intel GPUs 'n' is a byte offset in the + GRF. + }]; +} + def C11NoReturnDocs : Documentation { let Category = DocCatFunction; let Content = [{ diff --git a/clang/lib/CodeGen/CGSYCLRuntime.cpp b/clang/lib/CodeGen/CGSYCLRuntime.cpp index a827f6fb82f91..40b5c61ad581b 100644 --- a/clang/lib/CodeGen/CGSYCLRuntime.cpp +++ b/clang/lib/CodeGen/CGSYCLRuntime.cpp @@ -50,9 +50,11 @@ static bool isPFWI(const FunctionDecl &FD) { return FD.getName() == "parallel_for_work_item"; } -const char *WG_SCOPE_MD_ID = "work_group_scope"; -const char *WI_SCOPE_MD_ID = "work_item_scope"; -const char *PFWI_MD_ID = "parallel_for_work_item"; +constexpr char WG_SCOPE_MD_ID[] = "work_group_scope"; +constexpr char WI_SCOPE_MD_ID[] = "work_item_scope"; +constexpr char PFWI_MD_ID[] = "parallel_for_work_item"; +constexpr char ATTR_GENX_VOLATILE[] = "genx_volatile"; +constexpr char ATTR_GENX_BYTE_OFFSET[] = "genx_byte_offset"; } // anonymous namespace @@ -101,6 +103,19 @@ bool CGSYCLRuntime::actOnAutoVarEmit(CodeGenFunction &CGF, const VarDecl &D, return true; } +bool CGSYCLRuntime::actOnGlobalVarEmit(CodeGenModule &CGM, const VarDecl &D, + llvm::Value *Addr) { + SYCLRegisterNumAttr *RegAttr = D.getAttr(); + if (!RegAttr) + return false; + auto *GlobVar = cast(Addr); + GlobVar->addAttribute(ATTR_GENX_VOLATILE); + GlobVar->addAttribute(ATTR_GENX_BYTE_OFFSET, + Twine(RegAttr->getNumber()).str()); + // TODO consider reversing the error/success return values + return true; +} + bool Util::matchQualifiedTypeName(const CXXRecordDecl *RecTy, ArrayRef Scopes) { // The idea: check the declaration context chain starting from the type diff --git a/clang/lib/CodeGen/CGSYCLRuntime.h b/clang/lib/CodeGen/CGSYCLRuntime.h index 12885f42aae85..71bc45599516f 100644 --- a/clang/lib/CodeGen/CGSYCLRuntime.h +++ b/clang/lib/CodeGen/CGSYCLRuntime.h @@ -34,6 +34,8 @@ class CGSYCLRuntime { void emitWorkGroupLocalVarDecl(CodeGenFunction &CGF, const VarDecl &D); bool actOnAutoVarEmit(CodeGenFunction &CGF, const VarDecl &D, llvm::Value *Addr); + bool actOnGlobalVarEmit(CodeGenModule &CGM, const VarDecl &D, + llvm::Value *Addr); }; } // namespace CodeGen diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index c656e2d10f21e..61c767de2e797 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3885,6 +3885,13 @@ LangAS CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D) { if (!D || D->getType().getAddressSpace() == LangAS::Default) { return LangAS::opencl_global; } + if (D) + AddrSpace = D->getType().getAddressSpace(); + if (AddrSpace == LangAS::opencl_private || + AddrSpace == LangAS::opencl_local) + // SYCL explicit SIMD path: recognize globals in private or local address + // space. + return AddrSpace; } if (LangOpts.CUDA && LangOpts.CUDAIsDevice) { @@ -4415,8 +4422,12 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, if (getCodeGenOpts().hasReducedDebugInfo()) DI->EmitGlobalVariable(GV, D); - if (LangOpts.SYCLIsDevice) + if (LangOpts.SYCLIsDevice) { maybeEmitPipeStorageMetadata(D, GV, *this); + // Notify SYCL code generation infrastructure that a global variable is + // being generated. + getSYCLRuntime().actOnGlobalVarEmit(*this, *D, GV); + } } void CodeGenModule::EmitExternalVarDeclaration(const VarDecl *D) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index b3944d3560754..051af6724ba14 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -12578,6 +12578,14 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { if (getLangOpts().OpenCL && Var->getType().getAddressSpace() == LangAS::opencl_local) return; + // In SYCL ESIMD device code non-constant file scope variables can't be + // initialized. + // TODO add proper diagnostics for both SYCL and OpenCL paths + if (getLangOpts().SYCLExplicitSIMD && getLangOpts().SYCLIsDevice && + Var->isFileVarDecl() && Var->hasGlobalStorage() && + (Var->getType().getAddressSpace() != LangAS::opencl_constant)) + return; + // C++03 [dcl.init]p9: // If no initializer is specified for an object, and the // object is of (possibly cv-qualified) non-POD class type (or diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 08dfc66729f96..8b303f7adc6a2 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -4497,6 +4497,21 @@ static void handleSYCLDeviceIndirectlyCallableAttr(Sema &S, Decl *D, handleSimpleAttribute(S, D, AL); } +static void handleSYCLRegisterNumAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + auto *VD = cast(D); + if (!VD->hasGlobalStorage()) { + S.Diag(AL.getLoc(), diag::err_sycl_attibute_cannot_be_applied_here) + << AL << 0; + return; + } + assert(AL.getNumArgs() == 1); + uint32_t RegNo = 0; + const Expr *E = AL.getArgAsExpr(0); + if (!checkUInt32Argument(S, AL, E, RegNo, 0, /*StrictlyUnsigned=*/true)) + return; + D->addAttr(::new (S.Context) SYCLRegisterNumAttr(S.Context, AL, RegNo)); +} + static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (checkAttrMutualExclusion(S, D, AL)) return; @@ -7536,6 +7551,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_SYCLDeviceIndirectlyCallable: handleSYCLDeviceIndirectlyCallableAttr(S, D, AL); break; + case ParsedAttr::AT_SYCLRegisterNum: + handleSYCLRegisterNumAttr(S, D, AL); + break; case ParsedAttr::AT_Format: handleFormatAttr(S, D, AL); break; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 4f61ebdb828e0..0d34060e3662e 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -221,7 +221,9 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef Locs, if (!IsConst && VD->getStorageClass() == SC_Static) SYCLDiagIfDeviceCode(*Locs.begin(), diag::err_sycl_restrict) << Sema::KernelNonConstStaticDataVariable; - else if (!IsConst && VD->hasGlobalStorage() && !isa(VD)) + // Non-const globals are allowed for CM. + else if (!getLangOpts().SYCLExplicitSIMD && !IsConst && + VD->hasGlobalStorage() && !isa(VD)) SYCLDiagIfDeviceCode(*Locs.begin(), diag::err_sycl_restrict) << Sema::KernelGlobalVariable; } diff --git a/clang/test/CodeGenSYCL/esimd-private-global.cpp b/clang/test/CodeGenSYCL/esimd-private-global.cpp new file mode 100644 index 0000000000000..27a5178479529 --- /dev/null +++ b/clang/test/CodeGenSYCL/esimd-private-global.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -disable-llvm-passes -triple spir64-unknown-unknown-sycldevice \ +// RUN: -fsycl -fsycl-is-device -fsycl-explicit-simd -emit-llvm %s -o - | \ +// RUN: FileCheck %s + +// This test checks that FE allows globals with register_num attribute in ESIMD mode. + +__attribute__((opencl_private)) __attribute__((register_num(17))) int vc; + +// CHECK-DAG: @vc = {{.+}} i32 0, align 4 #0 +// CHECK-DAG: attributes #0 = { "genx_byte_offset"="17" "genx_volatile" } + +SYCL_EXTERNAL void init_vc(int x) { + vc = x; +} diff --git a/clang/test/SemaSYCL/esimd-register-num-attr.cpp b/clang/test/SemaSYCL/esimd-register-num-attr.cpp new file mode 100644 index 0000000000000..15dc3bdcfa5a4 --- /dev/null +++ b/clang/test/SemaSYCL/esimd-register-num-attr.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsycl -fsycl-is-device -fsycl-explicit-simd -fsyntax-only -verify -pedantic %s + +#define ESIMD_PRIVATE __attribute__((opencl_private)) +#define ESIMD_REGISTER_NUM(n) __attribute__((register_num(n))) + +// no error expected +ESIMD_PRIVATE ESIMD_REGISTER_NUM(17) int privGlob; + +void foo() { + // expected-warning@+1{{'register_num' attribute only applies to global variables}} + ESIMD_REGISTER_NUM(17) + int privLoc; +} From 43f3f1eabccdaf80c6fb79ca3b27a9563321a202 Mon Sep 17 00:00:00 2001 From: Konstantin S Bobrovsky Date: Wed, 27 May 2020 16:12:24 -0700 Subject: [PATCH 2/4] [SQUASH] Addressed review comments. - Better checking and diagnostics - More tests Signed-off-by: Konstantin S Bobrovsky --- clang/include/clang/Basic/Attr.td | 10 ---------- clang/include/clang/Basic/AttrDocs.td | 13 ------------- .../include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/include/clang/Sema/Sema.h | 8 ++++++++ clang/lib/CodeGen/CodeGenModule.cpp | 7 ------- clang/lib/Sema/SemaDecl.cpp | 16 ++++++++++------ clang/lib/Sema/SemaDeclAttr.cpp | 3 ++- clang/lib/Sema/SemaExpr.cpp | 4 ++-- .../test/CodeGenSYCL/esimd-private-global.cpp | 6 +++--- clang/test/SemaSYCL/esimd-private-global.cpp | 18 ++++++++++++++++++ .../test/SemaSYCL/esimd-register-num-attr.cpp | 13 ------------- 11 files changed, 45 insertions(+), 55 deletions(-) create mode 100644 clang/test/SemaSYCL/esimd-private-global.cpp delete mode 100644 clang/test/SemaSYCL/esimd-register-num-attr.cpp diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 2d48c2643af30..ec08a843be682 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1135,16 +1135,6 @@ def SYCLKernel : InheritableAttr { let Documentation = [SYCLKernelDocs]; } -// Marks functions which must not be vectorized via horizontal SIMT widening, -// e.g. because the function is already vectorized. Used to mark SYCL -// explicit SIMD kernels and functions. -def SYCLSimd : InheritableAttr { - let Spellings = [GNU<"sycl_explicit_simd">]; - let Subjects = SubjectList<[Function]>; - let LangOpts = [SYCLIsDevice]; - let Documentation = [SYCLSimdDocs]; -} - // Available in SYCL explicit SIMD extension. Binds a file scope private // variable to a specific register. def SYCLRegisterNum : InheritableAttr { diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 2f130ef311bb0..07f40b0cfe69a 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -330,19 +330,6 @@ The SYCL kernel in the previous code sample meets these expectations. }]; } -def SYCLSimdDocs : Documentation { - let Category = DocCatFunction; - let Content = [{ - The ``__attribute__((sycl_explicit_simd))`` attribute is used by the device - compiler front end to mark kernels and functions to be compiled and executed - in the explicit SIMD mode. In this mode subgroup size is always 1 and - explicit SIMD extensions - such as manual vectorization using wide vector - data types and operations can be used. Compiler may decide to compile such - functions using different different optimization and code generation - pipeline. - }]; -} - def SYCLRegisterNumDocs : Documentation { let Category = DocCatVariable; let Content = [{ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index d4dbe93fe0f30..0006d1553a101 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10888,4 +10888,6 @@ def err_ext_int_bad_size : Error<"%select{signed|unsigned}0 _ExtInt must " "have a bit size of at least %select{2|1}0">; def err_ext_int_max_size : Error<"%select{signed|unsigned}0 _ExtInt of bit " "sizes greater than %1 not supported">; +def err_esimd_glob_cant_init : Error< + "(SYCL explicit SIMD) private global variable cannot have an initializer">; } // end of sema component. diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index c1297cf19b688..d527dc65ccb06 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -12660,6 +12660,14 @@ class Sema final { void finalizeSYCLDelayedAnalysis(const FunctionDecl *Caller, const FunctionDecl *Callee, SourceLocation Loc); + + /// Tells whether given variable is a SYCL explicit SIMD extension's "private + /// global" variable - global variable in the private address space. + bool isSYCLEsimdPrivateGlobal(VarDecl *VDecl) { + return getLangOpts().SYCLIsDevice && getLangOpts().SYCLExplicitSIMD && + VDecl->hasGlobalStorage() && + (VDecl->getType().getAddressSpace() != LangAS::opencl_constant); + } }; template diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 61c767de2e797..3a429bdebec01 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3885,13 +3885,6 @@ LangAS CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D) { if (!D || D->getType().getAddressSpace() == LangAS::Default) { return LangAS::opencl_global; } - if (D) - AddrSpace = D->getType().getAddressSpace(); - if (AddrSpace == LangAS::opencl_private || - AddrSpace == LangAS::opencl_local) - // SYCL explicit SIMD path: recognize globals in private or local address - // space. - return AddrSpace; } if (LangOpts.CUDA && LangOpts.CUDAIsDevice) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 051af6724ba14..efea9a9dc5049 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -11979,6 +11979,13 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { VDecl->setInvalidDecl(); return; } + // In the SYCL explicit SIMD extension non constant "private globals" can't + // be explicitly initialized in the declaration. + if (isSYCLEsimdPrivateGlobal(VDecl)) { + Diag(VDecl->getLocation(), diag::err_esimd_glob_cant_init); + VDecl->setInvalidDecl(); + return; + } // The LoaderUninitialized attribute acts as a definition (of undef). if (VDecl->hasAttr()) { @@ -12578,12 +12585,9 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { if (getLangOpts().OpenCL && Var->getType().getAddressSpace() == LangAS::opencl_local) return; - // In SYCL ESIMD device code non-constant file scope variables can't be - // initialized. - // TODO add proper diagnostics for both SYCL and OpenCL paths - if (getLangOpts().SYCLExplicitSIMD && getLangOpts().SYCLIsDevice && - Var->isFileVarDecl() && Var->hasGlobalStorage() && - (Var->getType().getAddressSpace() != LangAS::opencl_constant)) + // In SYCL explicit SIMD extension "private global" variables can't be + // initialized even implicitly, so don't synthesize an implicit initializer. + if (isSYCLEsimdPrivateGlobal(Var)) return; // C++03 [dcl.init]p9: diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 8b303f7adc6a2..c56d4148adbe9 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -4504,7 +4504,8 @@ static void handleSYCLRegisterNumAttr(Sema &S, Decl *D, const ParsedAttr &AL) { << AL << 0; return; } - assert(AL.getNumArgs() == 1); + if (!checkAttributeNumArgs(S, AL, 1)) + return; uint32_t RegNo = 0; const Expr *E = AL.getArgAsExpr(0); if (!checkUInt32Argument(S, AL, E, RegNo, 0, /*StrictlyUnsigned=*/true)) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 0d34060e3662e..2cb1ac15fdeb7 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -221,8 +221,8 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef Locs, if (!IsConst && VD->getStorageClass() == SC_Static) SYCLDiagIfDeviceCode(*Locs.begin(), diag::err_sycl_restrict) << Sema::KernelNonConstStaticDataVariable; - // Non-const globals are allowed for CM. - else if (!getLangOpts().SYCLExplicitSIMD && !IsConst && + // Non-const globals are allowed for SYCL explicit SIMD. + else if (!isSYCLEsimdPrivateGlobal(VD) && !IsConst && VD->hasGlobalStorage() && !isa(VD)) SYCLDiagIfDeviceCode(*Locs.begin(), diag::err_sycl_restrict) << Sema::KernelGlobalVariable; diff --git a/clang/test/CodeGenSYCL/esimd-private-global.cpp b/clang/test/CodeGenSYCL/esimd-private-global.cpp index 27a5178479529..d5c475b5656af 100644 --- a/clang/test/CodeGenSYCL/esimd-private-global.cpp +++ b/clang/test/CodeGenSYCL/esimd-private-global.cpp @@ -5,10 +5,10 @@ // This test checks that FE allows globals with register_num attribute in ESIMD mode. __attribute__((opencl_private)) __attribute__((register_num(17))) int vc; - -// CHECK-DAG: @vc = {{.+}} i32 0, align 4 #0 -// CHECK-DAG: attributes #0 = { "genx_byte_offset"="17" "genx_volatile" } +// CHECK: @vc = {{.+}} i32 0, align 4 #0 SYCL_EXTERNAL void init_vc(int x) { vc = x; + // CHECK: store i32 %0, i32* @vc } +// CHECK: attributes #0 = { "genx_byte_offset"="17" "genx_volatile" } diff --git a/clang/test/SemaSYCL/esimd-private-global.cpp b/clang/test/SemaSYCL/esimd-private-global.cpp new file mode 100644 index 0000000000000..3bb23fa78e762 --- /dev/null +++ b/clang/test/SemaSYCL/esimd-private-global.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsycl -fsycl-is-device -fsycl-explicit-simd -fsyntax-only -verify -pedantic %s + +// no error expected +__attribute__((opencl_private)) __attribute__((register_num(17))) int privGlob; + +// expected-error@+1{{'register_num' attribute takes one argument}} +__attribute__((opencl_private)) __attribute__((register_num())) int privGlob1; + +// expected-error@+1{{'register_num' attribute takes one argument}} +__attribute__((opencl_private)) __attribute__((register_num(10, 11))) int privGlob2; + +// expected-error@+1{{(SYCL explicit SIMD) private global variable cannot have an initializer}} +__attribute__((opencl_private)) int privGlob3 = 10; + +void foo() { + // expected-warning@+1{{'register_num' attribute only applies to global variables}} + __attribute__((register_num(17))) int privLoc; +} diff --git a/clang/test/SemaSYCL/esimd-register-num-attr.cpp b/clang/test/SemaSYCL/esimd-register-num-attr.cpp deleted file mode 100644 index 15dc3bdcfa5a4..0000000000000 --- a/clang/test/SemaSYCL/esimd-register-num-attr.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// RUN: %clang_cc1 -fsycl -fsycl-is-device -fsycl-explicit-simd -fsyntax-only -verify -pedantic %s - -#define ESIMD_PRIVATE __attribute__((opencl_private)) -#define ESIMD_REGISTER_NUM(n) __attribute__((register_num(n))) - -// no error expected -ESIMD_PRIVATE ESIMD_REGISTER_NUM(17) int privGlob; - -void foo() { - // expected-warning@+1{{'register_num' attribute only applies to global variables}} - ESIMD_REGISTER_NUM(17) - int privLoc; -} From d6162238de7c3a4bea9861668198df529cdd8c4b Mon Sep 17 00:00:00 2001 From: Konstantin S Bobrovsky Date: Fri, 5 Jun 2020 22:24:12 -0700 Subject: [PATCH 3/4] [SQUASH] Review: disabled pragma syntax for register_num attribute Signed-off-by: Konstantin S Bobrovsky --- clang/include/clang/Basic/Attr.td | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index ec08a843be682..c8858f821acdb 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1145,6 +1145,7 @@ def SYCLRegisterNum : InheritableAttr { // for the host device as well let LangOpts = [SYCLExplicitSIMD]; let Documentation = [SYCLRegisterNumDocs]; + let PragmaAttributeSupport = 0; } def SYCLScope : Attr { From 21ec553a2a6c37703a694f78a99992988a831df0 Mon Sep 17 00:00:00 2001 From: Konstantin S Bobrovsky Date: Mon, 8 Jun 2020 18:10:54 -0700 Subject: [PATCH 4/4] [SQUASH] Review: changed error message for initializer check. Signed-off-by: Konstantin S Bobrovsky --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/test/SemaSYCL/esimd-private-global.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 0006d1553a101..0af416ec759a6 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10889,5 +10889,5 @@ def err_ext_int_bad_size : Error<"%select{signed|unsigned}0 _ExtInt must " def err_ext_int_max_size : Error<"%select{signed|unsigned}0 _ExtInt of bit " "sizes greater than %1 not supported">; def err_esimd_glob_cant_init : Error< - "(SYCL explicit SIMD) private global variable cannot have an initializer">; + "SYCL explicit SIMD does not permit private global variable to have an initializer">; } // end of sema component. diff --git a/clang/test/SemaSYCL/esimd-private-global.cpp b/clang/test/SemaSYCL/esimd-private-global.cpp index 3bb23fa78e762..3023385e48e8d 100644 --- a/clang/test/SemaSYCL/esimd-private-global.cpp +++ b/clang/test/SemaSYCL/esimd-private-global.cpp @@ -9,7 +9,7 @@ __attribute__((opencl_private)) __attribute__((register_num())) int privGlob1; // expected-error@+1{{'register_num' attribute takes one argument}} __attribute__((opencl_private)) __attribute__((register_num(10, 11))) int privGlob2; -// expected-error@+1{{(SYCL explicit SIMD) private global variable cannot have an initializer}} +// expected-error@+1{{SYCL explicit SIMD does not permit private global variable to have an initializer}} __attribute__((opencl_private)) int privGlob3 = 10; void foo() {