Skip to content

[SYCL] Add template parameter support for num_simd_work_items attribute #2510

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 7 commits into from
Sep 23, 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
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -1209,7 +1209,7 @@ def SYCLIntelKernelArgsRestrict : InheritableAttr {

def SYCLIntelNumSimdWorkItems : InheritableAttr {
let Spellings = [CXX11<"intelfpga","num_simd_work_items">];
let Args = [UnsignedArgument<"Number">];
let Args = [ExprArgument<"Value">];
let LangOpts = [SYCLIsDevice, SYCLIsHost];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [SYCLIntelNumSimdWorkItemsAttrDocs];
Expand Down Expand Up @@ -1300,7 +1300,7 @@ def LoopUnrollHint : InheritableAttr {
def IntelReqdSubGroupSize: InheritableAttr {
let Spellings = [GNU<"intel_reqd_sub_group_size">,
CXX11<"intel", "reqd_sub_group_size">];
let Args = [ExprArgument<"SubGroupSize">];
let Args = [ExprArgument<"Value">];
let Subjects = SubjectList<[Function, CXXMethod], ErrorDiag>;
let Documentation = [IntelReqdSubGroupSizeDocs];
let LangOpts = [OpenCL, SYCLIsDevice, SYCLIsHost];
Expand Down
33 changes: 28 additions & 5 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -9986,7 +9986,9 @@ class Sema final {
Expr *E);
void AddIntelFPGABankBitsAttr(Decl *D, const AttributeCommonInfo &CI,
Expr **Exprs, unsigned Size);

template <typename AttrType>
void addIntelSYCLSingleArgFunctionAttr(Decl *D, const AttributeCommonInfo &CI,
Expr *E);
/// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
void AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
bool IsPackExpansion);
Expand Down Expand Up @@ -10041,10 +10043,6 @@ class Sema final {
bool checkAllowedSYCLInitializer(VarDecl *VD,
bool CheckValueDependent = false);

// Adds an intel_reqd_sub_group_size attribute to a particular declaration.
void addIntelReqdSubGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI,
Expr *E);

//===--------------------------------------------------------------------===//
// C++ Coroutines TS
//
Expand Down Expand Up @@ -12836,6 +12834,31 @@ class Sema final {
}
};

template <typename AttrType>
void Sema::addIntelSYCLSingleArgFunctionAttr(Decl *D,
const AttributeCommonInfo &CI,
Expr *E) {
assert(E && "Attribute must have an argument.");

if (!E->isInstantiationDependent()) {
Optional<llvm::APSInt> ArgVal = E->getIntegerConstantExpr(getASTContext());
if (!ArgVal) {
Diag(E->getExprLoc(), diag::err_attribute_argument_type)
<< CI.getAttrName() << AANT_ArgumentIntegerConstant
<< E->getSourceRange();
return;
}
int32_t ArgInt = ArgVal->getSExtValue();
if (ArgInt <= 0) {
Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
<< CI.getAttrName() << /*positive*/ 0;
return;
}
}

D->addAttr(::new (Context) AttrType(Context, CI, E));
}

template <typename AttrType>
void Sema::AddOneConstantValueAttr(Decl *D, const AttributeCommonInfo &CI,
Expr *E) {
Expand Down
10 changes: 7 additions & 3 deletions clang/lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD,
FD->getAttr<IntelReqdSubGroupSizeAttr>()) {
llvm::LLVMContext &Context = getLLVMContext();
Optional<llvm::APSInt> ArgVal =
A->getSubGroupSize()->getIntegerConstantExpr(FD->getASTContext());
A->getValue()->getIntegerConstantExpr(FD->getASTContext());
assert(ArgVal.hasValue() && "Not an integer constant expression");
llvm::Metadata *AttrMDArgs[] = {llvm::ConstantAsMetadata::get(
Builder.getInt32(ArgVal->getSExtValue()))};
Expand All @@ -629,8 +629,12 @@ void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD,

if (const SYCLIntelNumSimdWorkItemsAttr *A =
FD->getAttr<SYCLIntelNumSimdWorkItemsAttr>()) {
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("num_simd_work_items",
llvm::MDNode::get(Context, AttrMDArgs));
}
Expand Down
43 changes: 4 additions & 39 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2979,31 +2979,6 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
}

// Handles intel_reqd_sub_group_size.
void Sema::addIntelReqdSubGroupSizeAttr(Decl *D,
const AttributeCommonInfo &Attr,
Expr *E) {
if (!E)
return;

if (!E->isInstantiationDependent()) {
Optional<llvm::APSInt> ArgVal = E->getIntegerConstantExpr(getASTContext());
if (!ArgVal) {
Diag(E->getExprLoc(), diag::err_attribute_argument_type)
<< Attr.getAttrName() << AANT_ArgumentIntegerConstant
<< E->getSourceRange();
return;
}
int32_t ArgInt = ArgVal->getSExtValue();
if (ArgInt <= 0) {
Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
<< Attr.getAttrName() << /*positive*/ 0;
return;
}
}

D->addAttr(::new (Context) IntelReqdSubGroupSizeAttr(Context, Attr, E));
}

static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
if (S.LangOpts.SYCLIsHost)
return;
Expand All @@ -3013,7 +2988,7 @@ static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
if (D->getAttr<IntelReqdSubGroupSizeAttr>())
S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;

S.addIntelReqdSubGroupSizeAttr(D, AL, E);
S.addIntelSYCLSingleArgFunctionAttr<IntelReqdSubGroupSizeAttr>(D, AL, E);
}

// Handles num_simd_work_items.
Expand All @@ -3022,23 +2997,13 @@ static void handleNumSimdWorkItemsAttr(Sema &S, Decl *D,
if (D->isInvalidDecl())
return;

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

if (NumSimdWorkItems == 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_is_zero)
<< Attr << E->getSourceRange();
return;
}
Expr *E = Attr.getArgAsExpr(0);

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

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

// Handles max_global_work_dim.
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/Sema/SemaSYCL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2740,15 +2740,15 @@ void Sema::MarkDevice(void) {
KernelBody ? KernelBody->getAttr<SYCLSimdAttr>() : nullptr;
if (auto *Existing =
SYCLKernel->getAttr<IntelReqdSubGroupSizeAttr>()) {
if (getIntExprValue(Existing->getSubGroupSize(), getASTContext()) !=
getIntExprValue(Attr->getSubGroupSize(), getASTContext())) {
if (getIntExprValue(Existing->getValue(), getASTContext()) !=
getIntExprValue(Attr->getValue(), getASTContext())) {
Diag(SYCLKernel->getLocation(),
diag::err_conflicting_sycl_kernel_attributes);
Diag(Existing->getLocation(), diag::note_conflicting_attribute);
Diag(Attr->getLocation(), diag::note_conflicting_attribute);
SYCLKernel->setInvalidDecl();
}
} else if (KBSimdAttr && (getIntExprValue(Attr->getSubGroupSize(),
} else if (KBSimdAttr && (getIntExprValue(Attr->getValue(),
getASTContext()) != 1)) {
reportConflictingAttrs(*this, KernelBody, KBSimdAttr, Attr);
} else {
Expand Down
21 changes: 14 additions & 7 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -541,15 +541,16 @@ static void instantiateSYCLIntelPipeIOAttr(
S.addSYCLIntelPipeIOAttr(New, *Attr, Result.getAs<Expr>());
}

static void instantiateIntelReqdSubGroupSizeAttr(
template <typename AttrName>
static void instantiateIntelSYCLFunctionAttr(
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
const IntelReqdSubGroupSizeAttr *Attr, Decl *New) {
// The SubGroupSize expression is a constant expression.
const AttrName *Attr, Decl *New) {
EnterExpressionEvaluationContext Unevaluated(
S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
ExprResult Result = S.SubstExpr(Attr->getSubGroupSize(), TemplateArgs);
ExprResult Result = S.SubstExpr(Attr->getValue(), TemplateArgs);
if (!Result.isInvalid())
S.addIntelReqdSubGroupSizeAttr(New, *Attr, Result.getAs<Expr>());
S.addIntelSYCLSingleArgFunctionAttr<AttrName>(New, *Attr,
Result.getAs<Expr>());
}

void Sema::InstantiateAttrsForDecl(
Expand Down Expand Up @@ -697,8 +698,14 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
}
if (const auto *IntelReqdSubGroupSize =
dyn_cast<IntelReqdSubGroupSizeAttr>(TmplAttr)) {
instantiateIntelReqdSubGroupSizeAttr(*this, TemplateArgs,
IntelReqdSubGroupSize, New);
instantiateIntelSYCLFunctionAttr<IntelReqdSubGroupSizeAttr>(
*this, TemplateArgs, IntelReqdSubGroupSize, New);
continue;
}
if (const auto *SYCLIntelNumSimdWorkItems =
dyn_cast<SYCLIntelNumSimdWorkItemsAttr>(TmplAttr)) {
instantiateIntelSYCLFunctionAttr<SYCLIntelNumSimdWorkItemsAttr>(
*this, TemplateArgs, SYCLIntelNumSimdWorkItems, New);
continue;
}
// Existing DLL attribute on the instantiation takes precedence.
Expand Down
11 changes: 10 additions & 1 deletion clang/test/CodeGenSYCL/num-simd-work-items.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ class Foo {
[[intelfpga::num_simd_work_items(1)]] void operator()() const {}
};

template <int SIZE>
class Functor {
public:
[[intelfpga::num_simd_work_items(SIZE)]] void operator()() const {}
};

template <typename name, typename Func>
__attribute__((sycl_kernel)) void kernel(const Func &kernelFunc) {
kernelFunc();
Expand All @@ -17,10 +23,13 @@ void bar() {
kernel<class kernel_name2>(
[]() [[intelfpga::num_simd_work_items(42)]] {});

Functor<2> f;
kernel<class kernel_name3>(f);
}

// CHECK: define spir_kernel void @{{.*}}kernel_name1() {{.*}} !num_simd_work_items ![[NUM1:[0-9]+]]
// CHECK: define spir_kernel void @{{.*}}kernel_name2() {{.*}} !num_simd_work_items ![[NUM42:[0-9]+]]
// CHECK: define spir_kernel void @{{.*}}kernel_name3() {{.*}} !num_simd_work_items ![[NUM2:[0-9]+]]
// CHECK: ![[NUM1]] = !{i32 1}
// CHECK: ![[NUM42]] = !{i32 42}

// CHECK: ![[NUM2]] = !{i32 2}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// RUN: %clang_cc1 %s -fsycl -fsycl-is-device -triple spir64 -fsyntax-only -Wno-sycl-2017-compat -DTRIGGER_ERROR -verify
// RUN: %clang_cc1 %s -fsycl -fsycl-is-device -triple spir64 -fsyntax-only -Wno-sycl-2017-compat -ast-dump | FileCheck %s
// RUN: %clang_cc1 -fsycl -fsycl-is-host -fsyntax-only -Wno-sycl-2017-compat -verify %s

#ifndef __SYCL_DEVICE_ONLY__
struct FuncObj {
Expand All @@ -20,7 +19,6 @@ void foo() {
}

#else // __SYCL_DEVICE_ONLY__

[[intelfpga::num_simd_work_items(2)]] void func_do_not_ignore() {}

struct FuncObj {
Expand All @@ -34,28 +32,31 @@ __attribute__((sycl_kernel)) void kernel(const Func &kernelFunc) {

int main() {
// CHECK-LABEL: FunctionDecl {{.*}}test_kernel1
// CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}} 42
// CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}}
// CHECK-NEXT: IntegerLiteral{{.*}}42{{$}}
kernel<class test_kernel1>(
FuncObj());

// CHECK-LABEL: FunctionDecl {{.*}}test_kernel2
// CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}} 8
// CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}}
// CHECK-NEXT: IntegerLiteral{{.*}}8{{$}}
kernel<class test_kernel2>(
[]() [[intelfpga::num_simd_work_items(8)]] {});

// CHECK-LABEL: FunctionDecl {{.*}}test_kernel3
// CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}} 2
// CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}}
// CHECK-NEXT: IntegerLiteral{{.*}}2{{$}}
kernel<class test_kernel3>(
[]() { func_do_not_ignore(); });

#ifdef TRIGGER_ERROR
[[intelfpga::num_simd_work_items(0)]] int Var = 0; // expected-error{{'num_simd_work_items' attribute only applies to functions}}

kernel<class test_kernel4>(
[]() [[intelfpga::num_simd_work_items(0)]] {}); // expected-error{{'num_simd_work_items' attribute must be greater than 0}}
[]() [[intelfpga::num_simd_work_items(0)]]{}); // expected-error{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}}

kernel<class test_kernel5>(
[]() [[intelfpga::num_simd_work_items(-42)]] {}); // expected-error{{'num_simd_work_items' attribute requires a non-negative integral compile time constant expression}}
[]() [[intelfpga::num_simd_work_items(-42)]]{}); // expected-error{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}}

kernel<class test_kernel6>(
[]() [[intelfpga::num_simd_work_items(1), intelfpga::num_simd_work_items(2)]] {}); // expected-warning{{attribute 'num_simd_work_items' is already applied with different parameters}}
Expand Down
8 changes: 8 additions & 0 deletions clang/test/SemaSYCL/num_simd_work_items_host.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// RUN: %clang_cc1 -fsycl -fsycl-is-host -fsyntax-only -Wno-sycl-2017-compat -verify %s
// expected-no-diagnostics

[[intelfpga::num_simd_work_items(2)]] void func_do_not_ignore() {}

struct FuncObj {
[[intelfpga::num_simd_work_items(42)]] void operator()() const {}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// RUN: %clang_cc1 -fsycl -fsycl-is-device -fsyntax-only -ast-dump -verify -pedantic %s | FileCheck %s

// Test that checkes template parameter support for 'num_simd_work_items' attribute on sycl device.

template <int SIZE>
class KernelFunctor {
public:
// expected-error@+1{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}}
[[intelfpga::num_simd_work_items(SIZE)]] void operator()() {}
};

int main() {
//expected-note@+1{{in instantiation of template class 'KernelFunctor<-1>' requested here}}
KernelFunctor<-1>();
// no error expected
KernelFunctor<10>();
}

// CHECK: ClassTemplateDecl {{.*}} {{.*}} KernelFunctor
// CHECK: ClassTemplateSpecializationDecl {{.*}} {{.*}} class KernelFunctor definition
// CHECK: CXXRecordDecl {{.*}} {{.*}} implicit class KernelFunctor
// CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}}
// CHECK: SubstNonTypeTemplateParmExpr {{.*}}
// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}}
// CHECK-NEXT: IntegerLiteral{{.*}}10{{$}}