Skip to content

Commit ed4fa17

Browse files
committed
[SYCL] Enable FPGA max_concurrency memory attribute
Signed-off-by: Viktoria Maksimova <[email protected]>
1 parent e87838c commit ed4fa17

File tree

7 files changed

+176
-11
lines changed

7 files changed

+176
-11
lines changed

clang/include/clang/Basic/Attr.td

+24
Original file line numberDiff line numberDiff line change
@@ -1387,6 +1387,14 @@ def Mode : Attr {
13871387
let PragmaAttributeSupport = 0;
13881388
}
13891389

1390+
def IntelFPGALocalNonConstVar : SubsetSubject<Var,
1391+
[{S->hasLocalStorage() &&
1392+
S->getKind() != Decl::ImplicitParam &&
1393+
S->getKind() != Decl::ParmVar &&
1394+
S->getKind() != Decl::NonTypeTemplateParm &&
1395+
!S->getType().isConstQualified()}],
1396+
"local non-const variables">;
1397+
13901398
def IntelFPGAConstVar : SubsetSubject<Var,
13911399
[{S->getKind() != Decl::ImplicitParam &&
13921400
S->getKind() != Decl::ParmVar &&
@@ -1474,6 +1482,22 @@ def IntelFPGANumBanks : Attr {
14741482
}];
14751483
}
14761484

1485+
def IntelFPGAMaxConcurrency : InheritableAttr {
1486+
let Spellings = [GNU<"max_concurrency">, CXX11<"intelfpga","max_concurrency">];
1487+
let Args = [ExprArgument<"Value">];
1488+
let LangOpts = [SYCL];
1489+
let Subjects = SubjectList<[IntelFPGALocalNonConstVar, Field], ErrorDiag>;
1490+
let Documentation = [IntelFPGAMaxConcurrencyAttrDocs];
1491+
let AdditionalMembers = [{
1492+
static unsigned getMinValue() {
1493+
return 0;
1494+
}
1495+
static unsigned getMaxValue() {
1496+
return 1024*1024;
1497+
}
1498+
}];
1499+
}
1500+
14771501
def Naked : InheritableAttr {
14781502
let Spellings = [GCC<"naked">, Declspec<"naked">];
14791503
let Subjects = SubjectList<[Function]>;

clang/include/clang/Basic/AttrDocs.td

+11
Original file line numberDiff line numberDiff line change
@@ -1709,6 +1709,17 @@ with N banks.
17091709
}];
17101710
}
17111711

1712+
def IntelFPGAMaxConcurrencyAttrDocs : Documentation {
1713+
let Category = DocCatVariable;
1714+
let Heading = "max_concurrency (IntelFGPA)";
1715+
let Content = [{
1716+
This attribute may be attached to a variable or struct member declaration and
1717+
instructs the backend to replicate the memory generated for the variable or
1718+
struct member sufficiently to enable the specified number of simultaneous
1719+
threads or loop iterations.
1720+
}];
1721+
}
1722+
17121723
def RISCVInterruptDocs : Documentation {
17131724
let Category = DocCatFunction;
17141725
let Heading = "interrupt (RISCV)";

clang/include/clang/Sema/Sema.h

+3
Original file line numberDiff line numberDiff line change
@@ -8755,6 +8755,9 @@ class Sema {
87558755
bool checkRangedIntegralArgument(Expr *E, const AttrType *TmpAttr,
87568756
ExprResult &Result);
87578757
template <typename AttrType>
8758+
void AddOneConstantValueAttr(SourceRange AttrRange, Decl *D, Expr *E,
8759+
unsigned SpellingListIndex);
8760+
template <typename AttrType>
87588761
void AddOneConstantPowerTwoValueAttr(SourceRange AttrRange, Decl *D, Expr *E,
87598762
unsigned SpellingListIndex);
87608763

clang/lib/CodeGen/CodeGenModule.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -3535,6 +3535,10 @@ void CodeGenModule::generateIntelFPGAAnnotation(
35353535
llvm::APSInt BWAInt = BWA->getValue()->EvaluateKnownConstInt(getContext());
35363536
Out << '{' << BWA->getSpelling() << ':' << BWAInt << '}';
35373537
}
3538+
if (const auto *MCA = D->getAttr<IntelFPGAMaxConcurrencyAttr>()) {
3539+
llvm::APSInt MCAInt = MCA->getValue()->EvaluateKnownConstInt(getContext());
3540+
Out << '{' << MCA->getSpelling() << ':' << MCAInt << '}';
3541+
}
35383542
if (const auto *NBA = D->getAttr<IntelFPGANumBanksAttr>()) {
35393543
llvm::APSInt BWAInt = NBA->getValue()->EvaluateKnownConstInt(getContext());
35403544
Out << '{' << NBA->getSpelling() << ':' << BWAInt << '}';

clang/lib/Sema/SemaDeclAttr.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -3781,6 +3781,28 @@ bool Sema::checkRangedIntegralArgument(Expr *E, const AttrType *TmpAttr,
37813781
return false;
37823782
}
37833783

3784+
template <typename AttrType>
3785+
void Sema::AddOneConstantValueAttr(SourceRange AttrRange, Decl *D, Expr *E,
3786+
unsigned SpellingListIndex) {
3787+
AttrType TmpAttr(AttrRange, Context, E, SpellingListIndex);
3788+
3789+
if (!E->isValueDependent()) {
3790+
ExprResult ICE;
3791+
if (checkRangedIntegralArgument<AttrType>(E, &TmpAttr, ICE))
3792+
return;
3793+
E = ICE.get();
3794+
}
3795+
3796+
if (IntelFPGAMaxConcurrencyAttr::classof(&TmpAttr)) {
3797+
if (!D->hasAttr<IntelFPGAMemoryAttr>())
3798+
D->addAttr(IntelFPGAMemoryAttr::CreateImplicit(
3799+
Context, IntelFPGAMemoryAttr::Default));
3800+
}
3801+
3802+
D->addAttr(::new (Context)
3803+
AttrType(AttrRange, Context, E, SpellingListIndex));
3804+
}
3805+
37843806
template <typename AttrType>
37853807
void Sema::AddOneConstantPowerTwoValueAttr(SourceRange AttrRange, Decl *D,
37863808
Expr *E,
@@ -5037,6 +5059,8 @@ static bool checkIntelFPGARegisterAttrCompatibility(Sema &S, Decl *D,
50375059
InCompat = true;
50385060
if (checkAttrMutualExclusion<IntelFPGABankWidthAttr>(S, D, Attr))
50395061
InCompat = true;
5062+
if (checkAttrMutualExclusion<IntelFPGAMaxConcurrencyAttr>(S, D, Attr))
5063+
InCompat = true;
50405064
if (auto *NBA = D->getAttr<IntelFPGANumBanksAttr>())
50415065
if (!NBA->isImplicit() &&
50425066
checkAttrMutualExclusion<IntelFPGANumBanksAttr>(S, D, Attr))
@@ -5074,6 +5098,17 @@ static void handleOneConstantPowerTwoValueAttr(Sema &S, Decl *D,
50745098
Attr.getAttributeSpellingListIndex());
50755099
}
50765100

5101+
static void handleIntelFPGAMaxConcurrencyAttr(Sema &S, Decl *D,
5102+
const ParsedAttr &Attr) {
5103+
checkForDuplicateAttribute<IntelFPGAMaxConcurrencyAttr>(S, D, Attr);
5104+
if (checkAttrMutualExclusion<IntelFPGARegisterAttr>(S, D, Attr))
5105+
return;
5106+
5107+
S.AddOneConstantValueAttr<IntelFPGAMaxConcurrencyAttr>(
5108+
Attr.getRange(), D, Attr.getArgAsExpr(0),
5109+
Attr.getAttributeSpellingListIndex());
5110+
}
5111+
50775112
static void handleXRayLogArgsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
50785113
ParamIdx ArgCount;
50795114

@@ -7436,6 +7471,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
74367471
case ParsedAttr::AT_IntelFPGANumBanks:
74377472
handleOneConstantPowerTwoValueAttr<IntelFPGANumBanksAttr>(S, D, AL);
74387473
break;
7474+
case ParsedAttr::AT_IntelFPGAMaxConcurrency:
7475+
handleIntelFPGAMaxConcurrencyAttr(S, D, AL);
7476+
break;
74397477

74407478
case ParsedAttr::AT_AnyX86NoCallerSavedRegisters:
74417479
handleSimpleAttribute<AnyX86NoCallerSavedRegistersAttr>(S, D, AL);

clang/test/CodeGenSYCL/intel-fpga-local.cpp

+17-6
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
//CHECK: [[ANN2:@.str[\.]*[0-9]*]] = {{.*}}{register:1}
55
//CHECK: [[ANN3:@.str[\.]*[0-9]*]] = {{.*}}{memory:DEFAULT}
66
//CHECK: [[ANN4:@.str[\.]*[0-9]*]] = {{.*}}{memory:DEFAULT}{bankwidth:4}
7-
//CHECK: [[ANN5:@.str[\.]*[0-9]*]] = {{.*}}{memory:BLOCK_RAM}
8-
//CHECK: [[ANN6:@.str[\.]*[0-9]*]] = {{.*}}{memory:MLAB}
9-
//CHECK: [[ANN7:@.str[\.]*[0-9]*]] = {{.*}}{memory:DEFAULT}{bankwidth:8}
7+
//CHECK: [[ANN5:@.str[\.]*[0-9]*]] = {{.*}}{memory:DEFAULT}{max_concurrency:8}
8+
//CHECK: [[ANN6:@.str[\.]*[0-9]*]] = {{.*}}{memory:BLOCK_RAM}
9+
//CHECK: [[ANN7:@.str[\.]*[0-9]*]] = {{.*}}{memory:MLAB}
10+
//CHECK: [[ANN8:@.str[\.]*[0-9]*]] = {{.*}}{memory:DEFAULT}{bankwidth:8}
11+
//CHECK: [[ANN9:@.str[\.]*[0-9]*]] = {{.*}}{memory:DEFAULT}{max_concurrency:4}
1012

1113
void foo() {
1214
//CHECK: %[[VAR_ONE:[0-9]+]] = bitcast{{.*}}var_one
@@ -32,6 +34,7 @@ struct foo_two {
3234
int __attribute__((register)) f2;
3335
int __attribute__((__memory__)) f3;
3436
int __attribute__((__bankwidth__(4))) f4;
37+
int __attribute__((max_concurrency(8))) f5;
3538
};
3639

3740
void bar() {
@@ -52,6 +55,10 @@ void bar() {
5255
//CHECK: %[[CAST:.*]] = bitcast{{.*}}%[[FIELD4]]
5356
//CHECK: call i8* @llvm.ptr.annotation.p0i8{{.*}}%[[CAST]]{{.*}}[[ANN4]]
5457
s1.f4 = 0;
58+
//CHECK: %[[FIELD5:.*]] = getelementptr inbounds %struct.foo_two{{.*}}
59+
//CHECK: %[[CAST:.*]] = bitcast{{.*}}%[[FIELD5]]
60+
//CHECK: call i8* @llvm.ptr.annotation.p0i8{{.*}}%[[CAST]]{{.*}}[[ANN5]]
61+
s1.f5 = 0;
5562
}
5663

5764
void baz() {
@@ -69,16 +76,20 @@ void baz() {
6976
int v_three [[intelfpga::memory]];
7077
//CHECK: %[[V_FOUR:[0-9]+]] = bitcast{{.*}}v_four
7178
//CHECK: %[[V_FOUR1:v_four[0-9]+]] = bitcast{{.*}}v_four
72-
//CHECK: llvm.var.annotation{{.*}}%[[V_FOUR1]],{{.*}}[[ANN5]]
79+
//CHECK: llvm.var.annotation{{.*}}%[[V_FOUR1]],{{.*}}[[ANN6]]
7380
int v_four [[intelfpga::memory("BLOCK_RAM")]];
7481
//CHECK: %[[V_FIVE:[0-9]+]] = bitcast{{.*}}v_five
7582
//CHECK: %[[V_FIVE1:v_five[0-9]+]] = bitcast{{.*}}v_five
76-
//CHECK: llvm.var.annotation{{.*}}%[[V_FIVE1]],{{.*}}[[ANN6]]
83+
//CHECK: llvm.var.annotation{{.*}}%[[V_FIVE1]],{{.*}}[[ANN7]]
7784
int v_five [[intelfpga::memory("MLAB")]];
7885
//CHECK: %[[V_SIX:[0-9]+]] = bitcast{{.*}}v_six
7986
//CHECK: %[[V_SIX1:v_six[0-9]+]] = bitcast{{.*}}v_six
80-
//CHECK: llvm.var.annotation{{.*}}%[[V_SIX1]],{{.*}}[[ANN7]]
87+
//CHECK: llvm.var.annotation{{.*}}%[[V_SIX1]],{{.*}}[[ANN8]]
8188
int v_six [[intelfpga::bankwidth(8)]];
89+
//CHECK: %[[V_SEVEN:[0-9]+]] = bitcast{{.*}}v_seven
90+
//CHECK: %[[V_SEVEN1:v_seven[0-9]+]] = bitcast{{.*}}v_seven
91+
//CHECK: llvm.var.annotation{{.*}}%[[V_SEVEN1]],{{.*}}[[ANN9]]
92+
int v_seven [[intelfpga::max_concurrency(4)]];
8293
}
8394

8495
template <typename name, typename Func>

clang/test/SemaSYCL/intel-fpga-local.cpp

+79-5
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,22 @@ void foo1()
5353
//CHECK: IntelFPGANumBanksAttr
5454
//CHECK-NEXT: ConstantExpr
5555
//CHECK-NEXT: IntegerLiteral{{.*}}4{{$}}
56-
__attribute__((__numbanks__(4))) unsigned int v_six2[32];
56+
[[intelfpga::numbanks(4)]] unsigned int v_six2[32];
57+
58+
//CHECK: VarDecl{{.*}}v_seven
59+
//CHECK: IntelFPGAMemoryAttr{{.*}}Implicit
60+
//CHECK: IntelFPGAMaxConcurrencyAttr
61+
//CHECK-NEXT: ConstantExpr
62+
//CHECK-NEXT: IntegerLiteral{{.*}}4{{$}}
63+
__attribute__((max_concurrency(4)))
64+
unsigned int v_seven[64];
65+
66+
//CHECK: VarDecl{{.*}}v_seven2
67+
//CHECK: IntelFPGAMemoryAttr{{.*}}Implicit
68+
//CHECK: IntelFPGAMaxConcurrencyAttr
69+
//CHECK-NEXT: ConstantExpr
70+
//CHECK-NEXT: IntegerLiteral{{.*}}8{{$}}
71+
[[intelfpga::max_concurrency(8)]] unsigned int v_seven2[64];
5772

5873
int __attribute__((__register__)) A;
5974
int __attribute__((__numbanks__(4), __bankwidth__(16))) E;
@@ -77,6 +92,12 @@ void foo1()
7792
//expected-note@-2 {{conflicting attribute is here}}
7893
unsigned int reg_six[64];
7994

95+
//expected-error@+2{{attributes are not compatible}}
96+
__attribute__((__register__))
97+
__attribute__((__max_concurrency__(16)))
98+
//expected-note@-2 {{conflicting attribute is here}}
99+
unsigned int reg_six_two[64];
100+
80101
//expected-error@+2{{attributes are not compatible}}
81102
__attribute__((__register__))
82103
__attribute__((__numbanks__(8)))
@@ -117,7 +138,7 @@ void foo1()
117138
__attribute__((__bankwidth__(3)))
118139
unsigned int bw_three[64];
119140

120-
//expected-error@+1{{requires integer constant between 1 and 1048576}}
141+
//expected-error@+1{{'bankwidth' attribute requires integer constant between 1 and 1048576 inclusive}}
121142
__attribute__((__bankwidth__(-4)))
122143
unsigned int bw_four[64];
123144

@@ -131,10 +152,43 @@ void foo1()
131152
__attribute__((__bankwidth__(4,8)))
132153
unsigned int bw_six[64];
133154

134-
//expected-error@+1{{requires integer constant between 1 and 1048576}}
155+
//expected-error@+1{{'bankwidth' attribute requires integer constant between 1 and 1048576 inclusive}}
135156
__attribute__((__bankwidth__(0)))
136157
unsigned int bw_seven[64];
137158

159+
// max_concurrency
160+
//expected-error@+2{{attributes are not compatible}}
161+
__attribute__((__max_concurrency__(16)))
162+
__attribute__((__register__))
163+
//expected-note@-2 {{conflicting attribute is here}}
164+
unsigned int mc_one[64];
165+
166+
//CHECK: VarDecl{{.*}}mc_two
167+
//CHECK: IntelFPGAMaxConcurrencyAttr
168+
//CHECK-NEXT: ConstantExpr
169+
//CHECK-NEXT: IntegerLiteral{{.*}}8{{$}}
170+
//CHECK: IntelFPGAMaxConcurrencyAttr
171+
//CHECK-NEXT: ConstantExpr
172+
//CHECK-NEXT: IntegerLiteral{{.*}}16{{$}}
173+
//expected-warning@+2{{is already applied}}
174+
__attribute__((__max_concurrency__(8)))
175+
__attribute__((__max_concurrency__(16)))
176+
unsigned int mc_two[64];
177+
178+
//expected-error@+1{{'max_concurrency' attribute requires integer constant between 0 and 1048576 inclusive}}
179+
__attribute__((__max_concurrency__(-4)))
180+
unsigned int mc_four[64];
181+
182+
int i_max_concurrency = 32; // expected-note {{declared here}}
183+
//expected-error@+1{{expression is not an integral constant expression}}
184+
__attribute__((__max_concurrency__(i_max_concurrency)))
185+
//expected-note@-1{{read of non-const variable 'i_max_concurrency' is not allowed in a constant expression}}
186+
unsigned int mc_five[64];
187+
188+
//expected-error@+1{{'__max_concurrency__' attribute takes one argument}}
189+
__attribute__((__max_concurrency__(4,8)))
190+
unsigned int mc_six[64];
191+
138192
// numbanks
139193
//expected-error@+2{{attributes are not compatible}}
140194
__attribute__((__numbanks__(16)))
@@ -158,7 +212,7 @@ void foo1()
158212
__attribute__((__numbanks__(15)))
159213
unsigned int nb_three[64];
160214

161-
//expected-error@+1{{requires integer constant between 1 and 1048576}}
215+
//expected-error@+1{{attribute requires integer constant between 1 and 1048576 inclusive}}
162216
__attribute__((__numbanks__(-4)))
163217
unsigned int nb_four[64];
164218

@@ -172,11 +226,24 @@ void foo1()
172226
__attribute__((__numbanks__(4,8)))
173227
unsigned int nb_six[64];
174228

175-
//expected-error@+1{{requires integer constant between 1 and 1048576}}
229+
//expected-error@+1{{'numbanks' attribute requires integer constant between 1 and 1048576 inclusive}}
176230
__attribute__((__numbanks__(0)))
177231
unsigned int nb_seven[64];
178232
}
179233

234+
//expected-error@+1{{attribute only applies to local non-const variables and non-static data members}}
235+
__attribute__((__max_concurrency__(8)))
236+
__constant unsigned int ext_two[64] = { 1, 2, 3 };
237+
238+
void other2()
239+
{
240+
//expected-error@+1{{attribute only applies to local non-const variables and non-static data members}}
241+
__attribute__((__max_concurrency__(8))) const int ext_six[64] = { 0, 1 };
242+
}
243+
244+
//expected-error@+1{{attribute only applies to local non-const variables and non-static data members}}
245+
void other3(__attribute__((__max_concurrency__(8))) int pfoo) {}
246+
180247
struct foo {
181248
//CHECK: FieldDecl{{.*}}v_two
182249
//CHECK: IntelFPGAMemoryAttr
@@ -207,6 +274,13 @@ struct foo {
207274
//CHECK-NEXT: ConstantExpr
208275
//CHECK-NEXT: IntegerLiteral{{.*}}8{{$}}
209276
__attribute__((__numbanks__(8))) unsigned int v_six[64];
277+
278+
//CHECK: FieldDecl{{.*}}v_seven
279+
//CHECK: IntelFPGAMemoryAttr{{.*}}Implicit
280+
//CHECK: IntelFPGAMaxConcurrencyAttr
281+
//CHECK-NEXT: ConstantExpr
282+
//CHECK-NEXT: IntegerLiteral{{.*}}4{{$}}
283+
__attribute__((__max_concurrency__(4))) unsigned int v_seven[64];
210284
};
211285

212286
template <typename name, typename Func>

0 commit comments

Comments
 (0)