Skip to content

Commit 9318194

Browse files
committed
[SYCL] Fix attribute emission handling
1 parent 41fb3aa commit 9318194

File tree

3 files changed

+76
-1
lines changed

3 files changed

+76
-1
lines changed

clang/include/clang/Basic/AttrDocs.td

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4526,7 +4526,9 @@ This attribute can only be applied to functions and indicates that the function
45264526
is only available for the device. It allows functions marked with it to
45274527
overload existing functions without the attribute, in which case the overload
45284528
with the attribute will be used on the device side and the overload without
4529-
will be used on the host side.
4529+
will be used on the host side. Note: as opposed to ``sycl_device`` this does
4530+
not mark the function as being exported, both attributes can be used together
4531+
if needed.
45304532
}];
45314533
}
45324534

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4414,6 +4414,43 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
44144414
}
44154415
}
44164416

4417+
4418+
// When using SYCLDeviceOnlyAttr, there can be two functions with the same
4419+
// mangling, the host function and the device overload. So when compiling for
4420+
// device we need to make sure we're selecting the SYCLDeviceOnlyAttr
4421+
// overload and dropping the host overload.
4422+
if (LangOpts.SYCLIsDevice) {
4423+
StringRef MangledName = getMangledName(GD);
4424+
auto DDI = DeferredDecls.find(MangledName);
4425+
// If we have an existing declaration with the same mangling for this
4426+
// symbol it may be a SYCLDeviceOnlyAttr case.
4427+
if (DDI != DeferredDecls.end()) {
4428+
auto *G = cast<ValueDecl>(DeferredDecls[MangledName].getDecl());
4429+
4430+
if (!G->hasAttr<SYCLDeviceOnlyAttr>() &&
4431+
Global->hasAttr<SYCLDeviceOnlyAttr>() &&
4432+
Global->hasAttr<SYCLDeviceAttr>()) {
4433+
// If the host declaration was already processed and the device only
4434+
// declaration is also a sycl external declaration, remove the host
4435+
// variant and skip. The device only variant will be generated later
4436+
// as it's marked sycl external.
4437+
DeferredDecls.erase(DDI);
4438+
return;
4439+
} else if (!G->hasAttr<SYCLDeviceOnlyAttr>() &&
4440+
Global->hasAttr<SYCLDeviceOnlyAttr>()) {
4441+
// If the host declaration was already processed, replace it with the
4442+
// device only declaration.
4443+
DeferredDecls[MangledName] = GD;
4444+
return;
4445+
} else if (!Global->hasAttr<SYCLDeviceOnlyAttr>() &&
4446+
G->hasAttr<SYCLDeviceOnlyAttr>()) {
4447+
// If the device only declaration was already processed, skip the
4448+
// host declaration.
4449+
return;
4450+
}
4451+
}
4452+
}
4453+
44174454
// clang::ParseAST ensures that we emit the SYCL devices at the end, so
44184455
// anything that is a device (or indirectly called) will be handled later.
44194456
if (LangOpts.SYCLIsDevice && MustBeEmitted(Global)) {

clang/test/CodeGenSYCL/sycl-device-only.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@ __attribute__((sycl_device)) int bar(int b) {
1515
return foo(b);
1616
}
1717

18+
// Verify that the order of declaration doesn't change the behavior.
19+
//
20+
// CHECK-LABEL: _Z3fooswapi
21+
// CHECKH: %add = add nsw i32 %0, 10
22+
// CHECKD: %add = add nsw i32 %0, 20
23+
__attribute__((sycl_device_only)) int fooswap(int a) { return a + 20; }
24+
int fooswap(int a) { return a + 10; }
25+
26+
// Use a `sycl_device` function as entry point
27+
__attribute__((sycl_device)) int barswap(int b) {
28+
return fooswap(b);
29+
}
30+
1831
// Verify that in extern C the attribute enables mangling.
1932
extern "C" {
2033
// CHECK-LABEL: _Z3fooci
@@ -28,3 +41,26 @@ __attribute__((sycl_device)) int barc(int b) {
2841
return fooc(b);
2942
}
3043
}
44+
45+
// Check that both attributes can work together
46+
// CHECK-LABEL: _Z3fooai
47+
// CHECKH: %add = add nsw i32 %0, 10
48+
// CHECKD: %add = add nsw i32 %0, 20
49+
int fooa(int a) { return a + 10; }
50+
__attribute__((sycl_device_only, sycl_device)) int fooa(int a) { return a + 20; }
51+
52+
// Use a `sycl_device` function as entry point
53+
__attribute__((sycl_device)) int bara(int b) {
54+
return fooa(b);
55+
}
56+
57+
// CHECK-LABEL: _Z3fooaswapi
58+
// CHECKH: %add = add nsw i32 %0, 10
59+
// CHECKD: %add = add nsw i32 %0, 20
60+
__attribute__((sycl_device_only, sycl_device)) int fooaswap(int a) { return a + 20; }
61+
int fooaswap(int a) { return a + 10; }
62+
63+
// Use a `sycl_device` function as entry point
64+
__attribute__((sycl_device)) int baraswap(int b) {
65+
return fooaswap(b);
66+
}

0 commit comments

Comments
 (0)