diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index fc8d392e3937a..5b4b1907fa3cc 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1850,6 +1850,23 @@ def IntelFPGABankBits : Attr { }]; } +def IntelFPGAForcePow2Depth : Attr { + let Spellings = [CXX11<"intelfpga","force_pow2_depth">]; + let Args = [ExprArgument<"Value">]; + let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar, + Field], ErrorDiag>; + let LangOpts = [SYCLIsDevice, SYCLIsHost]; + let Documentation = [IntelFPGAForcePow2DepthAttrDocs]; + let AdditionalMembers = [{ + static unsigned getMinValue() { + return 0; + } + static unsigned getMaxValue() { + return 1; + } + }]; +} + def Naked : InheritableAttr { let Spellings = [GCC<"naked">, Declspec<"naked">]; let Subjects = SubjectList<[Function]>; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 58af06c66bb84..e530f8cff5c9c 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -1935,6 +1935,26 @@ pointer address bits to bank on. }]; } +def IntelFPGAForcePow2DepthAttrDocs : Documentation { + let Category = DocCatVariable; + let Heading = "force_pow2_depth (IntelFPGA)"; + let Content = [{ +This attribute may be attached to a variable or struct member declaration and +provides explicit control over the geometry of memory blocks used in a given +memory system. + +In the presence of this attribute, the compiler: + +1. Will automatically size the memory depth to the next largest power of 2 if +force_pow2_depth is set to 1, and will prefer width-stitching of RAM blocks +over depth-stitching. + +2. Will not size the memory to the next largest power of 2 if force_pow2_depth +is set to 0, and will prefer depth-stitching over width-stitching if RAM usage +can be lowered. + }]; +} + def SYCLIntelKernelArgsRestrictDocs : Documentation { let Category = DocCatVariable; let Heading = "kernel_args_restrict"; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 1e1fe2085be07..fc437c5c385ce 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -4062,6 +4062,11 @@ void CodeGenModule::generateIntelFPGAAnnotation( } if (D->hasAttr()) Out << "{simple_dual_port:1}"; + if (const auto *FP2D = D->getAttr()) { + llvm::APSInt FP2DInt = + FP2D->getValue()->EvaluateKnownConstInt(getContext()); + Out << '{' << FP2D->getSpelling() << ':' << FP2DInt << '}'; + } } void CodeGenModule::addGlobalIntelFPGAAnnotation(const VarDecl *VD, diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 007412764c776..dc5b06829f3b6 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5215,6 +5215,8 @@ static bool checkIntelFPGARegisterAttrCompatibility(Sema &S, Decl *D, InCompat = true; if (checkAttrMutualExclusion(S, D, Attr)) InCompat = true; + if (checkAttrMutualExclusion(S, D, Attr)) + InCompat = true; return InCompat; } @@ -5419,6 +5421,24 @@ static void handleIntelFPGAPrivateCopiesAttr(Sema &S, Decl *D, D, Attr, Attr.getArgAsExpr(0)); } +static void handleIntelFPGAForcePow2DepthAttr(Sema &S, Decl *D, + const ParsedAttr &Attr) { + if (S.LangOpts.SYCLIsHost) + return; + + checkForDuplicateAttribute(S, D, Attr); + + if (checkAttrMutualExclusion(S, D, Attr)) + return; + + if (!D->hasAttr()) + D->addAttr(IntelFPGAMemoryAttr::CreateImplicit( + S.Context, IntelFPGAMemoryAttr::Default)); + + S.AddOneConstantValueAttr(D, Attr, + Attr.getArgAsExpr(0)); +} + static void handleXRayLogArgsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { ParamIdx ArgCount; @@ -8018,6 +8038,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_IntelFPGABankBits: handleIntelFPGABankBitsAttr(S, D, AL); break; + case ParsedAttr::AT_IntelFPGAForcePow2Depth: + handleIntelFPGAForcePow2DepthAttr(S, D, AL); + break; case ParsedAttr::AT_SYCLIntelPipeIO: handleSYCLIntelPipeIOAttr(S, D, AL); break; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index fbe642ed9341a..91606e34eec91 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -555,6 +555,17 @@ static void instantiateIntelFPGABankBitsAttr( S.AddIntelFPGABankBitsAttr(New, *Attr, Args.data(), Args.size()); } +static void instantiateIntelFPGAForcePow2DepthAttr( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + const IntelFPGAForcePow2DepthAttr *Attr, Decl *New) { + EnterExpressionEvaluationContext Unevaluated( + S, Sema::ExpressionEvaluationContext::ConstantEvaluated); + ExprResult Result = S.SubstExpr(Attr->getValue(), TemplateArgs); + if (!Result.isInvalid()) + S.AddOneConstantValueAttr( + New, *Attr, Result.getAs()); +} + static void instantiateSYCLIntelPipeIOAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, const SYCLIntelPipeIOAttr *Attr, Decl *New) { @@ -699,6 +710,11 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, instantiateIntelFPGABankBitsAttr(*this, TemplateArgs, IntelFPGABankBits, New); } + if (const auto *IntelFPGAForcePow2Depth = + dyn_cast(TmplAttr)) { + instantiateIntelFPGAForcePow2DepthAttr(*this, TemplateArgs, + IntelFPGAForcePow2Depth, New); + } if (const auto *SYCLIntelPipeIO = dyn_cast(TmplAttr)) { instantiateSYCLIntelPipeIOAttr(*this, TemplateArgs, SYCLIntelPipeIO, New); continue; diff --git a/clang/test/CodeGenSYCL/intel-fpga-local.cpp b/clang/test/CodeGenSYCL/intel-fpga-local.cpp index cad71abf6e362..05bb362efee09 100644 --- a/clang/test/CodeGenSYCL/intel-fpga-local.cpp +++ b/clang/test/CodeGenSYCL/intel-fpga-local.cpp @@ -5,6 +5,8 @@ // CHECK-DEVICE: [[ANN_numbanks_4:@.str]] = {{.*}}{memory:DEFAULT}{sizeinfo:4}{numbanks:4} // CHECK-BOTH: @_ZZ15attrs_on_staticvE15static_annotate = internal{{.*}}constant i32 30, align 4 // CHECK-BOTH: [[ANN_annotate:@.str[.0-9]*]] = {{.*}}foobar +// CHECK-BOTH: @_ZZ15attrs_on_staticvE16static_force_p2d = internal{{.*}}constant i32 40, align 4 +// CHECK-DEVICE: [[ANN_force_pow2_depth_0:@.str[.0-9]*]] = {{.*}}{memory:DEFAULT}{sizeinfo:4}{force_pow2_depth:0} // CHECK-DEVICE: [[ANN_register:@.str.[0-9]*]] = {{.*}}{register:1} // CHECK-DEVICE: [[ANN_memory_default:@.str.[0-9]*]] = {{.*}}{memory:DEFAULT}{sizeinfo:4} // CHECK-DEVICE: [[ANN_mlab_sizeinfo_500:@.str.[0-9]*]] = {{.*}}{memory:MLAB}{sizeinfo:4,500} @@ -22,22 +24,25 @@ // CHECK-DEVICE: [[ANN_bankbits_bankwidth:@.str.[0-9]*]] = {{.*}}{memory:DEFAULT}{sizeinfo:4,10,2}{bankwidth:16}{numbanks:2}{bank_bits:0} // CHECK-DEVICE: [[ANN_memory_blockram:@.str.[0-9]*]] = {{.*}}{memory:BLOCK_RAM}{sizeinfo:4} // CHECK-DEVICE: [[ANN_memory_mlab:@.str.[0-9]*]] = {{.*}}{memory:MLAB}{sizeinfo:4} +// CHECK-DEVICE: [[ANN_force_pow2_depth_1:@.str.[0-9]*]] = {{.*}}{memory:DEFAULT}{sizeinfo:4}{force_pow2_depth:1} // CHECK-DEVICE: [[ANN_private_copies_4:@.str.[0-9]*]] = {{.*}}{memory:DEFAULT}{sizeinfo:4}{private_copies:4} // CHECK-DEVICE: [[ANN_max_replicates_4:@.str.[0-9]*]] = {{.*}}{max_replicates:4} // CHECK-BOTH: @llvm.global.annotations // CHECK-DEVICE-SAME: { i8* addrspacecast (i8 addrspace(1)* bitcast (i32 addrspace(1)* @_ZZ15attrs_on_staticvE15static_numbanks to i8 addrspace(1)*) to i8*) -// CHECK-DEVICE-SAME: [[ANN_numbanks_4]]{{.*}} i32 39 +// CHECK-DEVICE-SAME: [[ANN_numbanks_4]]{{.*}} i32 43 // CHECK-DEVICE-SAME: { i8* addrspacecast (i8 addrspace(1)* bitcast (i32 addrspace(1)* @_ZZ15attrs_on_staticvE15static_annotate to i8 addrspace(1)*) to i8*) // CHECK-HOST-SAME: { i8* bitcast (i32* @_ZZ15attrs_on_staticvE15static_annotate to i8*) -// CHECK-BOTH-SAME: [[ANN_annotate]]{{.*}} i32 40 - +// CHECK-BOTH-SAME: [[ANN_annotate]]{{.*}} i32 44 +// CHECK-DEVICE-SAME: { i8* addrspacecast (i8 addrspace(1)* bitcast (i32 addrspace(1)* @_ZZ15attrs_on_staticvE16static_force_p2d to i8 addrspace(1)*) to i8*) +// CHECK-DEVICE-SAME: [[ANN_force_pow2_depth_0]]{{.*}} i32 45 // CHECK-HOST-NOT: llvm.var.annotation // CHECK-HOST-NOT: llvm.ptr.annotation void attrs_on_static() { const static int static_numbanks [[intelfpga::numbanks(4)]] = 20; const static int static_annotate [[clang::annotate("foobar")]] = 30; + const static int static_force_p2d [[intelfpga::force_pow2_depth(0)]] = 40; } void attrs_on_var() { @@ -105,6 +110,10 @@ void attrs_on_var() { // CHECK-DEVICE: %[[VAR_BANK_BITS_WIDTH1:bank_bits_width[0-9]+]] = bitcast{{.*}}%bank_bits_width // CHECK-DEVICE: @llvm.var.annotation{{.*}}%[[VAR_BANK_BITS_WIDTH1]],{{.*}}[[ANN_bankbits_bankwidth]] [[intelfpga::bank_bits(0), intelfpga::bankwidth(16)]] int bank_bits_width[10][2]; + // CHECK-DEVICE: %[[VAR_FP2D:[0-9]+]] = bitcast{{.*}}%force_p2d + // CHECK-DEVICE: %[[VAR_FP2D1:force_p2d[0-9]+]] = bitcast{{.*}}%force_p2d + // CHECK-DEVICE: llvm.var.annotation{{.*}}%[[VAR_FP2D1]],{{.*}}[[ANN_force_pow2_depth_0]] + int force_p2d [[intelfpga::force_pow2_depth(0)]]; } void attrs_on_struct() { @@ -123,6 +132,7 @@ void attrs_on_struct() { int maxreplicates [[intelfpga::max_replicates(2)]]; int dualport [[intelfpga::simple_dual_port]]; int bankbits [[intelfpga::bank_bits(4, 5)]]; + int force_p2d [[intelfpga::force_pow2_depth(1)]]; } s; // CHECK-DEVICE: %[[FIELD_NUMBANKS:.*]] = getelementptr inbounds %struct.{{.*}}.attrs_on_struct{{.*}} @@ -167,12 +177,15 @@ void attrs_on_struct() { // CHECK-DEVICE: %[[FIELD_BANKBITS:.*]] = getelementptr inbounds %struct.{{.*}}.attrs_on_struct{{.*}} // CHECK-DEVICE: call i32* @llvm.ptr.annotation.p0i32{{.*}}%[[FIELD_BANKBITS]]{{.*}}[[ANN_bankbits_4_5]] s.bankbits = 0; + // CHECK-DEVICE: %[[FIELD_FP2D:.*]] = getelementptr inbounds %struct.{{.*}}.attrs_on_struct{{.*}} + // CHECK-DEVICE: call i32* @llvm.ptr.annotation.p0i32{{.*}}%[[FIELD_FP2D]]{{.*}}[[ANN_force_pow2_depth_1]] + s.force_p2d = 0; } // CHECK-HOST-NOT: llvm.var.annotation // CHECK-HOST-NOT: llvm.ptr.annotation -template +template void attrs_with_template_param() { // CHECK-DEVICE: %[[TEMPL_NUMBANKS:numbanks[0-9]+]] = bitcast{{.*}}%numbanks // CHECK-DEVICE: @llvm.var.annotation{{.*}}%[[TEMPL_NUMBANKS]],{{.*}}[[ANN_numbanks_4]] @@ -189,6 +202,9 @@ void attrs_with_template_param() { // CHECK-DEVICE: %[[TEMPL_BANKBITS:bankbits[0-9]+]] = bitcast{{.*}}%bankbits // CHECK-DEVICE: @llvm.var.annotation{{.*}}%[[TEMPL_BANKBITS]],{{.*}}[[ANN_bankbits_4_5]] int bankbits [[intelfpga::bank_bits(A, B)]]; + // CHECK-DEVICE: %[[TEMPL_FP2D:force_p2d[0-9]+]] = bitcast{{.*}}%force_p2d + // CHECK-DEVICE: @llvm.var.annotation{{.*}}%[[TEMPL_FP2D]]{{.*}}[[ANN_force_pow2_depth_1]] + int force_p2d [[intelfpga::force_pow2_depth(C)]]; struct templ_on_struct_fields { int numbanks [[intelfpga::numbanks(A)]] ; @@ -196,6 +212,7 @@ void attrs_with_template_param() { int privatecopies [[intelfpga::private_copies(A)]]; int maxreplicates [[intelfpga::max_replicates(A)]]; int bankbits [[intelfpga::bank_bits(A, B)]]; + int force_p2d [[intelfpga::force_pow2_depth(C)]]; } s; // CHECK-DEVICE: %[[FIELD_NUMBANKS:.*]] = getelementptr inbounds %struct.{{.*}}.templ_on_struct_fields{{.*}} @@ -213,6 +230,9 @@ void attrs_with_template_param() { // CHECK-DEVICE: %[[FIELD_BANKBITS:.*]] = getelementptr inbounds %struct.{{.*}}.templ_on_struct_fields{{.*}} // CHECK-DEVICE: call i32* @llvm.ptr.annotation.p0i32{{.*}}%[[FIELD_BANKBITS]]{{.*}}[[ANN_bankbits_4_5]] s.bankbits = 0; + // CHECK-DEVICE: %[[FIELD_FP2D:.*]] = getelementptr inbounds %struct.{{.*}}.templ_on_struct_fields{{.*}} + // CHECK-DEVICE: call i32* @llvm.ptr.annotation.p0i32{{.*}}%[[FIELD_FP2D]]{{.*}}[[ANN_force_pow2_depth_1]] + s.force_p2d = 0; } void field_addrspace_cast() { @@ -246,7 +266,7 @@ int main() { attrs_on_var(); attrs_on_struct(); field_addrspace_cast(); - attrs_with_template_param<4,5>(); + attrs_with_template_param<4, 5, 1>(); }); return 0; } diff --git a/clang/test/SemaSYCL/intel-fpga-local.cpp b/clang/test/SemaSYCL/intel-fpga-local.cpp index 1f20a6c4ff85d..07852a1623a3d 100644 --- a/clang/test/SemaSYCL/intel-fpga-local.cpp +++ b/clang/test/SemaSYCL/intel-fpga-local.cpp @@ -113,6 +113,20 @@ void check_ast() [[intelfpga::simple_dual_port]] unsigned int dual_port[64]; + //CHECK: VarDecl{{.*}}arr_force_p2d_0 + //CHECK: IntelFPGAMemoryAttr{{.*}}Implicit + //CHECK: IntelFPGAForcePow2DepthAttr + //CHECK: ConstantExpr + //CHECK: IntegerLiteral{{.*}}0{{$}} + [[intelfpga::force_pow2_depth(0)]] unsigned int arr_force_p2d_0[64]; + + //CHECK: VarDecl{{.*}}arr_force_p2d_1 + //CHECK: IntelFPGAMemoryAttr{{.*}}Implicit + //CHECK: IntelFPGAForcePow2DepthAttr + //CHECK: ConstantExpr + //CHECK: IntegerLiteral{{.*}}1{{$}} + [[intelfpga::force_pow2_depth(1)]] unsigned int arr_force_p2d_1[64]; + [[intelfpga::register]] int var_reg; [[intelfpga::numbanks(4), intelfpga::bankwidth(16), intelfpga::singlepump]] int var_singlepump; [[intelfpga::numbanks(4), intelfpga::bankwidth(16), intelfpga::doublepump]] int var_doublepump; @@ -120,6 +134,8 @@ void check_ast() [[intelfpga::bank_bits(2,3), intelfpga::bankwidth(16)]] int var_bank_bits_width; [[intelfpga::max_replicates(2)]] int var_max_repl; [[intelfpga::simple_dual_port]] int var_dual_port; + [[intelfpga::force_pow2_depth(1)]] int var_force_p2d; + [[intelfpga::force_pow2_depth(1)]] const int const_force_p2d[64] = {0, 1}; } //CHECK: FunctionDecl{{.*}}diagnostics @@ -201,7 +217,6 @@ void diagnostics() //expected-note@-2 {{conflicting attribute is here}} unsigned int reg_private_copies[64]; - //expected-error@+2{{attributes are not compatible}} [[intelfpga::register]] [[intelfpga::numbanks(8)]] @@ -224,6 +239,16 @@ void diagnostics() //expected-note@-1 {{conflicting attribute is here}} [[intelfpga::simple_dual_port]] unsigned int reg_dualport[64]; + //expected-error@+3{{'force_pow2_depth' and 'register' attributes are not compatible}} + [[intelfpga::register]] + //expected-note@-1 {{conflicting attribute is here}} + [[intelfpga::force_pow2_depth(0)]] unsigned int reg_force_p2d[64]; + + //expected-error@+3{{'register' and 'force_pow2_depth' attributes are not compatible}} + [[intelfpga::force_pow2_depth(1)]] + //expected-note@-1 {{conflicting attribute is here}} + [[intelfpga::register]] unsigned int force_p2d_reg[64]; + // **memory //expected-error@+2{{attributes are not compatible}} [[intelfpga::memory]] @@ -447,6 +472,28 @@ void diagnostics() //expected-error@+1{{requires integer constant between 0 and 1048576}} [[intelfpga::bank_bits(-1)]] unsigned int bb_negative_arg[4]; + + // force_pow2_depth + //expected-error@+1{{'force_pow2_depth' attribute requires integer constant between 0 and 1 inclusive}} + [[intelfpga::force_pow2_depth(-1)]] unsigned int force_p2d_below_min[64]; + //expected-error@+1{{'force_pow2_depth' attribute requires integer constant between 0 and 1 inclusive}} + [[intelfpga::force_pow2_depth(2)]] unsigned int force_p2d_above_max[64]; + + //expected-error@+1{{'force_pow2_depth' attribute takes one argument}} + [[intelfpga::force_pow2_depth]] unsigned int force_p2d_no_args[64]; + //expected-error@+1{{'force_pow2_depth' attribute takes one argument}} + [[intelfpga::force_pow2_depth(0, 1)]] unsigned int force_p2d_2_args[64]; + + //CHECK: VarDecl{{.*}}force_p2d_dup + //CHECK: IntelFPGAMemoryAttr{{.*}}Implicit + //CHECK: IntelFPGAForcePow2DepthAttr + //CHECK-NEXT: ConstantExpr + //CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} + //CHECK: IntelFPGAForcePow2DepthAttr + //CHECK-NEXT: ConstantExpr + //CHECK-NEXT: IntegerLiteral{{.*}}0{{$}} + //expected-warning@+1{{attribute 'force_pow2_depth' is already applied}} + [[intelfpga::force_pow2_depth(1), intelfpga::force_pow2_depth(0)]] unsigned int force_p2d_dup[64]; } //CHECK: FunctionDecl{{.*}}check_gnu_style @@ -484,6 +531,9 @@ void check_gnu_style() { //expected-warning@+1{{unknown attribute 'bank_bits' ignored}} int __attribute__((bank_bits(4))) bankbits; + + //expected-warning@+1{{unknown attribute 'force_pow2_depth' ignored}} + int __attribute__((force_pow2_depth(0))) force_p2d; } //expected-error@+1{{attribute only applies to local non-const variables and non-static data members}} @@ -499,6 +549,13 @@ void attr_on_const_error() //expected-error@+1{{attribute only applies to local non-const variables and non-static data members}} void attr_on_func_arg([[intelfpga::private_copies(8)]] int pc) {} +//expected-error@+1{{attribute only applies to constant variables, local variables, static variables, slave memory arguments, and non-static data members}} +[[intelfpga::force_pow2_depth(0)]] +__attribute__((opencl_constant)) unsigned int ocl_const_force_p2d[64] = {1, 2, 3}; + +//expected-no-error@+1 +void force_p2d_attr_on_func_arg([[intelfpga::force_pow2_depth(0)]] int pc) {} + struct foo { //CHECK: FieldDecl{{.*}}doublepump //CHECK: IntelFPGAMemoryAttr{{.*}}Implicit @@ -571,10 +628,17 @@ struct foo { //CHECK-NEXT: ConstantExpr //CHECK-NEXT: IntegerLiteral{{.*}}3{{$}} [[intelfpga::bank_bits(2,3)]] unsigned int bankbits[64]; + + //CHECK: FieldDecl{{.*}}force_p2d_field + //CHECK: IntelFPGAMemoryAttr{{.*}}Implicit + //CHECK: IntelFPGAForcePow2DepthAttr + //CHECK-NEXT: ConstantExpr + //CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} + [[intelfpga::force_pow2_depth(1)]] unsigned int force_p2d_field[64]; }; //CHECK: FunctionDecl{{.*}}used check_template_parameters -template +template void check_template_parameters() { //CHECK: VarDecl{{.*}}numbanks //CHECK-NEXT: IntelFPGAMemoryAttr{{.*}}Implicit @@ -617,6 +681,8 @@ void check_template_parameters() { [[intelfpga::max_replicates(A)]] unsigned int max_replicates; + [[intelfpga::force_pow2_depth(E)]] const int const_force_p2d_templ[64] = {0, 1}; + //expected-error@+1{{'numbanks' attribute takes one argument}} [[intelfpga::numbanks(A,B)]] int numbanks_negative; @@ -632,8 +698,42 @@ void check_template_parameters() { //expected-note@-1 {{conflicting attribute is here}} [[intelfpga::max_replicates(C)]] unsigned int maxrepl_reg; + + //expected-error@+1{{'force_pow2_depth' attribute requires integer constant between 0 and 1 inclusive}} + [[intelfpga::force_pow2_depth(A)]] unsigned int force_p2d_below_min[64]; + + //expected-error@+1{{'force_pow2_depth' attribute takes one argument}} + [[intelfpga::force_pow2_depth(E, E)]] unsigned int force_p2d_2_args[64]; + + //expected-error@+3{{'force_pow2_depth' and 'register' attributes are not compatible}} + [[intelfpga::register]] + //expected-note@-1{{conflicting attribute is here}} + [[intelfpga::force_pow2_depth(E)]] unsigned int reg_force_p2d[64]; + + //CHECK: VarDecl{{.*}}force_p2d_dup + //CHECK: IntelFPGAMemoryAttr{{.*}}Implicit + //CHECK: IntelFPGAForcePow2DepthAttr + //CHECK-NEXT: ConstantExpr + //CHECK-NEXT: SubstNonTypeTemplateParmExpr + //CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} + //CHECK: IntelFPGAForcePow2DepthAttr + //CHECK: ConstantExpr + //CHECK-NEXT: IntegerLiteral{{.*}}0{{$}} + //expected-warning@+1{{attribute 'force_pow2_depth' is already applied}} + [[intelfpga::force_pow2_depth(E), intelfpga::force_pow2_depth(0)]] unsigned int force_p2d_dup[64]; } +template +struct templ_st { + //CHECK: FieldDecl{{.*}}templ_force_p2d_field + //CHECK: IntelFPGAMemoryAttr{{.*}}Implicit + //CHECK: IntelFPGAForcePow2DepthAttr + //CHECK: ConstantExpr + //CHECK-NEXT: SubstNonTypeTemplateParmExpr + //CHECK-NEXT: IntegerLiteral{{.*}}0{{$}} + [[intelfpga::force_pow2_depth(A)]] unsigned int templ_force_p2d_field[64]; +}; + template __attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) { kernelFunc(); @@ -644,8 +744,9 @@ int main() { check_ast(); diagnostics(); check_gnu_style(); - check_template_parameters<2, 4, 8, -1>(); - //expected-note@-1 +{{in instantiation of function template specialization}} + //expected-note@+1{{in instantiation of function template specialization}} + check_template_parameters<2, 4, 8, -1, 1>(); + struct templ_st<0> ts {}; }); return 0; }