Skip to content

Commit 8bed533

Browse files
vmaksimobader
authored andcommitted
[SYCL][FPGA] Enable uses_global_work_offset attribute (#1010)
`uses_global_work_offset` attribute applies to a device function/lambda function or function call operator. Valid values are 0 and 1. If value >1 is specified as an argument, we warn user that it will be adjusted to 1. As attribute is not ignored in this case and it does not match any existing diagnostic group, the new `AdjustedAttributes` group was added. Signed-off-by: Viktoria Maksimova <[email protected]>
1 parent 97a199f commit 8bed533

File tree

10 files changed

+152
-3
lines changed

10 files changed

+152
-3
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,6 +1144,15 @@ def SYCLIntelMaxGlobalWorkDim : InheritableAttr {
11441144
let PragmaAttributeSupport = 0;
11451145
}
11461146

1147+
def SYCLIntelUsesGlobalWorkOffset : InheritableAttr {
1148+
let Spellings = [CXX11<"intelfpga","uses_global_work_offset">];
1149+
let Args = [BoolArgument<"Enabled">];
1150+
let LangOpts = [SYCLIsDevice, SYCLIsHost];
1151+
let Subjects = SubjectList<[Function], ErrorDiag>;
1152+
let Documentation = [SYCLIntelUsesGlobalWorkOffsetDocs];
1153+
let PragmaAttributeSupport = 0;
1154+
}
1155+
11471156
def C11NoReturn : InheritableAttr {
11481157
let Spellings = [Keyword<"_Noreturn">];
11491158
let Subjects = SubjectList<[Function], ErrorDiag>;

clang/include/clang/Basic/AttrDocs.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2009,6 +2009,16 @@ device kernel, the attribute is ignored and it is not propagated to a kernel.
20092009
}];
20102010
}
20112011

2012+
def SYCLIntelUsesGlobalWorkOffsetDocs : Documentation {
2013+
let Category = DocCatFunction;
2014+
let Heading = "uses_global_work_offset (IntelFPGA)";
2015+
let Content = [{
2016+
Applies to a device function/lambda function or function call operator (of a
2017+
function object). If 0, compiler doesn't use the global work offset values for
2018+
the device function. Valid values are 0 and 1.
2019+
}];
2020+
}
2021+
20122022
def SYCLFPGAPipeDocs : Documentation {
20132023
let Category = DocCatStmt;
20142024
let Heading = "pipe (read_only, write_only)";

clang/include/clang/Basic/AttributeCommonInfo.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,8 @@ class AttributeCommonInfo {
158158
(ParsedAttr == AT_IntelReqdSubGroupSize && isCXX11Attribute()) ||
159159
ParsedAttr == AT_SYCLIntelNumSimdWorkItems ||
160160
ParsedAttr == AT_SYCLIntelMaxWorkGroupSize ||
161-
ParsedAttr == AT_SYCLIntelMaxGlobalWorkDim)
161+
ParsedAttr == AT_SYCLIntelMaxGlobalWorkDim ||
162+
ParsedAttr == AT_SYCLIntelUsesGlobalWorkOffset)
162163
return true;
163164

164165
return false;

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,8 +637,10 @@ def NSReturnsMismatch : DiagGroup<"nsreturns-mismatch">;
637637
def IndependentClassAttribute : DiagGroup<"IndependentClass-attribute">;
638638
def UnknownAttributes : DiagGroup<"unknown-attributes">;
639639
def IgnoredAttributes : DiagGroup<"ignored-attributes">;
640+
def AdjustedAttributes : DiagGroup<"adjusted-attributes">;
640641
def Attributes : DiagGroup<"attributes", [UnknownAttributes,
641-
IgnoredAttributes]>;
642+
IgnoredAttributes,
643+
AdjustedAttributes]>;
642644
def UnknownSanitizers : DiagGroup<"unknown-sanitizers">;
643645
def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args",
644646
[CXX98CompatUnnamedTypeTemplateArgs]>;

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10324,6 +10324,9 @@ def err_sycl_x_y_z_arguments_must_be_one : Error<
1032410324
"%0 X-, Y- and Z- sizes must be 1 when %1 attribute is used with value 0">;
1032510325
def err_intel_attribute_argument_is_not_in_range: Error<
1032610326
"The value of %0 attribute must be in range from 0 to 3">;
10327+
def warn_boolean_attribute_argument_is_not_valid: Warning<
10328+
"The value of %0 attribute should be 0 or 1. Adjusted to 1">,
10329+
InGroup<AdjustedAttributes>;
1032710330
def err_sycl_attibute_cannot_be_applied_here
1032810331
: Error<"%0 attribute cannot be applied to a "
1032910332
"%select{static function or function in an anonymous namespace"

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,17 @@ void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD,
668668
Fn->setMetadata("max_global_work_dim",
669669
llvm::MDNode::get(Context, AttrMDArgs));
670670
}
671+
672+
if (const SYCLIntelUsesGlobalWorkOffsetAttr *A =
673+
FD->getAttr<SYCLIntelUsesGlobalWorkOffsetAttr>()) {
674+
bool IsEnabled = A->getEnabled();
675+
if (!IsEnabled) {
676+
llvm::Metadata *AttrMDArgs[] = {
677+
llvm::ConstantAsMetadata::get(Builder.getInt32(IsEnabled))};
678+
Fn->setMetadata("uses_global_work_offset",
679+
llvm::MDNode::get(Context, AttrMDArgs));
680+
}
681+
}
671682
}
672683

673684
/// Determine whether the function F ends with a return stmt.

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5166,6 +5166,26 @@ static bool checkForDuplicateAttribute(Sema &S, Decl *D,
51665166
return false;
51675167
}
51685168

5169+
static void handleUsesGlobalWorkOffsetAttr(Sema &S, Decl *D,
5170+
const ParsedAttr &Attr) {
5171+
if (S.LangOpts.SYCLIsHost)
5172+
return;
5173+
5174+
checkForDuplicateAttribute<SYCLIntelUsesGlobalWorkOffsetAttr>(S, D, Attr);
5175+
5176+
uint32_t Enabled;
5177+
const Expr *E = Attr.getArgAsExpr(0);
5178+
if (!checkUInt32Argument(S, Attr, E, Enabled, 0,
5179+
/*StrictlyUnsigned=*/true))
5180+
return;
5181+
if (Enabled > 1)
5182+
S.Diag(Attr.getLoc(), diag::warn_boolean_attribute_argument_is_not_valid)
5183+
<< Attr;
5184+
5185+
D->addAttr(::new (S.Context)
5186+
SYCLIntelUsesGlobalWorkOffsetAttr(S.Context, Attr, Enabled));
5187+
}
5188+
51695189
/// Handle the [[intelfpga::doublepump]] and [[intelfpga::singlepump]] attributes.
51705190
/// One but not both can be specified
51715191
/// Both are incompatible with the __register__ attribute.
@@ -7599,6 +7619,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
75997619
case ParsedAttr::AT_SYCLIntelMaxGlobalWorkDim:
76007620
handleMaxGlobalWorkDimAttr(S, D, AL);
76017621
break;
7622+
case ParsedAttr::AT_SYCLIntelUsesGlobalWorkOffset:
7623+
handleUsesGlobalWorkOffsetAttr(S, D, AL);
7624+
break;
76027625
case ParsedAttr::AT_VecTypeHint:
76037626
handleVecTypeHint(S, D, AL);
76047627
break;
@@ -8082,6 +8105,10 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
80828105
} else if (const auto *A = D->getAttr<SYCLIntelMaxWorkGroupSizeAttr>()) {
80838106
Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
80848107
D->setInvalidDecl();
8108+
} else if (const auto *A =
8109+
D->getAttr<SYCLIntelUsesGlobalWorkOffsetAttr>()) {
8110+
Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
8111+
D->setInvalidDecl();
80858112
} else if (const auto *A = D->getAttr<VecTypeHintAttr>()) {
80868113
Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
80878114
D->setInvalidDecl();

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,14 @@ class MarkDeviceFunction : public RecursiveASTVisitor<MarkDeviceFunction> {
469469
FD->dropAttr<SYCLIntelMaxGlobalWorkDimAttr>();
470470
}
471471
}
472+
if (auto *A = FD->getAttr<SYCLIntelUsesGlobalWorkOffsetAttr>()) {
473+
if (ParentFD == SYCLKernel) {
474+
Attrs.insert(A);
475+
} else {
476+
SemaRef.Diag(A->getLocation(), diag::warn_attribute_ignored) << A;
477+
FD->dropAttr<SYCLIntelUsesGlobalWorkOffsetAttr>();
478+
}
479+
}
472480

473481
// TODO: vec_len_hint should be handled here
474482

@@ -1359,7 +1367,8 @@ void Sema::MarkDevice(void) {
13591367
case attr::Kind::SYCLIntelKernelArgsRestrict:
13601368
case attr::Kind::SYCLIntelNumSimdWorkItems:
13611369
case attr::Kind::SYCLIntelMaxGlobalWorkDim:
1362-
case attr::Kind::SYCLIntelMaxWorkGroupSize: {
1370+
case attr::Kind::SYCLIntelMaxWorkGroupSize:
1371+
case attr::Kind::SYCLIntelUsesGlobalWorkOffset: {
13631372
SYCLKernel->addAttr(A);
13641373
break;
13651374
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %clang_cc1 -triple spir64-unknown-unknown-sycldevice -disable-llvm-passes -fsycl-is-device -emit-llvm -o - %s | FileCheck %s
2+
3+
class Foo {
4+
public:
5+
[[intelfpga::uses_global_work_offset(0)]] void operator()() {}
6+
};
7+
8+
template <typename name, typename Func>
9+
__attribute__((sycl_kernel)) void kernel(Func kernelFunc) {
10+
kernelFunc();
11+
}
12+
13+
void bar() {
14+
Foo boo;
15+
kernel<class kernel_name1>(boo);
16+
17+
kernel<class kernel_name2>(
18+
[]() [[intelfpga::uses_global_work_offset(0)]]{});
19+
20+
kernel<class kernel_name3>(
21+
[]() [[intelfpga::uses_global_work_offset(1)]]{});
22+
}
23+
24+
// CHECK: define spir_kernel void @{{.*}}kernel_name1() {{.*}} !uses_global_work_offset ![[NUM5:[0-9]+]]
25+
// CHECK: define spir_kernel void @{{.*}}kernel_name2() {{.*}} !uses_global_work_offset ![[NUM5]]
26+
// CHECK: define spir_kernel void @{{.*}}kernel_name3() {{.*}} ![[NUM4:[0-9]+]]
27+
// CHECK-NOT: ![[NUM4]] = !{i32 1}
28+
// CHECK: ![[NUM5]] = !{i32 0}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// RUN: %clang_cc1 -Wno-return-type -fsycl-is-device -fcxx-exceptions -fsyntax-only -ast-dump -verify -pedantic %s | FileCheck %s
2+
3+
struct FuncObj {
4+
[[intelfpga::uses_global_work_offset(1)]] void operator()() {}
5+
};
6+
7+
template <typename name, typename Func>
8+
void kernel(Func kernelFunc) {
9+
kernelFunc();
10+
}
11+
12+
int main() {
13+
// CHECK: SYCLIntelUsesGlobalWorkOffsetAttr{{.*}}Enabled
14+
kernel<class test_kernel1>([]() {
15+
FuncObj();
16+
});
17+
18+
// CHECK: SYCLIntelUsesGlobalWorkOffsetAttr
19+
// CHECK-NOT: Enabled
20+
kernel<class test_kernel2>(
21+
[]() [[intelfpga::uses_global_work_offset(0)]]{});
22+
23+
// CHECK: SYCLIntelUsesGlobalWorkOffsetAttr{{.*}}Enabled
24+
// expected-warning@+2{{'uses_global_work_offset' attribute should be 0 or 1. Adjusted to 1}}
25+
kernel<class test_kernel3>(
26+
[]() [[intelfpga::uses_global_work_offset(42)]]{});
27+
28+
// expected-error@+2{{'uses_global_work_offset' attribute requires a non-negative integral compile time constant expression}}
29+
kernel<class test_kernel4>(
30+
[]() [[intelfpga::uses_global_work_offset(-1)]]{});
31+
32+
// expected-error@+2{{'uses_global_work_offset' attribute requires parameter 0 to be an integer constant}}
33+
kernel<class test_kernel5>(
34+
[]() [[intelfpga::uses_global_work_offset("foo")]]{});
35+
36+
kernel<class test_kernel6>([]() {
37+
// expected-error@+1{{'uses_global_work_offset' attribute only applies to functions}}
38+
[[intelfpga::uses_global_work_offset(1)]] int a;
39+
});
40+
41+
// CHECK: SYCLIntelUsesGlobalWorkOffsetAttr{{.*}}
42+
// CHECK-NOT: Enabled
43+
// CHECK: SYCLIntelUsesGlobalWorkOffsetAttr{{.*}}Enabled
44+
// expected-warning@+2{{attribute 'uses_global_work_offset' is already applied}}
45+
kernel<class test_kernel7>(
46+
[]() [[intelfpga::uses_global_work_offset(0), intelfpga::uses_global_work_offset(1)]]{});
47+
48+
return 0;
49+
}

0 commit comments

Comments
 (0)