Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -1293,7 +1293,7 @@ def SYCLIntelMaxWorkGroupSize : InheritableAttr {
def SYCLIntelMaxGlobalWorkDim : InheritableAttr {
let Spellings = [CXX11<"intelfpga","max_global_work_dim">,
CXX11<"intel","max_global_work_dim">];
let Args = [UnsignedArgument<"Number">];
let Args = [ExprArgument<"Value">];
let LangOpts = [SYCLIsDevice, SYCLIsHost];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [SYCLIntelMaxGlobalWorkDimAttrDocs];
Expand Down
22 changes: 18 additions & 4 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -12963,10 +12963,24 @@ void Sema::addIntelSYCLSingleArgFunctionAttr(Decl *D,
return;
}
int32_t ArgInt = ArgVal->getSExtValue();
if (ArgInt <= 0) {
Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
<< CI.getAttrName() << /*positive*/ 0;
return;
if (CI.getParsedKind() == ParsedAttr::AT_SYCLIntelNumSimdWorkItems ||
CI.getParsedKind() == ParsedAttr::AT_IntelReqdSubGroupSize) {
if (ArgInt <= 0) {
Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
<< CI.getAttrName() << /*positive*/ 0;
return;
}
} else if (CI.getParsedKind() == ParsedAttr::AT_SYCLIntelMaxGlobalWorkDim) {
if (ArgInt < 0) {
Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
<< CI.getAttrName() << /*positive*/ 0;
return;
} else if (ArgInt > 3) {
Diag(E->getExprLoc(),
diag::err_intel_attribute_argument_is_not_in_range)
<< CI.getAttrName();
return;
}
}
}

Expand Down
8 changes: 6 additions & 2 deletions clang/lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -682,8 +682,12 @@ void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD,

if (const SYCLIntelMaxGlobalWorkDimAttr *A =
FD->getAttr<SYCLIntelMaxGlobalWorkDimAttr>()) {
llvm::Metadata *AttrMDArgs[] = {
llvm::ConstantAsMetadata::get(Builder.getInt32(A->getNumber()))};
llvm::LLVMContext &Context = getLLVMContext();
Optional<llvm::APSInt> ArgVal =
A->getValue()->getIntegerConstantExpr(FD->getASTContext());
assert(ArgVal.hasValue() && "Not an integer constant expression");
llvm::Metadata *AttrMDArgs[] = {llvm::ConstantAsMetadata::get(
Builder.getInt32(ArgVal->getSExtValue()))};
Fn->setMetadata("max_global_work_dim",
llvm::MDNode::get(Context, AttrMDArgs));
}
Expand Down
20 changes: 6 additions & 14 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2926,7 +2926,7 @@ static bool checkWorkGroupSizeValues(Sema &S, Decl *D, const ParsedAttr &Attr,
}

if (const auto *A = D->getAttr<SYCLIntelMaxGlobalWorkDimAttr>())
if (A->getNumber() == 0)
if (A->getValue() == 0)
Result &= checkZeroDim(A, WGSize[0], WGSize[1], WGSize[2],
/*ReverseAttrs=*/true);

Expand Down Expand Up @@ -3087,34 +3087,26 @@ static void handleMaxGlobalWorkDimAttr(Sema &S, Decl *D,
if (D->isInvalidDecl())
return;

uint32_t MaxGlobalWorkDim;
const Expr *E = Attr.getArgAsExpr(0);
if (!checkUInt32Argument(S, Attr, E, MaxGlobalWorkDim, 0,
/*StrictlyUnsigned=*/true))
return;

if (MaxGlobalWorkDim > 3) {
S.Diag(Attr.getLoc(), diag::err_intel_attribute_argument_is_not_in_range)
<< Attr;
return;
}
Expr *E = Attr.getArgAsExpr(0);

uint32_t MaxGlobalWorkDim;
if (MaxGlobalWorkDim == 0) {
uint32_t WGSize[3] = {1, 1, 1};
if (!checkWorkGroupSizeValues(S, D, Attr, WGSize)) {
D->setInvalidDecl();
return;
}
}

if (D->getAttr<SYCLIntelMaxGlobalWorkDimAttr>())
S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr;

if (checkDeprecatedSYCLAttributeSpelling(S, Attr))
S.Diag(Attr.getLoc(), diag::note_spelling_suggestion)
<< "'intel::max_global_work_dim'";

D->addAttr(::new (S.Context) SYCLIntelMaxGlobalWorkDimAttr(
S.Context, Attr, MaxGlobalWorkDim));
S.addIntelSYCLSingleArgFunctionAttr<SYCLIntelMaxGlobalWorkDimAttr>(D, Attr,
E);
}

static void handleVecTypeHint(Sema &S, Decl *D, const ParsedAttr &AL) {
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,12 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
*this, TemplateArgs, SYCLIntelSchedulerTargetFmaxMhz, New);
continue;
}
if (const auto *SYCLIntelMaxGlobalWorkDim =
dyn_cast<SYCLIntelMaxGlobalWorkDimAttr>(TmplAttr)) {
instantiateIntelSYCLFunctionAttr<SYCLIntelMaxGlobalWorkDimAttr>(
*this, TemplateArgs, SYCLIntelMaxGlobalWorkDim, New);
continue;
}
// Existing DLL attribute on the instantiation takes precedence.
if (TmplAttr->getKind() == attr::DLLExport ||
TmplAttr->getKind() == attr::DLLImport) {
Expand Down
39 changes: 26 additions & 13 deletions clang/test/CodeGenSYCL/intel-max-global-work-dim.cpp
Original file line number Diff line number Diff line change
@@ -1,24 +1,37 @@
// RUN: %clang_cc1 -fsycl -fsycl-is-device -triple spir64-unknown-unknown-sycldevice -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -fsycl -fsycl-is-device -internal-isystem %S/Inputs -triple spir64-unknown-unknown-sycldevice -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s

#include "sycl.hpp"

using namespace cl::sycl;
queue q;

class Foo {
public:
[[intel::max_global_work_dim(1)]] void operator()() const {}
};

template <typename name, typename Func>
__attribute__((sycl_kernel)) void kernel(const Func &kernelFunc) {
kernelFunc();
}
template <int SIZE>
class Functor {
public:
[[intel::max_global_work_dim(SIZE)]] void operator()() const {}
};

int main() {
q.submit([&](handler &h) {
Foo boo;
h.single_task<class kernel_name1>(boo);

void bar() {
Foo boo;
kernel<class kernel_name1>(boo);
h.single_task<class kernel_name2>(
[]() [[intel::max_global_work_dim(2)]]{});

kernel<class kernel_name2>(
[]() [[intel::max_global_work_dim(2)]]{});
Functor<2> f;
h.single_task<class kernel_name3>(f);
});
return 0;
}

// CHECK: define spir_kernel void @{{.*}}kernel_name1() {{.*}} !max_global_work_dim ![[NUM1:[0-9]+]]
// CHECK: define spir_kernel void @{{.*}}kernel_name2() {{.*}} !max_global_work_dim ![[NUM8:[0-9]+]]
// CHECK: define spir_kernel void @{{.*}}kernel_name1"() #0 {{.*}} !max_global_work_dim ![[NUM1:[0-9]+]]
// CHECK: define spir_kernel void @{{.*}}kernel_name2"() #0 {{.*}} !max_global_work_dim ![[NUM2:[0-9]+]]
// CHECK: define spir_kernel void @{{.*}}kernel_name3"() #0 {{.*}} !max_global_work_dim ![[NUM2]]
// CHECK: ![[NUM1]] = !{i32 1}
// CHECK: ![[NUM8]] = !{i32 2}
// CHECK: ![[NUM2]] = !{i32 2}
115 changes: 115 additions & 0 deletions clang/test/SemaSYCL/intel-max-global-work-dim-device.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// RUN: %clang_cc1 %s -fsyntax-only -fsycl -fsycl-is-device -internal-isystem %S/Inputs -Wno-sycl-2017-compat -triple spir64 -DTRIGGER_ERROR -verify
// RUN: %clang_cc1 %s -fsyntax-only -ast-dump -fsycl -fsycl-is-device -internal-isystem %S/Inputs -Wno-sycl-2017-compat -triple spir64 | FileCheck %s

#include "sycl.hpp"

using namespace cl::sycl;
queue q;

#ifndef __SYCL_DEVICE_ONLY__
struct FuncObj {
[[intel::max_global_work_dim(1)]] // expected-no-diagnostics
void
operator()() const {}
};

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

void foo() {
kernel<class test_kernel1>(
FuncObj());
}

#else // __SYCL_DEVICE_ONLY__

[[intel::max_global_work_dim(2)]] void func_do_not_ignore() {}

struct FuncObj {
[[intel::max_global_work_dim(1)]] void operator()() const {}
};

struct Func {
// expected-warning@+2 {{attribute 'intelfpga::max_global_work_dim' is deprecated}}
// expected-note@+1 {{did you mean to use 'intel::max_global_work_dim' instead?}}
[[intelfpga::max_global_work_dim(2)]] void operator()() const {}
};

struct TRIFuncObjGood1 {
[[intel::max_global_work_dim(0)]]
[[intel::max_work_group_size(1, 1, 1)]]
[[cl::reqd_work_group_size(1, 1, 1)]] void
operator()() const {}
};

struct TRIFuncObjGood2 {
[[intel::max_global_work_dim(3)]]
[[intel::max_work_group_size(8, 1, 1)]]
[[cl::reqd_work_group_size(4, 1, 1)]] void
operator()() const {}
};

#ifdef TRIGGER_ERROR
struct TRIFuncObjBad {
[[intel::max_global_work_dim(0)]]
[[intel::max_work_group_size(8, 8, 8)]] // expected-error{{'max_work_group_size' X-, Y- and Z- sizes must be 1 when 'max_global_work_dim' attribute is used with value 0}}
[[cl::reqd_work_group_size(4, 4, 4)]] // expected-error{{'reqd_work_group_size' X-, Y- and Z- sizes must be 1 when 'max_global_work_dim' attribute is used with value 0}}
void
operator()() const {}
};
#endif // TRIGGER_ERROR

int main() {
q.submit([&](handler &h) {
// CHECK-LABEL: FunctionDecl {{.*}}test_kernel1
// CHECK: SYCLIntelMaxGlobalWorkDimAttr {{.*}}
// CHECK-NEXT: IntegerLiteral{{.*}}1{{$}}
h.single_task<class test_kernel1>(FuncObj());

// CHECK-LABEL: FunctionDecl {{.*}}test_kernel2
// CHECK: SYCLIntelMaxGlobalWorkDimAttr {{.*}}
// CHECK-NEXT: IntegerLiteral{{.*}}2{{$}}
// expected-warning@+3 {{attribute 'intelfpga::max_global_work_dim' is deprecated}}
// expected-note@+2 {{did you mean to use 'intel::max_global_work_dim' instead?}}
h.single_task<class test_kernel2>(
[]() [[intelfpga::max_global_work_dim(2)]]{});

// CHECK-LABEL: FunctionDecl {{.*}}test_kernel3
// CHECK: SYCLIntelMaxGlobalWorkDimAttr {{.*}}
h.single_task<class test_kernel3>(
[]() { func_do_not_ignore(); });

h.single_task<class test_kernel4>(TRIFuncObjGood1());
// CHECK-LABEL: FunctionDecl {{.*}}test_kernel4
// CHECK: ReqdWorkGroupSizeAttr {{.*}} 1 1 1
// CHECK: SYCLIntelMaxWorkGroupSizeAttr {{.*}} 1 1 1
// CHECK: SYCLIntelMaxGlobalWorkDimAttr {{.*}}
// CHECK-NEXT: IntegerLiteral{{.*}}0{{$}}

h.single_task<class test_kernel5>(TRIFuncObjGood2());
// CHECK-LABEL: FunctionDecl {{.*}}test_kernel5
// CHECK: ReqdWorkGroupSizeAttr {{.*}} 1 1 4
// CHECK: SYCLIntelMaxWorkGroupSizeAttr {{.*}} 1 1 8
// CHECK: SYCLIntelMaxGlobalWorkDimAttr {{.*}}
// CHECK-NEXT: IntegerLiteral{{.*}}3{{$}}
#ifdef TRIGGER_ERROR
[[intel::max_global_work_dim(1)]] int Var = 0; // expected-error{{'max_global_work_dim' attribute only applies to functions}}

h.single_task<class test_kernel6>(
[]() [[intel::max_global_work_dim(-8)]]{}); // expected-error{{'max_global_work_dim' attribute requires a positive integral compile time constant expression}}

h.single_task<class test_kernel7>(
[]() [[intel::max_global_work_dim(3),
intel::max_global_work_dim(2)]]{}); // expected-warning{{attribute 'max_global_work_dim' is already applied with different parameters}}

h.single_task<class test_kernel8>(TRIFuncObjBad());

h.single_task<class test_kernel9>(
[]() [[intel::max_global_work_dim(4)]]{}); // expected-error{{The value of 'max_global_work_dim' attribute must be in range from 0 to 3}}
});
return 0;
#endif // TRIGGER_ERROR
}
#endif // __SYCL_DEVICE_ONLY__
8 changes: 8 additions & 0 deletions clang/test/SemaSYCL/intel-max-global-work-dim-host.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// RUN: %clang_cc1 -fsycl -fsycl-is-host -Wno-sycl-2017-compat -fsyntax-only -verify %s
// expected-no-diagnostics

[[intel::max_global_work_dim(2)]] void func_do_not_ignore() {}

struct FuncObj {
[[intel::max_global_work_dim(1)]] void operator()() const {}
};
Loading