Skip to content

[SYCL][FPGA] Enable uses_global_work_offset attribute #1010

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,15 @@ def SYCLIntelMaxGlobalWorkDim : InheritableAttr {
let PragmaAttributeSupport = 0;
}

def SYCLIntelUsesGlobalWorkOffset : InheritableAttr {
let Spellings = [CXX11<"intelfpga","uses_global_work_offset">];
let Args = [BoolArgument<"Enabled">];
let LangOpts = [SYCLIsDevice, SYCLIsHost];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [SYCLIntelUsesGlobalWorkOffsetDocs];
let PragmaAttributeSupport = 0;
}

def C11NoReturn : InheritableAttr {
let Spellings = [Keyword<"_Noreturn">];
let Subjects = SubjectList<[Function], ErrorDiag>;
Expand Down
10 changes: 10 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -2009,6 +2009,16 @@ device kernel, the attribute is ignored and it is not propagated to a kernel.
}];
}

def SYCLIntelUsesGlobalWorkOffsetDocs : Documentation {
let Category = DocCatFunction;
let Heading = "uses_global_work_offset (IntelFPGA)";
let Content = [{
Applies to a device function/lambda function or function call operator (of a
function object). If 0, compiler doesn't use the global work offset values for
the device function. Valid values are 0 and 1.
}];
}

def SYCLFPGAPipeDocs : Documentation {
let Category = DocCatStmt;
let Heading = "pipe (read_only, write_only)";
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Basic/AttributeCommonInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ class AttributeCommonInfo {
(ParsedAttr == AT_IntelReqdSubGroupSize && isCXX11Attribute()) ||
ParsedAttr == AT_SYCLIntelNumSimdWorkItems ||
ParsedAttr == AT_SYCLIntelMaxWorkGroupSize ||
ParsedAttr == AT_SYCLIntelMaxGlobalWorkDim)
ParsedAttr == AT_SYCLIntelMaxGlobalWorkDim ||
ParsedAttr == AT_SYCLIntelUsesGlobalWorkOffset)
return true;

return false;
Expand Down
4 changes: 3 additions & 1 deletion clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -637,8 +637,10 @@ def NSReturnsMismatch : DiagGroup<"nsreturns-mismatch">;
def IndependentClassAttribute : DiagGroup<"IndependentClass-attribute">;
def UnknownAttributes : DiagGroup<"unknown-attributes">;
def IgnoredAttributes : DiagGroup<"ignored-attributes">;
def AdjustedAttributes : DiagGroup<"adjusted-attributes">;
def Attributes : DiagGroup<"attributes", [UnknownAttributes,
IgnoredAttributes]>;
IgnoredAttributes,
AdjustedAttributes]>;
def UnknownSanitizers : DiagGroup<"unknown-sanitizers">;
def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args",
[CXX98CompatUnnamedTypeTemplateArgs]>;
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -10324,6 +10324,9 @@ def err_sycl_x_y_z_arguments_must_be_one : Error<
"%0 X-, Y- and Z- sizes must be 1 when %1 attribute is used with value 0">;
def err_intel_attribute_argument_is_not_in_range: Error<
"The value of %0 attribute must be in range from 0 to 3">;
def warn_boolean_attribute_argument_is_not_valid: Warning<
"The value of %0 attribute should be 0 or 1. Adjusted to 1">,
InGroup<AdjustedAttributes>;
def err_sycl_attibute_cannot_be_applied_here
: Error<"%0 attribute cannot be applied to a "
"%select{static function or function in an anonymous namespace"
Expand Down
11 changes: 11 additions & 0 deletions clang/lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,17 @@ void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD,
Fn->setMetadata("max_global_work_dim",
llvm::MDNode::get(Context, AttrMDArgs));
}

if (const SYCLIntelUsesGlobalWorkOffsetAttr *A =
FD->getAttr<SYCLIntelUsesGlobalWorkOffsetAttr>()) {
bool IsEnabled = A->getEnabled();
if (!IsEnabled) {
llvm::Metadata *AttrMDArgs[] = {
llvm::ConstantAsMetadata::get(Builder.getInt32(IsEnabled))};
Fn->setMetadata("uses_global_work_offset",
llvm::MDNode::get(Context, AttrMDArgs));
}
}
}

/// Determine whether the function F ends with a return stmt.
Expand Down
27 changes: 27 additions & 0 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5166,6 +5166,26 @@ static bool checkForDuplicateAttribute(Sema &S, Decl *D,
return false;
}

static void handleUsesGlobalWorkOffsetAttr(Sema &S, Decl *D,
const ParsedAttr &Attr) {
if (S.LangOpts.SYCLIsHost)
return;

checkForDuplicateAttribute<SYCLIntelUsesGlobalWorkOffsetAttr>(S, D, Attr);

uint32_t Enabled;
const Expr *E = Attr.getArgAsExpr(0);
if (!checkUInt32Argument(S, Attr, E, Enabled, 0,
/*StrictlyUnsigned=*/true))
return;
if (Enabled > 1)
S.Diag(Attr.getLoc(), diag::warn_boolean_attribute_argument_is_not_valid)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need to reset Enabled to 1 if the warning is generated, or will that be handled in the generation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need, as it is handled in code generation - CodeGenFunction.cpp:674

<< Attr;

D->addAttr(::new (S.Context)
SYCLIntelUsesGlobalWorkOffsetAttr(S.Context, Attr, Enabled));
}

/// Handle the [[intelfpga::doublepump]] and [[intelfpga::singlepump]] attributes.
/// One but not both can be specified
/// Both are incompatible with the __register__ attribute.
Expand Down Expand Up @@ -7599,6 +7619,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_SYCLIntelMaxGlobalWorkDim:
handleMaxGlobalWorkDimAttr(S, D, AL);
break;
case ParsedAttr::AT_SYCLIntelUsesGlobalWorkOffset:
handleUsesGlobalWorkOffsetAttr(S, D, AL);
break;
case ParsedAttr::AT_VecTypeHint:
handleVecTypeHint(S, D, AL);
break;
Expand Down Expand Up @@ -8082,6 +8105,10 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
} else if (const auto *A = D->getAttr<SYCLIntelMaxWorkGroupSizeAttr>()) {
Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
D->setInvalidDecl();
} else if (const auto *A =
D->getAttr<SYCLIntelUsesGlobalWorkOffsetAttr>()) {
Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
D->setInvalidDecl();
} else if (const auto *A = D->getAttr<VecTypeHintAttr>()) {
Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
D->setInvalidDecl();
Expand Down
11 changes: 10 additions & 1 deletion clang/lib/Sema/SemaSYCL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,14 @@ class MarkDeviceFunction : public RecursiveASTVisitor<MarkDeviceFunction> {
FD->dropAttr<SYCLIntelMaxGlobalWorkDimAttr>();
}
}
if (auto *A = FD->getAttr<SYCLIntelUsesGlobalWorkOffsetAttr>()) {
if (ParentFD == SYCLKernel) {
Attrs.insert(A);
} else {
SemaRef.Diag(A->getLocation(), diag::warn_attribute_ignored) << A;
FD->dropAttr<SYCLIntelUsesGlobalWorkOffsetAttr>();
}
}

// TODO: vec_len_hint should be handled here

Expand Down Expand Up @@ -1357,7 +1365,8 @@ void Sema::MarkDevice(void) {
case attr::Kind::SYCLIntelKernelArgsRestrict:
case attr::Kind::SYCLIntelNumSimdWorkItems:
case attr::Kind::SYCLIntelMaxGlobalWorkDim:
case attr::Kind::SYCLIntelMaxWorkGroupSize: {
case attr::Kind::SYCLIntelMaxWorkGroupSize:
case attr::Kind::SYCLIntelUsesGlobalWorkOffset: {
SYCLKernel->addAttr(A);
break;
}
Expand Down
28 changes: 28 additions & 0 deletions clang/test/CodeGenSYCL/intel-fpga-uses-global-work-offset.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// RUN: %clang_cc1 -triple spir64-unknown-unknown-sycldevice -disable-llvm-passes -fsycl-is-device -emit-llvm -o - %s | FileCheck %s

class Foo {
public:
[[intelfpga::uses_global_work_offset(0)]] void operator()() {}
};

template <typename name, typename Func>
__attribute__((sycl_kernel)) void kernel(Func kernelFunc) {
kernelFunc();
}

void bar() {
Foo boo;
kernel<class kernel_name1>(boo);

kernel<class kernel_name2>(
[]() [[intelfpga::uses_global_work_offset(0)]]{});

kernel<class kernel_name3>(
[]() [[intelfpga::uses_global_work_offset(1)]]{});
}

// CHECK: define spir_kernel void @{{.*}}kernel_name1() {{.*}} !uses_global_work_offset ![[NUM5:[0-9]+]]
// CHECK: define spir_kernel void @{{.*}}kernel_name2() {{.*}} !uses_global_work_offset ![[NUM5]]
// CHECK: define spir_kernel void @{{.*}}kernel_name3() {{.*}} ![[NUM4:[0-9]+]]
// CHECK-NOT: ![[NUM4]] = !{i32 1}
// CHECK: ![[NUM5]] = !{i32 0}
49 changes: 49 additions & 0 deletions clang/test/SemaSYCL/intel-fpga-uses-global-work-offset.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// RUN: %clang_cc1 -Wno-return-type -fsycl-is-device -fcxx-exceptions -fsyntax-only -ast-dump -verify -pedantic %s | FileCheck %s

struct FuncObj {
[[intelfpga::uses_global_work_offset(1)]] void operator()() {}
};

template <typename name, typename Func>
void kernel(Func kernelFunc) {
kernelFunc();
}

int main() {
// CHECK: SYCLIntelUsesGlobalWorkOffsetAttr{{.*}}Enabled
kernel<class test_kernel1>([]() {
FuncObj();
});

// CHECK: SYCLIntelUsesGlobalWorkOffsetAttr
// CHECK-NOT: Enabled
kernel<class test_kernel2>(
[]() [[intelfpga::uses_global_work_offset(0)]]{});

// CHECK: SYCLIntelUsesGlobalWorkOffsetAttr{{.*}}Enabled
// expected-warning@+2{{'uses_global_work_offset' attribute should be 0 or 1. Adjusted to 1}}
kernel<class test_kernel3>(
[]() [[intelfpga::uses_global_work_offset(42)]]{});

// expected-error@+2{{'uses_global_work_offset' attribute requires a non-negative integral compile time constant expression}}
kernel<class test_kernel4>(
[]() [[intelfpga::uses_global_work_offset(-1)]]{});

// expected-error@+2{{'uses_global_work_offset' attribute requires parameter 0 to be an integer constant}}
kernel<class test_kernel5>(
[]() [[intelfpga::uses_global_work_offset("foo")]]{});

kernel<class test_kernel6>([]() {
// expected-error@+1{{'uses_global_work_offset' attribute only applies to functions}}
[[intelfpga::uses_global_work_offset(1)]] int a;
});

// CHECK: SYCLIntelUsesGlobalWorkOffsetAttr{{.*}}
// CHECK-NOT: Enabled
// CHECK: SYCLIntelUsesGlobalWorkOffsetAttr{{.*}}Enabled
// expected-warning@+2{{attribute 'uses_global_work_offset' is already applied}}
kernel<class test_kernel7>(
[]() [[intelfpga::uses_global_work_offset(0), intelfpga::uses_global_work_offset(1)]]{});

return 0;
}