Skip to content

[SYCL][FPGA] Enable template parameter support for memory attributes #1113

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 2 commits into from
Feb 11, 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
85 changes: 85 additions & 0 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,65 @@ static void instantiateDependentAMDGPUWavesPerEUAttr(
S.addAMDGPUWavesPerEUAttr(New, Attr, MinExpr, MaxExpr);
}

static void instantiateIntelFPGABankWidthAttr(
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
const IntelFPGABankWidthAttr *Attr, Decl *New) {
EnterExpressionEvaluationContext Unevaluated(
S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
ExprResult Result = S.SubstExpr(Attr->getValue(), TemplateArgs);
if (!Result.isInvalid())
return S.AddOneConstantPowerTwoValueAttr<IntelFPGABankWidthAttr>(
New, *Attr, Result.getAs<Expr>());
}

static void instantiateIntelFPGANumBanksAttr(
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
const IntelFPGANumBanksAttr *Attr, Decl *New) {
EnterExpressionEvaluationContext Unevaluated(
S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
ExprResult Result = S.SubstExpr(Attr->getValue(), TemplateArgs);
if (!Result.isInvalid())
return S.AddOneConstantPowerTwoValueAttr<IntelFPGANumBanksAttr>(
New, *Attr, Result.getAs<Expr>());
}

static void instantiateIntelFPGAPrivateCopiesAttr(
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
const IntelFPGAPrivateCopiesAttr *Attr, Decl *New) {
EnterExpressionEvaluationContext Unevaluated(
S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
ExprResult Result = S.SubstExpr(Attr->getValue(), TemplateArgs);
if (!Result.isInvalid())
return S.AddOneConstantValueAttr<IntelFPGAPrivateCopiesAttr>(
New, *Attr, Result.getAs<Expr>());
}

static void instantiateIntelFPGAMaxReplicatesAttr(
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
const IntelFPGAMaxReplicatesAttr *Attr, Decl *New) {
EnterExpressionEvaluationContext Unevaluated(
S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
ExprResult Result = S.SubstExpr(Attr->getValue(), TemplateArgs);
if (!Result.isInvalid())
return S.AddOneConstantValueAttr<IntelFPGAMaxReplicatesAttr>(
New, *Attr, Result.getAs<Expr>());
}

static void instantiateIntelFPGABankBitsAttr(
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
const IntelFPGABankBitsAttr *Attr, Decl *New) {
EnterExpressionEvaluationContext Unevaluated(
S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
SmallVector<Expr *, 8> Args;
for (auto I : Attr->args()) {
ExprResult Result = S.SubstExpr(I, TemplateArgs);
if (Result.isInvalid())
return;
Args.push_back(Result.getAs<Expr>());
}
S.AddIntelFPGABankBitsAttr(New, *Attr, Args.data(), Args.size());
}

void Sema::InstantiateAttrsForDecl(
const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl,
Decl *New, LateInstantiatedAttrVec *LateAttrs,
Expand Down Expand Up @@ -614,6 +673,32 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
*AMDGPUFlatWorkGroupSize, New);
}

if (const auto *IntelFPGABankWidth =
dyn_cast<IntelFPGABankWidthAttr>(TmplAttr)) {
instantiateIntelFPGABankWidthAttr(*this, TemplateArgs, IntelFPGABankWidth,
New);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we add 'continue' instruction here?

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, yes, we can.

if (const auto *IntelFPGANumBanks =
dyn_cast<IntelFPGANumBanksAttr>(TmplAttr)) {
instantiateIntelFPGANumBanksAttr(*this, TemplateArgs, IntelFPGANumBanks,
New);
}
if (const auto *IntelFPGAPrivateCopies =
dyn_cast<IntelFPGAPrivateCopiesAttr>(TmplAttr)) {
instantiateIntelFPGAPrivateCopiesAttr(*this, TemplateArgs,
IntelFPGAPrivateCopies, New);
}
if (const auto *IntelFPGAMaxReplicates =
dyn_cast<IntelFPGAMaxReplicatesAttr>(TmplAttr)) {
instantiateIntelFPGAMaxReplicatesAttr(*this, TemplateArgs,
IntelFPGAMaxReplicates, New);
}
if (const auto *IntelFPGABankBits =
dyn_cast<IntelFPGABankBitsAttr>(TmplAttr)) {
instantiateIntelFPGABankBitsAttr(*this, TemplateArgs, IntelFPGABankBits,
New);
}

// Existing DLL attribute on the instantiation takes precedence.
if (TmplAttr->getKind() == attr::DLLExport ||
TmplAttr->getKind() == attr::DLLImport) {
Expand Down
50 changes: 48 additions & 2 deletions clang/test/CodeGenSYCL/intel-fpga-local.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@
// CHECK-DEVICE: [[ANN_bankbits_bankwidth:@.str.[0-9]*]] = {{.*}}{memory:DEFAULT}{sizeinfo:4,10,2}{bankwidth:16}{numbanks:2}{bank_bits:0}
// CHECK-DEVICE: [[ANN_memory_blockram:@.str.[0-9]*]] = {{.*}}{memory:BLOCK_RAM}{sizeinfo:4}
// CHECK-DEVICE: [[ANN_memory_mlab:@.str.[0-9]*]] = {{.*}}{memory:MLAB}{sizeinfo:4}
// CHECK-DEVICE: [[ANN_private_copies_4:@.str.[0-9]*]] = {{.*}}{memory:DEFAULT}{sizeinfo:4}{private_copies:4}
// CHECK-DEVICE: [[ANN_max_replicates_4:@.str.[0-9]*]] = {{.*}}{max_replicates:4}

// CHECK-BOTH: @llvm.global.annotations
// CHECK-DEVICE-SAME: { i8* addrspacecast (i8 addrspace(1)* bitcast (i32 addrspace(1)* @_ZZ15attrs_on_staticvE15static_numbanks to i8 addrspace(1)*) to i8*)
// CHECK-DEVICE-SAME: [[ANN_numbanks_4]]{{.*}}i32 36
// CHECK-DEVICE-SAME: [[ANN_numbanks_4]]{{.*}}i32 38
// CHECK-DEVICE-SAME: { i8* addrspacecast (i8 addrspace(1)* bitcast (i32 addrspace(1)* @_ZZ15attrs_on_staticvE15static_annotate to i8 addrspace(1)*) to i8*)
// CHECK-HOST-SAME: { i8* bitcast (i32* @_ZZ15attrs_on_staticvE15static_annotate to i8*)
// CHECK-BOTH-SAME: [[ANN_annotate]]{{.*}}i32 40
// CHECK-BOTH-SAME: [[ANN_annotate]]{{.*}}i32 42

// CHECK-HOST-NOT: llvm.var.annotation
// CHECK-HOST-NOT: llvm.ptr.annotation
Expand Down Expand Up @@ -175,6 +177,49 @@ void attrs_on_struct() {
// CHECK-HOST-NOT: llvm.var.annotation
// CHECK-HOST-NOT: llvm.ptr.annotation

template <int A, int B>
void attrs_with_template_param() {
// CHECK-DEVICE: %[[TEMPL_NUMBANKS:numbanks[0-9]+]] = bitcast{{.*}}%numbanks
// CHECK-DEVICE: @llvm.var.annotation{{.*}}%[[TEMPL_NUMBANKS]],{{.*}}[[ANN_numbanks_4]]
int numbanks [[intelfpga::numbanks(A)]];
// CHECK-DEVICE: %[[TEMPL_BANKWIDTH:bankwidth[a-z0-9]+]] = bitcast{{.*}}%bankwidth
// CHECK-DEVICE: llvm.var.annotation{{.*}}%[[TEMPL_BANKWIDTH]],{{.*}}[[ANN_bankwidth_4]]
int bankwidth [[intelfpga::bankwidth(A)]];
// CHECK-DEVICE: %[[TEMPL_PRIV_COPIES:priv_copies[0-9]+]] = bitcast{{.*}}%priv_copies
// CHECK-DEVICE: llvm.var.annotation{{.*}}%[[TEMPL_PRIV_COPIES]],{{.*}}[[ANN_private_copies_4]]
int priv_copies [[intelfpga::private_copies(A)]];
// CHECK-DEVICE: %[[TEMPL_MAXREPL:max_repl[0-9]+]] = bitcast{{.*}}%max_repl
// CHECK-DEVICE: llvm.var.annotation{{.*}}%[[TEMPL_MAXREPL]],{{.*}}[[ANN_max_replicates_4]]
int max_repl [[intelfpga::max_replicates(A)]];
// CHECK-DEVICE: %[[TEMPL_BANKBITS:bankbits[0-9]+]] = bitcast{{.*}}%bankbits
// CHECK-DEVICE: @llvm.var.annotation{{.*}}%[[TEMPL_BANKBITS]],{{.*}}[[ANN_bankbits_4_5]]
int bankbits [[intelfpga::bank_bits(A, B)]];

struct templ_on_struct_fields {
int numbanks [[intelfpga::numbanks(A)]] ;
int bankwidth [[intelfpga::bankwidth(A)]];
int privatecopies [[intelfpga::private_copies(A)]];
int maxreplicates [[intelfpga::max_replicates(A)]];
int bankbits [[intelfpga::bank_bits(A, B)]];
} s;

// CHECK-DEVICE: %[[FIELD_NUMBANKS:.*]] = getelementptr inbounds %struct.{{.*}}.templ_on_struct_fields{{.*}}
// CHECK-DEVICE: call i32* @llvm.ptr.annotation.p0i32{{.*}}%[[FIELD_NUMBANKS]]{{.*}}[[ANN_numbanks_4]]
s.numbanks = 0;
// CHECK-DEVICE: %[[FIELD_BANKWIDTH:.*]] = getelementptr inbounds %struct.{{.*}}.templ_on_struct_fields{{.*}}
// CHECK-DEVICE: call i32* @llvm.ptr.annotation.p0i32{{.*}}%[[FIELD_BANKWIDTH]]{{.*}}[[ANN_bankwidth_4]]
s.bankwidth = 0;
// CHECK-DEVICE: %[[FIELD_PRIV_COPIES:.*]] = getelementptr inbounds %struct.{{.*}}.templ_on_struct_fields{{.*}}
// CHECK-DEVICE: call i32* @llvm.ptr.annotation.p0i32{{.*}}%[[FIELD_PRIV_COPIES]]{{.*}}[[ANN_private_copies_4]]
s.privatecopies = 0;
// CHECK-DEVICE: %[[FIELD_MAX_REPLICATES:.*]] = getelementptr inbounds %struct.{{.*}}.templ_on_struct_fields{{.*}}
// CHECK-DEVICE: call i32* @llvm.ptr.annotation.p0i32{{.*}}%[[FIELD_MAX_REPLICATES]]{{.*}}[[ANN_max_replicates_4]]
s.maxreplicates = 0;
// CHECK-DEVICE: %[[FIELD_BANKBITS:.*]] = getelementptr inbounds %struct.{{.*}}.templ_on_struct_fields{{.*}}
// CHECK-DEVICE: call i32* @llvm.ptr.annotation.p0i32{{.*}}%[[FIELD_BANKBITS]]{{.*}}[[ANN_bankbits_4_5]]
s.bankbits = 0;
}

void field_addrspace_cast() {
struct state {
[[intelfpga::numbanks(2)]] int mem[8];
Expand Down Expand Up @@ -206,6 +251,7 @@ int main() {
attrs_on_var();
attrs_on_struct();
field_addrspace_cast();
attrs_with_template_param<4,5>();
});
return 0;
}
63 changes: 63 additions & 0 deletions clang/test/SemaSYCL/intel-fpga-local.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,67 @@ struct foo {
[[intelfpga::bank_bits(2,3)]] unsigned int bankbits[64];
};

//CHECK: FunctionDecl{{.*}}used check_template_parameters
template<int A, int B, int C, int D>
void check_template_parameters() {
//CHECK: VarDecl{{.*}}numbanks
//CHECK-NEXT: IntelFPGAMemoryAttr{{.*}}Implicit
//CHECK-NEXT: IntelFPGANumBanksAttr
//CHECK-NEXT: ConstantExpr
//CHECK-NEXT: SubstNonTypeTemplateParmExpr
//CHECK-NEXT: IntegerLiteral{{.*}}8{{$}}
[[intelfpga::numbanks(C)]] unsigned int numbanks;

//CHECK: VarDecl{{.*}}private_copies
//CHECK: IntelFPGAMemoryAttr{{.*}}Implicit
//CHECK: IntelFPGAPrivateCopiesAttr
//CHECK-NEXT: ConstantExpr
//CHECK-NEXT: SubstNonTypeTemplateParmExpr
//CHECK-NEXT: IntegerLiteral{{.*}}8{{$}}
[[intelfpga::private_copies(C)]] unsigned int private_copies;

//CHECK: VarDecl{{.*}}bank_bits_width
//CHECK: IntelFPGANumBanksAttr{{.*}}Implicit{{$}}
//CHECK-NEXT: IntegerLiteral{{.*}}4{{$}}
//CHECK-NEXT: IntelFPGAMemoryAttr{{.*}}Implicit
//CHECK-NEXT: IntelFPGABankBitsAttr
//CHECK-NEXT: ConstantExpr
//CHECK-NEXT: SubstNonTypeTemplateParmExpr
//CHECK-NEXT: IntegerLiteral{{.*}}2{{$}}
//CHECK-NEXT: ConstantExpr
//CHECK-NEXT: IntegerLiteral{{.*}}3{{$}}
//CHECK: IntelFPGABankWidthAttr
//CHECK-NEXT: ConstantExpr
//CHECK-NEXT: SubstNonTypeTemplateParmExpr
//CHECK-NEXT: IntegerLiteral{{.*}}8{{$}}
[[intelfpga::bank_bits(A,3), intelfpga::bankwidth(C)]]
unsigned int bank_bits_width;

//CHECK: VarDecl{{.*}}max_replicates
//CHECK: IntelFPGAMaxReplicatesAttr
//CHECK: ConstantExpr
//CHECK-NEXT: SubstNonTypeTemplateParmExpr
//CHECK: IntegerLiteral{{.*}}2{{$}}
[[intelfpga::max_replicates(A)]]
unsigned int max_replicates;

//expected-error@+1{{'numbanks' attribute takes one argument}}
[[intelfpga::numbanks(A,B)]]
int numbanks_negative;

//expected-error@+1{{'max_replicates' attribute requires integer constant between 1 and 1048576}}
[[intelfpga::max_replicates(D)]]
[[intelfpga::max_replicates(C)]]
//expected-warning@-1{{attribute 'max_replicates' is already applied}}
unsigned int max_replicates_duplicate;

//expected-error@+3{{'max_replicates' and 'register' attributes are not compatible}}
[[intelfpga::register]]
//expected-note@-1 {{conflicting attribute is here}}
[[intelfpga::max_replicates(C)]]
unsigned int maxrepl_reg;
}

template <typename name, typename Func>
__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) {
kernelFunc();
Expand All @@ -583,6 +644,8 @@ int main() {
check_ast();
diagnostics();
check_gnu_style();
check_template_parameters<2, 4, 8, -1>();
//expected-note@-1 +{{in instantiation of function template specialization}}
});
return 0;
}