Skip to content

Commit 7becb9d

Browse files
vmaksimobader
authored andcommitted
[SYCL][FPGA] Add Intel FPGA bank_bits attribute (#876)
This attribute forces the memory system to implement the variable or struct member in a memory with 2^(N+1) banks, with (b0, ..., bn) forming the bank-select bits. Signed-off-by: Viktoria Maksimova <[email protected]>
1 parent 61d60b6 commit 7becb9d

File tree

8 files changed

+276
-5
lines changed

8 files changed

+276
-5
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1758,6 +1758,24 @@ def SYCLFPGAPipe : TypeAttr {
17581758
let Documentation = [SYCLFPGAPipeDocs];
17591759
}
17601760

1761+
// Variadic integral arguments.
1762+
def IntelFPGABankBits : Attr {
1763+
let Spellings = [CXX11<"intelfpga", "bank_bits">];
1764+
let Args = [VariadicExprArgument<"Args">];
1765+
let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar,
1766+
Field], ErrorDiag>;
1767+
let LangOpts = [SYCLIsDevice, SYCLIsHost];
1768+
let Documentation = [IntelFPGABankBitsDocs];
1769+
let AdditionalMembers = [{
1770+
static unsigned getMinValue() {
1771+
return 0;
1772+
}
1773+
static unsigned getMaxValue() {
1774+
return 1024*1024;
1775+
}
1776+
}];
1777+
}
1778+
17611779
def Naked : InheritableAttr {
17621780
let Spellings = [GCC<"naked">, Declspec<"naked">];
17631781
let Subjects = SubjectList<[Function]>;

clang/include/clang/Basic/AttrDocs.td

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1921,6 +1921,17 @@ loads).
19211921
}];
19221922
}
19231923

1924+
def IntelFPGABankBitsDocs : Documentation {
1925+
let Category = DocCatVariable;
1926+
let Heading = "bank_bits (IntelFPGA)";
1927+
let Content = [{
1928+
This attribute may be attached to a variable or struct member declaration and
1929+
instructs the backend to implement the variable or struct member in a banked
1930+
memory with 2^(N+1) banks, where the (b0, ..., bn) bits specified determine the
1931+
pointer address bits to bank on.
1932+
}];
1933+
}
1934+
19241935
def SYCLIntelKernelArgsRestrictDocs : Documentation {
19251936
let Category = DocCatVariable;
19261937
let Heading = "kernel_args_restrict";

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ def err_loop_unroll_compatibility : Error<
139139
"incompatible loop unroll instructions: '%0' and '%1'">;
140140
def err_pipe_attribute_arg_not_allowed : Error<
141141
"'%0' mode for pipe attribute is not supported. Allowed modes: 'read_only', 'write_only'">;
142+
def err_bankbits_numbanks_conflicting : Error<
143+
"the number of bank_bits must be equal to ceil(log2(numbanks))">;
144+
def err_bankbits_non_consecutive : Error<
145+
"bank_bits must be consecutive">;
142146

143147
// C99 variable-length arrays
144148
def ext_vla : Extension<"variable length arrays are a C99 feature">,

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9252,6 +9252,8 @@ class Sema final {
92529252
template <typename AttrType>
92539253
void AddOneConstantPowerTwoValueAttr(Decl *D, const AttributeCommonInfo &CI,
92549254
Expr *E);
9255+
void AddIntelFPGABankBitsAttr(Decl *D, const AttributeCommonInfo &CI,
9256+
Expr **Exprs, unsigned Size);
92559257

92569258
/// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
92579259
void AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3962,8 +3962,20 @@ void CodeGenModule::generateIntelFPGAAnnotation(
39623962
Out << '{' << MCA->getSpelling() << ':' << MCAInt << '}';
39633963
}
39643964
if (const auto *NBA = D->getAttr<IntelFPGANumBanksAttr>()) {
3965-
llvm::APSInt BWAInt = NBA->getValue()->EvaluateKnownConstInt(getContext());
3966-
Out << '{' << NBA->getSpelling() << ':' << BWAInt << '}';
3965+
llvm::APSInt NBAInt = NBA->getValue()->EvaluateKnownConstInt(getContext());
3966+
Out << '{' << NBA->getSpelling() << ':' << NBAInt << '}';
3967+
}
3968+
if (const auto *BBA = D->getAttr<IntelFPGABankBitsAttr>()) {
3969+
Out << '{' << BBA->getSpelling() << ':';
3970+
for (IntelFPGABankBitsAttr::args_iterator I = BBA->args_begin(),
3971+
E = BBA->args_end();
3972+
I != E; ++I) {
3973+
if (I != BBA->args_begin())
3974+
Out << ',';
3975+
llvm::APSInt BBAInt = (*I)->EvaluateKnownConstInt(getContext());
3976+
Out << BBAInt;
3977+
}
3978+
Out << '}';
39673979
}
39683980
if (const auto *MRA = D->getAttr<IntelFPGAMaxReplicatesAttr>()) {
39693981
llvm::APSInt MRAInt = MRA->getValue()->EvaluateKnownConstInt(getContext());

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3809,6 +3809,15 @@ void Sema::AddOneConstantPowerTwoValueAttr(Decl *D,
38093809
<< &TmpAttr;
38103810
return;
38113811
}
3812+
if (IntelFPGANumBanksAttr::classof(&TmpAttr)) {
3813+
if (auto *BBA = D->getAttr<IntelFPGABankBitsAttr>()) {
3814+
unsigned NumBankBits = BBA->args_size();
3815+
if (NumBankBits != Value.ceilLogBase2()) {
3816+
Diag(TmpAttr.getLocation(), diag::err_bankbits_numbanks_conflicting);
3817+
return;
3818+
}
3819+
}
3820+
}
38123821
E = ICE.get();
38133822
}
38143823

@@ -5151,6 +5160,8 @@ static bool checkIntelFPGARegisterAttrCompatibility(Sema &S, Decl *D,
51515160
InCompat = true;
51525161
if (checkAttrMutualExclusion<IntelFPGAMergeAttr>(S, D, Attr))
51535162
InCompat = true;
5163+
if (checkAttrMutualExclusion<IntelFPGABankBitsAttr>(S, D, Attr))
5164+
InCompat = true;
51545165

51555166
return InCompat;
51565167
}
@@ -5255,6 +5266,92 @@ static void handleIntelFPGAMergeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
52555266
IntelFPGAMergeAttr(S.Context, AL, Results[0], Results[1]));
52565267
}
52575268

5269+
/// Handle the bank_bits attribute.
5270+
/// This attribute accepts a list of values greater than zero.
5271+
/// This is incompatible with the register attribute.
5272+
/// The numbanks and bank_bits attributes are related. If numbanks exists
5273+
/// when handling bank_bits they are checked for consistency. If numbanks
5274+
/// hasn't been added yet an implicit one is added with the correct value.
5275+
/// If the user later adds a numbanks attribute the implicit one is removed.
5276+
/// The values must be consecutive values (i.e. 3,4,5 or 2,1).
5277+
static void handleIntelFPGABankBitsAttr(Sema &S, Decl *D,
5278+
const ParsedAttr &Attr) {
5279+
checkForDuplicateAttribute<IntelFPGABankBitsAttr>(S, D, Attr);
5280+
5281+
if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
5282+
return;
5283+
5284+
if (checkAttrMutualExclusion<IntelFPGARegisterAttr>(S, D, Attr))
5285+
return;
5286+
5287+
SmallVector<Expr *, 8> Args;
5288+
for (unsigned I = 0; I < Attr.getNumArgs(); ++I) {
5289+
Args.push_back(Attr.getArgAsExpr(I));
5290+
}
5291+
5292+
S.AddIntelFPGABankBitsAttr(D, Attr, Args.data(), Args.size());
5293+
}
5294+
5295+
void Sema::AddIntelFPGABankBitsAttr(Decl *D, const AttributeCommonInfo &CI,
5296+
Expr **Exprs, unsigned Size) {
5297+
IntelFPGABankBitsAttr TmpAttr(Context, CI, Exprs, Size);
5298+
SmallVector<Expr *, 8> Args;
5299+
SmallVector<int64_t, 8> Values;
5300+
bool ListIsValueDep = false;
5301+
for (auto *E : TmpAttr.args()) {
5302+
llvm::APSInt Value(32, /*IsUnsigned=*/false);
5303+
Expr::EvalResult Result;
5304+
ListIsValueDep = ListIsValueDep || E->isValueDependent();
5305+
if (!E->isValueDependent()) {
5306+
ExprResult ICE;
5307+
if (checkRangedIntegralArgument<IntelFPGABankBitsAttr>(E, &TmpAttr, ICE))
5308+
return;
5309+
if (E->EvaluateAsInt(Result, Context))
5310+
Value = Result.Val.getInt();
5311+
E = ICE.get();
5312+
}
5313+
Args.push_back(E);
5314+
Values.push_back(Value.getExtValue());
5315+
}
5316+
5317+
// Check that the list is consecutive.
5318+
if (!ListIsValueDep && Values.size() > 1) {
5319+
bool ListIsAscending = Values[0] < Values[1];
5320+
for (int I = 0, E = Values.size() - 1; I < E; ++I) {
5321+
if (Values[I + 1] != Values[I] + (ListIsAscending ? 1 : -1)) {
5322+
Diag(CI.getLoc(), diag::err_bankbits_non_consecutive) << &TmpAttr;
5323+
return;
5324+
}
5325+
}
5326+
}
5327+
5328+
// Check or add the related numbanks attribute.
5329+
if (auto *NBA = D->getAttr<IntelFPGANumBanksAttr>()) {
5330+
Expr *E = NBA->getValue();
5331+
if (!E->isValueDependent()) {
5332+
Expr::EvalResult Result;
5333+
E->EvaluateAsInt(Result, Context);
5334+
llvm::APSInt Value = Result.Val.getInt();
5335+
if (Args.size() != Value.ceilLogBase2()) {
5336+
Diag(TmpAttr.getLoc(), diag::err_bankbits_numbanks_conflicting);
5337+
return;
5338+
}
5339+
}
5340+
} else {
5341+
llvm::APInt Num(32, (unsigned)(1 << Args.size()));
5342+
Expr *NBE =
5343+
IntegerLiteral::Create(Context, Num, Context.IntTy, SourceLocation());
5344+
D->addAttr(IntelFPGANumBanksAttr::CreateImplicit(Context, NBE));
5345+
}
5346+
5347+
if (!D->hasAttr<IntelFPGAMemoryAttr>())
5348+
D->addAttr(IntelFPGAMemoryAttr::CreateImplicit(
5349+
Context, IntelFPGAMemoryAttr::Default));
5350+
5351+
D->addAttr(::new (Context)
5352+
IntelFPGABankBitsAttr(Context, CI, Args.data(), Args.size()));
5353+
}
5354+
52585355
static void handleIntelFPGAMaxPrivateCopiesAttr(Sema &S, Decl *D,
52595356
const ParsedAttr &Attr) {
52605357

@@ -7729,6 +7826,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
77297826
case ParsedAttr::AT_IntelFPGAMerge:
77307827
handleIntelFPGAMergeAttr(S, D, AL);
77317828
break;
7829+
case ParsedAttr::AT_IntelFPGABankBits:
7830+
handleIntelFPGABankBitsAttr(S, D, AL);
7831+
break;
77327832

77337833
case ParsedAttr::AT_AnyX86NoCallerSavedRegisters:
77347834
handleSimpleAttribute<AnyX86NoCallerSavedRegistersAttr>(S, D, AL);

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

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@
1818
//CHECK: [[ANN16:@.str.[0-9]*]] = {{.*}}foobar
1919
//CHECK: [[ANN17:@.str.[0-9]*]] = {{.*}}{memory:MLAB}{sizeinfo:4,500}
2020
//CHECK: [[ANN18:@.str.[0-9]*]] = {{.*}}{memory:BLOCK_RAM}{sizeinfo:4,10,2}
21+
//CHECK: [[ANN19:@.str.[0-9]*]] = {{.*}}{memory:DEFAULT}{sizeinfo:4}{numbanks:4}{bank_bits:4,5}
22+
//CHECK: [[ANN20:@.str.[0-9]*]] = {{.*}}{memory:DEFAULT}{sizeinfo:4,10,2}{bankwidth:16}{numbanks:2}{bank_bits:0}
23+
//CHECK: [[ANN21:@.str.[0-9]*]] = {{.*}}{memory:MLAB}{sizeinfo:4}{numbanks:8}{bank_bits:5,4,3}
2124

2225
//CHECK: @llvm.global.annotations
2326
//CHECK-SAME: { i8 addrspace(1)* bitcast (i32 addrspace(1)* @_ZZ3quxiE5a_one to i8 addrspace(1)*)
24-
//CHECK-SAME: [[ANN1]]{{.*}}i32 154
27+
//CHECK-SAME: [[ANN1]]{{.*}}i32 157
2528
//CHECK-SAME: { i8 addrspace(1)* bitcast (i32 addrspace(1)* @_ZZ3quxiE5b_two to i8 addrspace(1)*)
26-
//CHECK-SAME: [[ANN16]]{{.*}}i32 158
29+
//CHECK-SAME: [[ANN16]]{{.*}}i32 161
2730

2831
void foo() {
2932
//CHECK: %[[VAR_ONE:[0-9]+]] = bitcast{{.*}}var_one
@@ -172,6 +175,29 @@ void size_info() {
172175
[[intelfpga::memory("BLOCK_RAM")]] int var_b[10][2];
173176
}
174177

178+
struct s {
179+
int a [[intelfpga::bank_bits(4, 5)]];
180+
};
181+
182+
void bankbits() {
183+
//CHECK: %[[VAR:[0-9]+]] = bitcast{{.*}}%a
184+
//CHECK: %[[VAR1:a[0-9]+]] = bitcast{{.*}}%a
185+
//CHECK: @llvm.var.annotation{{.*}}%[[VAR1]],{{.*}}[[ANN19]]
186+
[[intelfpga::bank_bits(4,5)]] int a;
187+
//CHECK: %[[VARB:[0-9]+]] = bitcast{{.*}}%b
188+
//CHECK: %[[VARB1:b[0-9]+]] = bitcast{{.*}}%b
189+
//CHECK: @llvm.var.annotation{{.*}}%[[VARB1]],{{.*}}[[ANN20]]
190+
[[intelfpga::bank_bits(0), intelfpga::bankwidth(16)]] int b[10][2];
191+
//CHECK: %[[VARC:[0-9]+]] = bitcast{{.*}}%c
192+
//CHECK: %[[VARC1:c[0-9]+]] = bitcast{{.*}}%c
193+
//CHECK: @llvm.var.annotation{{.*}}%[[VARC1]],{{.*}}[[ANN21]]
194+
[[intelfpga::bank_bits(5,4,3), intelfpga::numbanks(8), intelfpga::memory("MLAB")]] int c;
195+
struct s s2;
196+
//CHECK: %[[FIELD_A:.*]] = getelementptr inbounds %struct.{{.*}}.s{{.*}}
197+
//CHECK: call i32* @llvm.ptr.annotation.p0i32{{.*}}%[[FIELD_A]]{{.*}}[[ANN19]]
198+
s2.a = 0;
199+
}
200+
175201
void field_addrspace_cast() {
176202
struct state {
177203
[[intelfpga::numbanks(2)]] int mem[8];
@@ -204,6 +230,7 @@ int main() {
204230
baz();
205231
qux(42);
206232
size_info();
233+
bankbits();
207234
field_addrspace_cast();
208235
});
209236
return 0;

0 commit comments

Comments
 (0)