Skip to content

Commit df49dcc

Browse files
authored
[SYCL] Remove need to mark free functions with SYCL_EXTERNAL attribute (#14170)
This change removes the need to mark free functions with the SYCL_EXTERNAL attribute. Within clang some instances of add_ir_attribute_function contain non-constexpr expressions (for example, introduced by sycl/ext/oneapi/matrix/matrix-unified.hpp). This occurs when there are non-instantiated functions/methods used in defining attribute values. These expressions are converted into constexprs later in the compilation pipeline. Calling getAttributeNameValuePairs unconditionally leads to compile-time asserts. To account for the non-constexpr attribute values, a check is first made to rule out instances of the problematic values.
1 parent 404f812 commit df49dcc

File tree

7 files changed

+119
-19
lines changed

7 files changed

+119
-19
lines changed

clang/lib/Sema/SemaDecl.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16318,10 +16318,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
1631816318
checkTypeSupport(FD->getType(), FD->getLocation(), FD);
1631916319

1632016320
// Handle free functions.
16321-
if (LangOpts.SYCLIsDevice && FD->hasAttr<SYCLDeviceAttr>() && Body &&
16322-
(FD->getTemplatedKind() == FunctionDecl::TK_NonTemplate ||
16323-
FD->getTemplatedKind() ==
16324-
FunctionDecl::TK_FunctionTemplateSpecialization))
16321+
if (LangOpts.SYCLIsDevice && Body && !FD->isDependentContext())
1632516322
SYCL().ProcessFreeFunction(FD);
1632616323

1632716324
return dcl;

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,10 +1065,8 @@ static target getAccessTarget(QualType FieldTy,
10651065
AccTy->getTemplateArgs()[3].getAsIntegral().getExtValue());
10661066
}
10671067

1068-
// FIXME: Free functions must have void return type, be declared at file scope,
1069-
// outside any namespaces, and with the SYCL_DEVICE attribute. If the
1070-
// SYCL_DEVICE attribute is not specified this function is not entered since the
1071-
// possibility of the function being a free function is ruled out already.
1068+
// FIXME: Free functions must have void return type and be declared at file
1069+
// scope, outside any namespaces.
10721070
static bool isFreeFunction(SemaSYCL &SemaSYCLRef, const FunctionDecl *FD) {
10731071
for (auto *IRAttr : FD->specific_attrs<SYCLAddIRAttributesFunctionAttr>()) {
10741072
SmallVector<std::pair<std::string, std::string>, 4> NameValuePairs =

clang/test/CodeGenSYCL/free_function_int_header.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
#include "sycl.hpp"
99

1010
// First overload of function ff_2.
11-
__attribute__((sycl_device))
1211
[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel",
1312
2)]] void
1413
ff_2(int *ptr, int start, int end) {
@@ -17,7 +16,6 @@ ff_2(int *ptr, int start, int end) {
1716
}
1817

1918
// Second overload of function ff_2.
20-
__attribute__((sycl_device))
2119
[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel",
2220
2)]] void
2321
ff_2(int* ptr, int start, int end, int value) {
@@ -27,7 +25,6 @@ __attribute__((sycl_device))
2725

2826
// Templated definition of function ff_3.
2927
template <typename T>
30-
__attribute__((sycl_device))
3128
[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 2)]] void
3229
ff_3(T *ptr, T start, T end) {
3330
for (int i = start; i <= end; i++)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//==---- free_function_implicit_sycl_extern.cpp ----------------------------==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// RUN: %clang_cc1 -fsycl-is-device -triple -spir64-unknown-unknown -verify %s
10+
11+
// expected-no-diagnostics
12+
13+
// This test confirms that functions or methods with add_ir_attributes_function
14+
// attribute values in dependent contexts can be handled without assertions when
15+
// checking for the presence of free function properties.
16+
17+
template <typename T> constexpr int value() { return 5; }
18+
19+
// In this struct the function the add_ir_attributes_function values for "S()"
20+
// are as follows. Note that the "value" is represented as a CallExpr.
21+
// `-SYCLAddIRAttributesFunctionAttr 0x562ec6c13390 < col:5, col : 67 >
22+
// | -ConstantExpr 0x562ec6c13440 < col:49 > 'const char[5]' lvalue
23+
// | |-value: LValue <todo>
24+
// | `-StringLiteral 0x562ec6c13160 < col:49 > 'const char[5]' lvalue "name"
25+
// `-CallExpr 0x562ec6c13220 < col:57, col : 66 > '<dependent type>'
26+
// `-UnresolvedLookupExpr 0x562ec6c131a8 < col:57, col : 64 > '<dependent type>' lvalue(ADL) = 'value' 0x562ec6bea700
27+
// `-TemplateArgument type 'T':'type-parameter-0-0'
28+
// `-TemplateTypeParmType 0x562ec6bea8b0 'T' dependent depth 0 index 0
29+
// `-TemplateTypeParm 0x562ec6bea860 'T'
30+
31+
template <typename T> struct S {
32+
#if defined(__SYCL_DEVICE_ONLY__)
33+
[[__sycl_detail__::add_ir_attributes_function("name", value<T>())]]
34+
#endif
35+
S() {
36+
}
37+
};
38+
39+
// For the free function "f" the add_ir_attributes_function values are:
40+
// | -SYCLAddIRAttributesFunctionAttr 0x56361c3c3ea8 < line:37 : 32, line : 39 : 15 >
41+
// | |-ConstantExpr 0x56361c3c3f00 < line:38 : 5 > 'const char[5]' lvalue
42+
// | | |-value: LValue <todo>
43+
// | | `-StringLiteral 0x56361c398cf0 < col:5 > 'const char[5]' lvalue "name"
44+
// | `-ConstantExpr 0x56361c3c3f60 < line:39 : 5, col : 14 > 'int'
45+
// | |-value: Int 5
46+
// | `-CallExpr 0x56361c3c3e88 < col:5, col : 14 > 'int'
47+
// | `-ImplicitCastExpr 0x56361c3c3e70 < col:5, col : 12 > 'int (*)()' < FunctionToPointerDecay >
48+
// | `-DeclRefExpr 0x56361c3c3dc0 < col:5, col : 12 > 'int ()' lvalue Function 0x56361c3c3cc8 'value' 'int ()' (FunctionTemplate 0x56361c398a90 'value')
49+
50+
template <typename T>
51+
__attribute__((sycl_device)) [[__sycl_detail__::add_ir_attributes_function(
52+
"name",
53+
value<T>())]] [[__sycl_detail__::
54+
add_ir_attributes_function("sycl-single-task-kernel",
55+
0)]] void
56+
f(T i) {}
57+
58+
template void f(int i);

sycl/test-e2e/KernelAndProgram/free_function_apis.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313
using namespace sycl;
1414

15-
SYCL_EXTERNAL
1615
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(
1716
(ext::oneapi::experimental::nd_range_kernel<2>))
1817
void ff_2(int *ptr, int start) {
@@ -25,8 +24,9 @@ void ff_2(int *ptr, int start) {
2524

2625
// Templated free function definition.
2726
template <typename T>
28-
SYCL_EXTERNAL SYCL_EXT_ONEAPI_FUNCTION_PROPERTY((
29-
ext::oneapi::experimental::single_task_kernel)) void ff_3(T *ptr, T start) {
27+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(
28+
(ext::oneapi::experimental::single_task_kernel))
29+
void ff_3(T *ptr, T start) {
3030
int(&ptr2D)[4][4] = *reinterpret_cast<int(*)[4][4]>(ptr);
3131
nd_item<2> Item = ext::oneapi::this_work_item::get_nd_item<2>();
3232
id<2> GId = Item.get_global_id();

sycl/test-e2e/KernelAndProgram/free_function_kernels.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ bool checkUSM(int *usmPtr, int size, int *Result) {
4646
return false;
4747
}
4848

49-
extern "C" SYCL_EXTERNAL SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(
49+
extern "C" SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(
5050
(ext::oneapi::experimental::single_task_kernel)) void ff_0(int *ptr,
5151
int start,
5252
int end) {
@@ -96,7 +96,6 @@ bool test_0(queue Queue) {
9696
}
9797

9898
// Overloaded free function definition.
99-
SYCL_EXTERNAL
10099
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(
101100
(ext::oneapi::experimental::nd_range_kernel<1>))
102101
void ff_1(int *ptr, int start, int end) {
@@ -147,7 +146,6 @@ bool test_1(queue Queue) {
147146
}
148147

149148
// Overloaded free function definition.
150-
SYCL_EXTERNAL
151149
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(
152150
(ext::oneapi::experimental::nd_range_kernel<2>))
153151
void ff_1(int *ptr, int start) {
@@ -203,8 +201,9 @@ bool test_2(queue Queue) {
203201

204202
// Templated free function definition.
205203
template <typename T>
206-
SYCL_EXTERNAL SYCL_EXT_ONEAPI_FUNCTION_PROPERTY((
207-
ext::oneapi::experimental::nd_range_kernel<2>)) void ff_3(T *ptr, T start) {
204+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(
205+
(ext::oneapi::experimental::nd_range_kernel<2>))
206+
void ff_3(T *ptr, T start) {
208207
int(&ptr2D)[4][4] = *reinterpret_cast<int(*)[4][4]>(ptr);
209208
nd_item<2> Item = ext::oneapi::this_work_item::get_nd_item<2>();
210209
id<2> GId = Item.get_global_id();
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//==---- free_function_errors.cpp --------------------------------------==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// RUN: %clangxx -fsyntax-only -fsycl-device-only -Xclang -verify -Xclang -verify-ignore-unexpected=note %s
10+
11+
#include <array>
12+
#include <sycl/sycl.hpp>
13+
14+
using namespace sycl;
15+
16+
struct S {
17+
int i;
18+
float f;
19+
};
20+
21+
union U {
22+
int i;
23+
float f;
24+
};
25+
26+
using accType = accessor<int, 1, access::mode::read_write>;
27+
28+
// expected-error@+3 {{'struct S' cannot be used as the type of a kernel parameter}}
29+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(
30+
(ext::oneapi::experimental::single_task_kernel))
31+
void ff(struct S s) {}
32+
33+
// expected-error@+3 {{'union U' cannot be used as the type of a kernel parameter}}
34+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(
35+
(ext::oneapi::experimental::single_task_kernel))
36+
void ff(union U u) {}
37+
38+
// expected-error@+3 {{'accType' (aka 'accessor<int, 1, access::mode::read_write>') cannot be used as the type of a kernel parameter}}
39+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(
40+
(ext::oneapi::experimental::single_task_kernel))
41+
void ff(accType acc) {}
42+
43+
// expected-error@+3 {{'std::array<int, 10>' cannot be used as the type of a kernel parameter}}
44+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(
45+
(ext::oneapi::experimental::single_task_kernel))
46+
void ff(std::array<int, 10> a) {}
47+
48+
// expected-error@+3 {{'int &' cannot be used as the type of a kernel parameter}}
49+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(
50+
(ext::oneapi::experimental::single_task_kernel))
51+
void ff(int &ip) {}

0 commit comments

Comments
 (0)