Skip to content

Commit 7ec85b0

Browse files
authored
[SYCL] Propagate attributes from redeclarations to SYCL kernel (#2063)
- Fix bug that propagates attributes from only canoncial declaration - Handle conflicting attributes - Add a test
1 parent 6306a99 commit 7ec85b0

File tree

3 files changed

+94
-1
lines changed

3 files changed

+94
-1
lines changed

clang/lib/Sema/SemaDecl.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3212,6 +3212,22 @@ static void adjustDeclContextForDeclaratorDecl(DeclaratorDecl *NewD,
32123212
FixSemaDC(VD->getDescribedVarTemplate());
32133213
}
32143214

3215+
template <typename AttributeType>
3216+
static void checkDimensionsAndSetDiagnostics(Sema &S, FunctionDecl *New,
3217+
FunctionDecl *Old) {
3218+
AttributeType *NewDeclAttr = New->getAttr<AttributeType>();
3219+
AttributeType *OldDeclAttr = Old->getAttr<AttributeType>();
3220+
if ((NewDeclAttr->getXDim() != OldDeclAttr->getXDim()) ||
3221+
(NewDeclAttr->getYDim() != OldDeclAttr->getYDim()) ||
3222+
(NewDeclAttr->getZDim() != OldDeclAttr->getZDim())) {
3223+
S.Diag(New->getLocation(), diag::err_conflicting_sycl_function_attributes)
3224+
<< OldDeclAttr << NewDeclAttr;
3225+
S.Diag(New->getLocation(), diag::warn_duplicate_attribute) << OldDeclAttr;
3226+
S.Diag(OldDeclAttr->getLocation(), diag::note_conflicting_attribute);
3227+
S.Diag(NewDeclAttr->getLocation(), diag::note_conflicting_attribute);
3228+
}
3229+
}
3230+
32153231
/// MergeFunctionDecl - We just parsed a function 'New' from
32163232
/// declarator D which has the same name and scope as a previous
32173233
/// declaration 'Old'. Figure out how to resolve this situation,
@@ -3286,6 +3302,15 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
32863302
}
32873303
}
32883304

3305+
if (New->hasAttr<ReqdWorkGroupSizeAttr>() &&
3306+
Old->hasAttr<ReqdWorkGroupSizeAttr>())
3307+
checkDimensionsAndSetDiagnostics<ReqdWorkGroupSizeAttr>(*this, New, Old);
3308+
3309+
if (New->hasAttr<SYCLIntelMaxWorkGroupSizeAttr>() &&
3310+
Old->hasAttr<SYCLIntelMaxWorkGroupSizeAttr>())
3311+
checkDimensionsAndSetDiagnostics<SYCLIntelMaxWorkGroupSizeAttr>(*this, New,
3312+
Old);
3313+
32893314
if (New->hasAttr<InternalLinkageAttr>() &&
32903315
!Old->hasAttr<InternalLinkageAttr>()) {
32913316
Diag(New->getLocation(), diag::err_internal_linkage_redeclaration)

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ class MarkDeviceFunction : public RecursiveASTVisitor<MarkDeviceFunction> {
554554

555555
for (const CallGraphNode *CI : *N) {
556556
if (auto *Callee = dyn_cast<FunctionDecl>(CI->getDecl())) {
557-
Callee = Callee->getCanonicalDecl();
557+
Callee = Callee->getMostRecentDecl();
558558
if (!Visited.count(Callee))
559559
WorkList.push_back({Callee, FD});
560560
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// RUN: %clang_cc1 %s -I %S/Inputs -fsyntax-only -fsycl -fsycl-is-device -triple spir64 -Wno-sycl-2017-compat -verify
2+
// RUN: %clang_cc1 %s -I %S/Inputs -fsyntax-only -fsycl -fsycl-is-device -triple spir64 -DTRIGGER_ERROR -Wno-sycl-2017-compat -verify
3+
// RUN: %clang_cc1 %s -I %S/Inputs -fsyntax-only -ast-dump -fsycl -fsycl-is-device -triple spir64 -Wno-sycl-2017-compat | FileCheck %s
4+
5+
#include <sycl.hpp>
6+
7+
#ifndef TRIGGER_ERROR
8+
//first case - good case
9+
[[intelfpga::no_global_work_offset]] // expected-no-diagnostics
10+
void
11+
func1();
12+
13+
[[intelfpga::max_work_group_size(4, 4, 4)]] void func1();
14+
15+
[[cl::reqd_work_group_size(2, 2, 2)]] void func1() {}
16+
17+
#else
18+
//second case - expect error
19+
[[intelfpga::max_work_group_size(4, 4, 4)]] // expected-note {{conflicting attribute is here}}
20+
void
21+
func2();
22+
23+
[[cl::reqd_work_group_size(8, 8, 8)]] // expected-note {{conflicting attribute is here}}
24+
void
25+
func2() {}
26+
27+
//third case - expect error
28+
[[cl::reqd_work_group_size(4, 4, 4)]] // expected-note {{conflicting attribute is here}}
29+
void
30+
func3();
31+
32+
[[cl::reqd_work_group_size(1, 1, 1)]] // expected-note {{conflicting attribute is here}}
33+
void
34+
// expected-warning@+1 {{attribute 'reqd_work_group_size' is already applied with different parameters}}
35+
func3() {} // expected-error {{'reqd_work_group_size' attribute conflicts with ''reqd_work_group_size'' attribute}}
36+
37+
//fourth case - expect error
38+
[[intelfpga::max_work_group_size(4, 4, 4)]] // expected-note {{conflicting attribute is here}}
39+
void
40+
func4();
41+
42+
[[intelfpga::max_work_group_size(8, 8, 8)]] // expected-note {{conflicting attribute is here}}
43+
void
44+
// expected-warning@+1 {{attribute 'max_work_group_size' is already applied with different parameters}}
45+
func4() {} // expected-error {{'max_work_group_size' attribute conflicts with ''max_work_group_size'' attribute}}
46+
#endif
47+
48+
int main() {
49+
#ifndef TRIGGER_ERROR
50+
// CHECK-LABEL: FunctionDecl {{.*}} main 'int ()'
51+
// CHECK: `-FunctionDecl {{.*}}test_kernel1 'void ()'
52+
// CHECK: -SYCLIntelMaxWorkGroupSizeAttr {{.*}} Inherited 4 4 4
53+
// CHECK: -SYCLIntelNoGlobalWorkOffsetAttr {{.*}} Inherited Enabled
54+
// CHECK: `-ReqdWorkGroupSizeAttr {{.*}} 2 2 2
55+
cl::sycl::kernel_single_task<class test_kernel1>(
56+
[]() { func1(); });
57+
58+
#else
59+
cl::sycl::kernel_single_task<class test_kernel2>(
60+
[]() { func2(); }); // expected-error {{conflicting attributes applied to a SYCL kernel or SYCL_EXTERNAL function}}
61+
62+
cl::sycl::kernel_single_task<class test_kernel3>(
63+
[]() { func3(); });
64+
65+
cl::sycl::kernel_single_task<class test_kernel4>(
66+
[]() { func4(); });
67+
#endif
68+
}

0 commit comments

Comments
 (0)