Skip to content

Commit f4ffe62

Browse files
AlexeySachkovbader
authored andcommitted
[SYCL] Add intel::device_indirectly_callable attribute
See documentation in AttrDocs.td Signed-off-by: Alexey Sachkov <[email protected]>
1 parent 4e52d44 commit f4ffe62

File tree

8 files changed

+125
-0
lines changed

8 files changed

+125
-0
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,6 +1058,13 @@ def SYCLScope : Attr {
10581058
let Documentation = [Undocumented];
10591059
}
10601060

1061+
def SYCLDeviceIndirectlyCallable : InheritableAttr {
1062+
let Spellings = [ CXX11<"intel", "device_indirectly_callable"> ];
1063+
let Subjects = SubjectList<[Function]>;
1064+
let LangOpts = [SYCLIsDevice];
1065+
let Documentation = [SYCLDeviceIndirectlyCallableDocs];
1066+
}
1067+
10611068
def C11NoReturn : InheritableAttr {
10621069
let Spellings = [Keyword<"_Noreturn">];
10631070
let Subjects = SubjectList<[Function], ErrorDiag>;

clang/include/clang/Basic/AttrDocs.td

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1825,6 +1825,26 @@ be applied multiple times to the same loop.
18251825
}];
18261826
}
18271827

1828+
def SYCLDeviceIndirectlyCallableDocs : Documentation {
1829+
let Category = DocCatFunction;
1830+
let Heading = "intel::device_indirectly_callable";
1831+
let Content = [{
1832+
This attribute can only be applied to functions and indicates that the
1833+
function must be treated as a device function and must be emitted even if it has
1834+
no direct uses from other SYCL device functions. However, it cannot be applied
1835+
to functions marked as 'static', functions declared within an anonymous
1836+
namespace or class member functions.
1837+
1838+
It also means that function should be available externally and
1839+
cannot be optimized out due to reachability analysis or by any other
1840+
optimization.
1841+
1842+
This attribute allows to pass name and address of the function to a special
1843+
``cl::sycl::intel::get_device_func_ptr`` API call which extracts the device
1844+
function pointer for the specified function.
1845+
}];
1846+
}
1847+
18281848
def RISCVInterruptDocs : Documentation {
18291849
let Category = DocCatFunction;
18301850
let Heading = "interrupt (RISCV)";

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9802,6 +9802,10 @@ def err_sycl_non_std_layout_type : Error<
98029802
"kernel parameter has non-standard layout class/struct type">;
98039803
def err_conflicting_sycl_kernel_attributes : Error<
98049804
"conflicting attributes applied to a SYCL kernel">;
9805+
def err_sycl_device_indirectly_callable_cannot_be_applied_here
9806+
: Error<"device_indirectly_callable attribute cannot be applied to a "
9807+
"%select{static function or function in an anonymous namespace"
9808+
"|class member function}0">;
98059809

98069810
def err_bit_cast_non_trivially_copyable : Error<
98079811
"__builtin_bit_cast %select{source|destination}0 type must be trivially copyable">;

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,11 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
823823
CGM.getCodeGenOpts().StackAlignment)
824824
Fn->addFnAttr("stackrealign");
825825

826+
if (getLangOpts().SYCLIsDevice)
827+
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
828+
if (FD->hasAttr<SYCLDeviceIndirectlyCallableAttr>())
829+
Fn->addFnAttr("referenced-indirectly");
830+
826831
llvm::BasicBlock *EntryBB = createBasicBlock("entry", CurFn);
827832

828833
// Create a marker to make it easy to insert allocas into the entryblock

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4414,6 +4414,27 @@ static void handleOptimizeNoneAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
44144414
D->addAttr(Optnone);
44154415
}
44164416

4417+
static void handleSYCLDeviceIndirectlyCallableAttr(Sema &S, Decl *D,
4418+
const ParsedAttr &AL) {
4419+
auto *FD = cast<FunctionDecl>(D);
4420+
if (!FD->isExternallyVisible()) {
4421+
S.Diag(AL.getLoc(),
4422+
diag::err_sycl_device_indirectly_callable_cannot_be_applied_here)
4423+
<< 0 /* static function or anonymous namespace */;
4424+
return;
4425+
}
4426+
if (isa<CXXMethodDecl>(FD)) {
4427+
S.Diag(AL.getLoc(),
4428+
diag::err_sycl_device_indirectly_callable_cannot_be_applied_here)
4429+
<< 1 /* class member function */;
4430+
return;
4431+
}
4432+
4433+
S.addSyclDeviceDecl(D);
4434+
D->addAttr(SYCLDeviceAttr::CreateImplicit(S.Context));
4435+
handleSimpleAttribute<SYCLDeviceIndirectlyCallableAttr>(S, D, AL);
4436+
}
4437+
44174438
static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
44184439
if (checkAttrMutualExclusion<CUDASharedAttr>(S, D, AL))
44194440
return;
@@ -7089,6 +7110,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
70897110
case ParsedAttr::AT_SYCLKernel:
70907111
handleSimpleAttribute<SYCLKernelAttr>(S, D, AL);
70917112
break;
7113+
case ParsedAttr::AT_SYCLDeviceIndirectlyCallable:
7114+
handleSYCLDeviceIndirectlyCallableAttr(S, D, AL);
7115+
break;
70927116
case ParsedAttr::AT_Format:
70937117
handleFormatAttr(S, D, AL);
70947118
break;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %clang_cc1 -triple spir64-unknown-linux-sycldevice -std=c++11 -fsycl-is-device -disable-llvm-passes -S -emit-llvm -x c++ %s -o - | FileCheck %s
2+
3+
void helper() {}
4+
5+
[[intel::device_indirectly_callable]]
6+
void foo() {
7+
helper();
8+
}
9+
10+
// CHECK: define spir_func void @{{.*foo.*}}() #[[ATTRS_FOO:[0-9]+]]
11+
// CHECK: call spir_func void @{{.*helper.*}}()
12+
//
13+
// CHECK: define spir_func void @{{.*helper.*}}() #[[ATTRS_HELPER:[0-9]+]]
14+
//
15+
// CHECK: attributes #[[ATTRS_FOO]] = { {{.*}} "referenced-indirectly"
16+
// CHECK-NOT: attributes #[[ATTRS_HELPER]] = { {{.*}} "referenced-indirectly"

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
// CHECK-NEXT: ReturnsNonNull (SubjectMatchRule_objc_method, SubjectMatchRule_function)
128128
// CHECK-NEXT: ReturnsTwice (SubjectMatchRule_function)
129129
// CHECK-NEXT: SYCLDevice (SubjectMatchRule_function, SubjectMatchRule_variable)
130+
// CHECK-NEXT: SYCLDeviceIndirectlyCallable (SubjectMatchRule_function)
130131
// CHECK-NEXT: SYCLKernel (SubjectMatchRule_function)
131132
// CHECK-NEXT: ScopedLockable (SubjectMatchRule_record)
132133
// CHECK-NEXT: Section (SubjectMatchRule_function, SubjectMatchRule_variable_is_global, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// RUN: %clang_cc1 -fsycl-is-device -fsyntax-only -verify %s
2+
// RUN: not %clang_cc1 -fsycl-is-device -ast-dump %s | FileCheck %s
3+
// RUN: %clang_cc1 -verify -DNO_SYCL %s
4+
5+
#ifndef NO_SYCL
6+
7+
[[intel::device_indirectly_callable]] // expected-warning {{'device_indirectly_callable' attribute only applies to functions}}
8+
int N;
9+
10+
[[intel::device_indirectly_callable(3)]] // expected-error {{'device_indirectly_callable' attribute takes no arguments}}
11+
void bar() {}
12+
13+
[[intel::device_indirectly_callable]] // expected-error {{device_indirectly_callable attribute cannot be applied to a static function or function in an anonymous namespace}}
14+
static void func1() {}
15+
16+
namespace {
17+
[[intel::device_indirectly_callable]] // expected-error {{device_indirectly_callable attribute cannot be applied to a static function or function in an anonymous namespace}}
18+
void func2() {}
19+
}
20+
21+
class A {
22+
[[intel::device_indirectly_callable]] // expected-error {{device_indirectly_callable attribute cannot be applied to a class member function}}
23+
A() {}
24+
25+
[[intel::device_indirectly_callable]] // expected-error {{device_indirectly_callable attribute cannot be applied to a class member function}}
26+
int func3() {}
27+
};
28+
29+
void helper() {}
30+
31+
[[intel::device_indirectly_callable]]
32+
void foo() {
33+
helper();
34+
}
35+
36+
#else
37+
38+
[[intel::device_indirectly_callable]] // expected-warning {{'device_indirectly_callable' attribute ignored}}
39+
void baz() {}
40+
41+
#endif // NO_SYCL
42+
43+
// CHECK: FunctionDecl {{.*}} helper
44+
// CHECK: SYCLDeviceAttr
45+
//
46+
// CHECK: FunctionDecl {{.*}} foo
47+
// CHECK: SYCLDeviceAttr
48+
// CHECK: SYCLDeviceIndirectlyCallableAttr

0 commit comments

Comments
 (0)