Skip to content

Commit a81aeac

Browse files
authored
Merge branch 'sycl' into stmt-attr-cleanups
2 parents 2d97c0b + ec80421 commit a81aeac

File tree

15 files changed

+439
-11
lines changed

15 files changed

+439
-11
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1888,11 +1888,12 @@ def SYCLIntelFPGAInitiationInterval : DeclOrStmtAttr {
18881888
let SupportsNonconformingLambdaSyntax = 1;
18891889
}
18901890

1891-
def SYCLIntelFPGAMaxConcurrency : StmtAttr {
1891+
def SYCLIntelFPGAMaxConcurrency : DeclOrStmtAttr {
18921892
let Spellings = [CXX11<"intelfpga","max_concurrency">,
18931893
CXX11<"intel","max_concurrency">];
1894-
let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt],
1895-
ErrorDiag, "'for', 'while', and 'do' statements">;
1894+
let Subjects = SubjectList<[ForStmt, CXXForRangeStmt, WhileStmt, DoStmt, Function],
1895+
ErrorDiag,
1896+
"'for', 'while', 'do' statements, and functions">;
18961897
let Args = [ExprArgument<"NThreadsExpr">];
18971898
let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost];
18981899
let HasCustomTypeTransform = 1;

clang/include/clang/Basic/AttrDocs.td

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2865,10 +2865,11 @@ def SYCLIntelFPGAMaxConcurrencyAttrDocs : Documentation {
28652865
let Category = DocCatVariable;
28662866
let Heading = "intel::max_concurrency";
28672867
let Content = [{
2868-
This attribute applies to a loop. Indicates that the loop should allow no more
2869-
than N threads or iterations to execute it simultaneously. N must be a non
2870-
negative integer. '0' indicates the max_concurrency case to be unbounded. Cannot
2871-
be applied multiple times to the same loop.
2868+
This attribute applies to a loop or a function. It indicates that the
2869+
loop/function should allow no more than N threads or iterations to execute it
2870+
simultaneously. N must be a non negative integer. '0' indicates the
2871+
max_concurrency case to be unbounded. Cannot be applied multiple times to the
2872+
same loop.
28722873

28732874
.. code-block:: c++
28742875

@@ -2877,10 +2878,13 @@ be applied multiple times to the same loop.
28772878
[[intel::max_concurrency(2)]] for (int i = 0; i != 10; ++i) a[i] = 0;
28782879
}
28792880

2881+
[[intel::max_concurrency(2)]] void foo1 { }
28802882
template<int N>
28812883
void bar() {
28822884
[[intel::max_concurrency(N)]] for(;;) { }
28832885
}
2886+
template<int N>
2887+
[[intel::max_concurrency(N)]] void bar1() { }
28842888

28852889
}];
28862890
}

clang/include/clang/Sema/Sema.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10304,6 +10304,9 @@ class Sema final {
1030410304
SYCLIntelFPGAInitiationIntervalAttr *MergeSYCLIntelFPGAInitiationIntervalAttr(
1030510305
Decl *D, const SYCLIntelFPGAInitiationIntervalAttr &A);
1030610306

10307+
SYCLIntelFPGAMaxConcurrencyAttr *MergeSYCLIntelFPGAMaxConcurrencyAttr(
10308+
Decl *D, const SYCLIntelFPGAMaxConcurrencyAttr &A);
10309+
1030710310
/// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
1030810311
void AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
1030910312
bool IsPackExpansion);
@@ -10358,6 +10361,12 @@ class Sema final {
1035810361
/// declaration.
1035910362
void addSYCLIntelPipeIOAttr(Decl *D, const AttributeCommonInfo &CI, Expr *ID);
1036010363

10364+
/// AddSYCLIntelFPGAMaxConcurrencyAttr - Adds a max_concurrency attribute to a
10365+
/// particular declaration.
10366+
void AddSYCLIntelFPGAMaxConcurrencyAttr(Decl *D,
10367+
const AttributeCommonInfo &CI,
10368+
Expr *E);
10369+
1036110370
bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);
1036210371
bool checkAllowedSYCLInitializer(VarDecl *VD,
1036310372
bool CheckValueDependent = false);

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,14 @@ void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD,
739739
Fn->setMetadata("stall_enable", llvm::MDNode::get(Context, AttrMDArgs));
740740
}
741741

742+
if (const auto *A = FD->getAttr<SYCLIntelFPGAMaxConcurrencyAttr>()) {
743+
const auto *CE = cast<ConstantExpr>(A->getNThreadsExpr());
744+
llvm::APSInt ArgVal = CE->getResultAsAPSInt();
745+
llvm::Metadata *AttrMDArgs[] = {
746+
llvm::ConstantAsMetadata::get(Builder.getInt32(ArgVal.getSExtValue()))};
747+
Fn->setMetadata("max_concurrency", llvm::MDNode::get(Context, AttrMDArgs));
748+
}
749+
742750
if (FD->hasAttr<SYCLIntelFPGADisableLoopPipeliningAttr>()) {
743751
llvm::Metadata *AttrMDArgs[] = {
744752
llvm::ConstantAsMetadata::get(Builder.getInt32(1))};

clang/lib/Sema/SemaDecl.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2628,6 +2628,8 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
26282628
NewAttr = S.MergeSYCLIntelNoGlobalWorkOffsetAttr(D, *A);
26292629
else if (const auto *A = dyn_cast<IntelFPGAMaxReplicatesAttr>(Attr))
26302630
NewAttr = S.MergeIntelFPGAMaxReplicatesAttr(D, *A);
2631+
else if (const auto *A = dyn_cast<SYCLIntelFPGAMaxConcurrencyAttr>(Attr))
2632+
NewAttr = S.MergeSYCLIntelFPGAMaxConcurrencyAttr(D, *A);
26312633
else if (const auto *A = dyn_cast<IntelFPGAForcePow2DepthAttr>(Attr))
26322634
NewAttr = S.MergeIntelFPGAForcePow2DepthAttr(D, *A);
26332635
else if (const auto *A = dyn_cast<SYCLIntelFPGAInitiationIntervalAttr>(Attr))

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6435,6 +6435,76 @@ static void handleSYCLIntelPipeIOAttr(Sema &S, Decl *D,
64356435
S.addSYCLIntelPipeIOAttr(D, Attr, E);
64366436
}
64376437

6438+
SYCLIntelFPGAMaxConcurrencyAttr *Sema::MergeSYCLIntelFPGAMaxConcurrencyAttr(
6439+
Decl *D, const SYCLIntelFPGAMaxConcurrencyAttr &A) {
6440+
// Check to see if there's a duplicate attribute with different values
6441+
// already applied to the declaration.
6442+
if (const auto *DeclAttr = D->getAttr<SYCLIntelFPGAMaxConcurrencyAttr>()) {
6443+
const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getNThreadsExpr());
6444+
const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getNThreadsExpr());
6445+
if (DeclExpr && MergeExpr &&
6446+
DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
6447+
Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
6448+
Diag(A.getLoc(), diag::note_previous_attribute);
6449+
}
6450+
return nullptr;
6451+
}
6452+
// FIXME
6453+
// max_concurrency and disable_component_pipelining attributes can't be
6454+
// applied to the same function. Upcoming patch needs to have this code
6455+
// added to it:
6456+
// if (checkAttrMutualExclusion<IntelDisableComponentPipeline>(S, D, AL))
6457+
// return;
6458+
6459+
return ::new (Context)
6460+
SYCLIntelFPGAMaxConcurrencyAttr(Context, A, A.getNThreadsExpr());
6461+
}
6462+
6463+
void Sema::AddSYCLIntelFPGAMaxConcurrencyAttr(Decl *D,
6464+
const AttributeCommonInfo &CI,
6465+
Expr *E) {
6466+
if (!E->isValueDependent()) {
6467+
llvm::APSInt ArgVal;
6468+
ExprResult Res = VerifyIntegerConstantExpression(E, &ArgVal);
6469+
if (Res.isInvalid())
6470+
return;
6471+
E = Res.get();
6472+
6473+
// This attribute requires a non-negative value.
6474+
if (ArgVal < 0) {
6475+
Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
6476+
<< CI << /*non-negative*/ 1;
6477+
return;
6478+
}
6479+
6480+
if (const auto *DeclAttr = D->getAttr<SYCLIntelFPGAMaxConcurrencyAttr>()) {
6481+
const auto *DeclExpr =
6482+
dyn_cast<ConstantExpr>(DeclAttr->getNThreadsExpr());
6483+
if (DeclExpr && ArgVal != DeclExpr->getResultAsAPSInt()) {
6484+
Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
6485+
Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
6486+
}
6487+
return;
6488+
}
6489+
}
6490+
6491+
D->addAttr(::new (Context) SYCLIntelFPGAMaxConcurrencyAttr(Context, CI, E));
6492+
}
6493+
6494+
static void handleSYCLIntelFPGAMaxConcurrencyAttr(Sema &S, Decl *D,
6495+
const ParsedAttr &A) {
6496+
S.CheckDeprecatedSYCLAttributeSpelling(A);
6497+
// FIXME
6498+
// max_concurrency and disable_component_pipelining attributes can't be
6499+
// applied to the same function. Upcoming patch needs to have this code
6500+
// added to it:
6501+
// if (checkAttrMutualExclusion<IntelDisableComponentPipeline>(S, D, AL))
6502+
// return;
6503+
6504+
Expr *E = A.getArgAsExpr(0);
6505+
S.AddSYCLIntelFPGAMaxConcurrencyAttr(D, A, E);
6506+
}
6507+
64386508
namespace {
64396509
struct IntrinToName {
64406510
uint32_t Id;
@@ -9689,6 +9759,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
96899759
case ParsedAttr::AT_SYCLIntelPipeIO:
96909760
handleSYCLIntelPipeIOAttr(S, D, AL);
96919761
break;
9762+
case ParsedAttr::AT_SYCLIntelFPGAMaxConcurrency:
9763+
handleSYCLIntelFPGAMaxConcurrencyAttr(S, D, AL);
9764+
break;
96929765

96939766
// Swift attributes.
96949767
case ParsedAttr::AT_SwiftAsyncName:

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,13 @@ class MarkDeviceFunction : public RecursiveASTVisitor<MarkDeviceFunction> {
565565
}
566566
}
567567

568+
// Attribute "max_concurrency" is applied to device functions only. The
569+
// attribute is not propagated to the caller.
570+
if (auto *A = FD->getAttr<SYCLIntelFPGAMaxConcurrencyAttr>())
571+
if (ParentFD == SYCLKernel) {
572+
Attrs.push_back(A);
573+
}
574+
568575
// Attribute "disable_loop_pipelining" can be applied explicitly on
569576
// kernel function. Attribute should not be propagated from device
570577
// functions to kernel.
@@ -3535,6 +3542,7 @@ void Sema::MarkDevice(void) {
35353542
case attr::Kind::SYCLIntelNoGlobalWorkOffset:
35363543
case attr::Kind::SYCLIntelUseStallEnableClusters:
35373544
case attr::Kind::SYCLIntelLoopFuse:
3545+
case attr::Kind::SYCLIntelFPGAMaxConcurrency:
35383546
case attr::Kind::SYCLIntelFPGADisableLoopPipelining:
35393547
case attr::Kind::SYCLIntelFPGAInitiationInterval:
35403548
case attr::Kind::SYCLSimd: {

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,16 @@ static void instantiateIntelSYCLFunctionAttr(
693693
S.addIntelSingleArgAttr<AttrName>(New, *Attr, Result.getAs<Expr>());
694694
}
695695

696+
static void instantiateSYCLIntelFPGAMaxConcurrencyAttr(
697+
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
698+
const SYCLIntelFPGAMaxConcurrencyAttr *A, Decl *New) {
699+
EnterExpressionEvaluationContext Unevaluated(
700+
S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
701+
ExprResult Result = S.SubstExpr(A->getNThreadsExpr(), TemplateArgs);
702+
if (!Result.isInvalid())
703+
S.AddSYCLIntelFPGAMaxConcurrencyAttr(New, *A, Result.getAs<Expr>());
704+
}
705+
696706
static void instantiateIntelFPGAPrivateCopiesAttr(
697707
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
698708
const IntelFPGAPrivateCopiesAttr *A, Decl *New) {
@@ -949,6 +959,11 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
949959
*this, TemplateArgs, SYCLIntelMaxWorkGroupSize, New);
950960
continue;
951961
}
962+
if (const auto *SYCLIntelMaxConcurrency =
963+
dyn_cast<SYCLIntelFPGAMaxConcurrencyAttr>(TmplAttr)) {
964+
instantiateSYCLIntelFPGAMaxConcurrencyAttr(*this, TemplateArgs,
965+
SYCLIntelMaxConcurrency, New);
966+
}
952967
if (const auto *SYCLIntelFPGAInitiationInterval =
953968
dyn_cast<SYCLIntelFPGAInitiationIntervalAttr>(TmplAttr)) {
954969
instantiateSYCLIntelFPGAInitiationIntervalAttr(
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
// RUN: %clang_cc1 -fsycl-is-device -internal-isystem %S/Inputs -disable-llvm-passes -triple spir64-unknown-unknown-sycldevice -sycl-std=2020 -emit-llvm -o - %s | FileCheck %s
2+
3+
#include "sycl.hpp"
4+
5+
// CHECK-LABEL: define{{.*}}@_Z15max_concurrencyILi5EEvv()
6+
// CHECK: entry:
7+
// CHECK: [[A:%.*]] = alloca [10 x i32], align 4
8+
// CHECK: [[A_CAST:%.*]] = addrspacecast [10 x i32]* [[A]] to [10 x i32] addrspace(4)*
9+
// CHECK: %4 = load i32, i32 addrspace(4)* %i.ascast, align 4
10+
// CHECK: [[IDXPROM:%*]] = sext i32 %4 to i64
11+
// CHECK: %arrayidx = getelementptr inbounds [10 x i32], [10 x i32] addrspace(4)* [[A_CAST]], i64 0, i64 [[IDXPROM]]
12+
// CHECK: store i32 0, i32 addrspace(4)* %arrayidx, align 4
13+
// CHECK: [[TMP2:%.*]] = load i32, i32 addrspace(4)* %i.ascast, align 4
14+
// CHECK: %inc = add nsw i32 [[TMP2]], 1
15+
// CHECK: store i32 %inc, i32 addrspace(4)* %i.ascast, align 4
16+
// CHECK: br label %for.cond, !llvm.loop ![[MD_MC:[0-9]+]]
17+
// CHECK: store i32 %inc10, i32 addrspace(4)* %i1.ascast, align 4
18+
// CHECK: br label %for.cond2, !llvm.loop ![[MD_MC_1:[0-9]+]]
19+
// CHECK: ret void
20+
21+
// CHECK: define {{.*}}spir_kernel void @"{{.*}}kernel_name1"() [[ATTR0:#.*]] {{.*}} !max_concurrency ![[NUM1:[0-9]+]]
22+
// CHECK: entry:
23+
// CHECK: [[F1:%.*]] = alloca [[CLASS_F1:%.*]], align 1
24+
// CHECK: [[F1_ASCAST:%.*]] = addrspacecast [[CLASS_F1]]* [[F1]] to [[CLASS_F1]] addrspace(4)*
25+
// CHECK: [[TMP0:%.*]] = bitcast [[CLASS_F1]]* [[F1]] to i8*
26+
// CHECK: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[TMP0]])
27+
// CHECK: call spir_func void @_ZNK8Functor1clEv([[CLASS_F1]] addrspace(4)* dereferenceable_or_null(1) [[F1_ASCAST]])
28+
// CHECK: [[TMP1:%.*]] = bitcast [[CLASS_F1]]* [[F1]] to i8*
29+
// CHECK: call void @llvm.lifetime.end.p0i8(i64 1, i8* [[TMP1]])
30+
// CHECK: ret void
31+
32+
// CHECK: define {{.*}}spir_kernel void @"{{.*}}kernel_name4"() [[ATTR0]] {{.*}} !max_concurrency ![[NUM1:[0-9]+]]
33+
// CHECK: entry
34+
// CHECK: [[F3:%.*]] = alloca [[CLASS_F3:%.*]], align 1
35+
// CHECK: [[F3_ASCAST:%.*]] = addrspacecast [[CLASS_F3]]* [[F3]] to [[CLASS_F3]] addrspace(4)*
36+
// CHECK: [[TMP2:%.*]] = bitcast [[CLASS_F3]]* [[F3]] to i8*
37+
// CHECK: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[TMP2]])
38+
// CHECK: call spir_func void @_ZNK8Functor3ILi4EEclEv([[CLASS_F3]] addrspace(4)* dereferenceable_or_null(1) [[F3_ASCAST]])
39+
// CHECK: [[TMP3:%.*]] = bitcast [[CLASS_F3]]* [[F3]] to i8*
40+
// CHECK: call void @llvm.lifetime.end.p0i8(i64 1, i8* [[TMP3]]
41+
// CHECK: ret void
42+
43+
// CHECK: define linkonce_odr spir_func void @_ZNK8Functor3ILi4EEclEv
44+
// CHECK: entry:
45+
// CHECK: [[ADDR_1:%.*]] = alloca [[CLASS_F3:%.*]] addrspace(4)*, align 8
46+
// CHECK: [[ADDR1_CAST:%.*]] = addrspacecast [[CLASS_F3]] addrspace(4)** [[ADDR_1]] to [[CLASS_F3]] addrspace(4)* addrspace(4)*
47+
// CHECK: store [[CLASS_F3]] addrspace(4)* %this, [[CLASS_F3]] addrspace(4)* addrspace(4)* [[ADDR1_CAST]], align 8
48+
// CHECK: %this1 = load [[CLASS_F3]] addrspace(4)*, [[CLASS_F3]] addrspace(4)* addrspace(4)* [[ADDR1_CAST]], align 8
49+
// CHECK: ret void
50+
51+
// CHECK: define dso_local spir_kernel void @"_ZTSZZ4mainENK3$_0clERN2cl4sycl7handlerEE12kernel_name5"()
52+
// CHECK: entry:
53+
// CHECK: [[H1:%.*]] = alloca [[H:%.*]], align 1
54+
// CHECK: [[H2:%.*]] = addrspacecast [[H]]* [[H1]] to [[H]] addrspace(4)*
55+
// CHECK: [[H3:%.*]] = bitcast [[H]]* [[H1]] to i8*
56+
// CHECK: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[H3]])
57+
// CHECK: call spir_func void @"_ZZZ4mainENK3$_1clERN2cl4sycl7handlerEENKUlvE_clEv"([[H]] addrspace(4)* dereferenceable_or_null(1) [[H2]])
58+
// CHECK: [[TMP4:%.*]] = bitcast [[H]]* [[H1]] to i8*
59+
// CHECK: call void @llvm.lifetime.end.p0i8(i64 1, i8* [[TMP4]])
60+
// CHECK: ret void
61+
62+
// CHECK: define {{.*}}spir_func void @"_ZZZ4mainENK3$_1clERN2cl4sycl7handlerEENKUlvE_clEv"
63+
// CHECK: entry:
64+
// CHECK: [[ADDR_1:%.*]] = alloca [[HH:%.*]] addrspace(4)*, align 8
65+
// CHECK: [[ADDR1_CAST:%.*]] = addrspacecast [[HH]] addrspace(4)** [[ADDR_1]] to [[HH]] addrspace(4)* addrspace(4)*
66+
// CHECK: store [[HH]] addrspace(4)* %this, [[HH]] addrspace(4)* addrspace(4)* [[ADDR1_CAST]], align 8
67+
// CHECK: %this1 = load [[HH]] addrspace(4)*, [[HH]] addrspace(4)* addrspace(4)* [[ADDR1_CAST]], align 8
68+
// CHECK: call spir_func void @_Z4funcILi2EEvv()
69+
// CHECK: ret void
70+
71+
template <int A>
72+
void max_concurrency() {
73+
int a[10];
74+
// CHECK: ![[MD_MC]] = distinct !{![[MD_MC]], ![[MP:[0-9]+]], ![[MD_max_concurrency:[0-9]+]]}
75+
// CHECK-NEXT: ![[MP]] = !{!"llvm.loop.mustprogress"}
76+
// CHECK-NEXT: ![[MD_max_concurrency]] = !{!"llvm.loop.max_concurrency.count", i32 5}
77+
[[intel::max_concurrency(A)]] for (int i = 0; i != 10; ++i)
78+
a[i] = 0;
79+
// CHECK: ![[MD_MC_1]] = distinct !{![[MD_MC_1]], ![[MP]], ![[MD_max_concurrency_1:[0-9]+]]}
80+
// CHECK-NEXT: ![[MD_max_concurrency_1]] = !{!"llvm.loop.max_concurrency.count", i32 4}
81+
[[intel::max_concurrency(4)]] for (int i = 0; i != 10; ++i)
82+
a[i] = 0;
83+
}
84+
85+
// CHECK: ![[NUM1]] = !{i32 4}
86+
87+
template <typename name, typename Func>
88+
__attribute__((sycl_kernel)) void kernel_single_task_1(const Func &kernelFunc) {
89+
kernelFunc();
90+
}
91+
92+
using namespace cl::sycl;
93+
94+
class Functor1 {
95+
public:
96+
[[intel::max_concurrency(4)]] void operator()() const {}
97+
};
98+
99+
[[intel::max_concurrency(2)]] void foo() {}
100+
101+
class Functor2 {
102+
public:
103+
void operator()() const {
104+
foo();
105+
}
106+
};
107+
template <int NT>
108+
class Functor3 {
109+
public:
110+
[[intel::max_concurrency(NT)]] void operator()() const {}
111+
};
112+
113+
template <int NT>
114+
[[intel::max_concurrency(NT)]] void func() {}
115+
116+
int main() {
117+
queue q;
118+
119+
kernel_single_task_1<class kernel_function>([]() {
120+
max_concurrency<5>();
121+
});
122+
123+
q.submit([&](handler &h) {
124+
Functor1 f1;
125+
h.single_task<class kernel_name1>(f1);
126+
127+
Functor2 f2;
128+
h.single_task<class kernel_name2>(f2);
129+
130+
Functor3<4> f3;
131+
h.single_task<class kernel_name4>(f3);
132+
133+
h.single_task<class kernel_name5>([]() {
134+
func<2>();
135+
});
136+
137+
});
138+
139+
140+
return 0;
141+
}

clang/test/Misc/pragma-attribute-supported-attributes-list.test

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@
154154
// CHECK-NEXT: SYCLDeviceIndirectlyCallable (SubjectMatchRule_function)
155155
// CHECK-NEXT: SYCLIntelFPGADisableLoopPipelining (SubjectMatchRule_function)
156156
// CHECK-NEXT: SYCLIntelFPGAInitiationInterval (SubjectMatchRule_function)
157+
// CHECK-NEXT: SYCLIntelFPGAMaxConcurrency (SubjectMatchRule_function)
157158
// CHECK-NEXT: SYCLIntelKernelArgsRestrict (SubjectMatchRule_function)
158159
// CHECK-NEXT: SYCLIntelLoopFuse (SubjectMatchRule_function)
159160
// CHECK-NEXT: SYCLIntelMaxGlobalWorkDim (SubjectMatchRule_function)

clang/test/SemaSYCL/intel-fpga-loops.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ void foo() {
1010
[[intel::ivdep]] int a[10];
1111
// expected-error@+1 {{'initiation_interval' attribute only applies to 'for', 'while', 'do' statements, and functions}}
1212
[[intel::initiation_interval(2)]] int c[10];
13-
// expected-error@+1 {{'max_concurrency' attribute cannot be applied to a declaration}}
13+
// expected-error@+1 {{'max_concurrency' attribute only applies to 'for', 'while', 'do' statements, and functions}}
1414
[[intel::max_concurrency(2)]] int d[10];
1515
// expected-error@+1 {{'disable_loop_pipelining' attribute only applies to 'for', 'while', 'do' statements, and functions}}
1616
[[intel::disable_loop_pipelining]] int g[10];
@@ -424,7 +424,7 @@ void parse_order_error() {
424424
// We had a bug where we would only look at the first attribute in the group
425425
// when trying to determine whether to diagnose the loop attributes on an
426426
// incorrect subject. Test that we properly catch this situation.
427-
[[clang::nomerge, intel::max_concurrency(1)]] // expected-error {{'max_concurrency' attribute only applies to 'for', 'while', and 'do' statements}}
427+
[[clang::nomerge, intel::max_concurrency(1)]] // expected-error {{'max_concurrency' attribute only applies to 'for', 'while', 'do' statements, and functions}}
428428
if (1) { parse_order_error(); } // Recursive call silences unrelated diagnostic about nomerge.
429429

430430
[[clang::nomerge, intel::max_concurrency(1)]] // OK

0 commit comments

Comments
 (0)