Skip to content

Commit ec31745

Browse files
committed
[SYCL] Add Intel FPGA force_pow2_depth attribute
This attribute provides explicit control over the geometry of memory blocks used in a given memory system. Signed-off-by: Mikhail Lychkov <[email protected]>
1 parent fc03fda commit ec31745

File tree

7 files changed

+211
-9
lines changed

7 files changed

+211
-9
lines changed

clang/include/clang/Basic/Attr.td

+17
Original file line numberDiff line numberDiff line change
@@ -1850,6 +1850,23 @@ def IntelFPGABankBits : Attr {
18501850
}];
18511851
}
18521852

1853+
def IntelFPGAForcePow2Depth : Attr {
1854+
let Spellings = [CXX11<"intelfpga","force_pow2_depth">];
1855+
let Args = [ExprArgument<"Value">];
1856+
let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar,
1857+
Field], ErrorDiag>;
1858+
let LangOpts = [SYCLIsDevice, SYCLIsHost];
1859+
let Documentation = [IntelFPGAForcePow2DepthAttrDocs];
1860+
let AdditionalMembers = [{
1861+
static unsigned getMinValue() {
1862+
return 0;
1863+
}
1864+
static unsigned getMaxValue() {
1865+
return 1;
1866+
}
1867+
}];
1868+
}
1869+
18531870
def Naked : InheritableAttr {
18541871
let Spellings = [GCC<"naked">, Declspec<"naked">];
18551872
let Subjects = SubjectList<[Function]>;

clang/include/clang/Basic/AttrDocs.td

+20
Original file line numberDiff line numberDiff line change
@@ -1935,6 +1935,26 @@ pointer address bits to bank on.
19351935
}];
19361936
}
19371937

1938+
def IntelFPGAForcePow2DepthAttrDocs : Documentation {
1939+
let Category = DocCatVariable;
1940+
let Heading = "force_pow2_depth (IntelFPGA)";
1941+
let Content = [{
1942+
This attribute may be attached to a variable or struct member declaration and
1943+
provides explicit control over the geometry of memory blocks used in a given
1944+
memory system.
1945+
1946+
In the presence of this attribute, the compiler:
1947+
1948+
1. Will automatically size the memory depth to the next largest power of 2 if
1949+
force_pow2_depth is set to 1, and will prefer width-stitching of RAM blocks
1950+
over depth-stitching.
1951+
1952+
2. Will not size the memory to the next largest power of 2 if force_pow2_depth
1953+
is set to 0, and will prefer depth-stitching over width-stitching if RAM usage
1954+
can be lowered.
1955+
}];
1956+
}
1957+
19381958
def SYCLIntelKernelArgsRestrictDocs : Documentation {
19391959
let Category = DocCatVariable;
19401960
let Heading = "kernel_args_restrict";

clang/lib/CodeGen/CodeGenModule.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -4062,6 +4062,11 @@ void CodeGenModule::generateIntelFPGAAnnotation(
40624062
}
40634063
if (D->hasAttr<IntelFPGASimpleDualPortAttr>())
40644064
Out << "{simple_dual_port:1}";
4065+
if (const auto *FP2D = D->getAttr<IntelFPGAForcePow2DepthAttr>()) {
4066+
llvm::APSInt FP2DInt =
4067+
FP2D->getValue()->EvaluateKnownConstInt(getContext());
4068+
Out << '{' << FP2D->getSpelling() << ':' << FP2DInt << '}';
4069+
}
40654070
}
40664071

40674072
void CodeGenModule::addGlobalIntelFPGAAnnotation(const VarDecl *VD,

clang/lib/Sema/SemaDeclAttr.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -5215,6 +5215,8 @@ static bool checkIntelFPGARegisterAttrCompatibility(Sema &S, Decl *D,
52155215
InCompat = true;
52165216
if (checkAttrMutualExclusion<IntelFPGABankBitsAttr>(S, D, Attr))
52175217
InCompat = true;
5218+
if (checkAttrMutualExclusion<IntelFPGAForcePow2DepthAttr>(S, D, Attr))
5219+
InCompat = true;
52185220

52195221
return InCompat;
52205222
}
@@ -5419,6 +5421,24 @@ static void handleIntelFPGAPrivateCopiesAttr(Sema &S, Decl *D,
54195421
D, Attr, Attr.getArgAsExpr(0));
54205422
}
54215423

5424+
static void handleIntelFPGAForcePow2DepthAttr(Sema &S, Decl *D,
5425+
const ParsedAttr &Attr) {
5426+
if (S.LangOpts.SYCLIsHost)
5427+
return;
5428+
5429+
checkForDuplicateAttribute<IntelFPGAForcePow2DepthAttr>(S, D, Attr);
5430+
5431+
if (checkAttrMutualExclusion<IntelFPGARegisterAttr>(S, D, Attr))
5432+
return;
5433+
5434+
if (!D->hasAttr<IntelFPGAMemoryAttr>())
5435+
D->addAttr(IntelFPGAMemoryAttr::CreateImplicit(
5436+
S.Context, IntelFPGAMemoryAttr::Default));
5437+
5438+
S.AddOneConstantValueAttr<IntelFPGAForcePow2DepthAttr>(D, Attr,
5439+
Attr.getArgAsExpr(0));
5440+
}
5441+
54225442
static void handleXRayLogArgsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
54235443
ParamIdx ArgCount;
54245444

@@ -8018,6 +8038,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
80188038
case ParsedAttr::AT_IntelFPGABankBits:
80198039
handleIntelFPGABankBitsAttr(S, D, AL);
80208040
break;
8041+
case ParsedAttr::AT_IntelFPGAForcePow2Depth:
8042+
handleIntelFPGAForcePow2DepthAttr(S, D, AL);
8043+
break;
80218044
case ParsedAttr::AT_SYCLIntelPipeIO:
80228045
handleSYCLIntelPipeIOAttr(S, D, AL);
80238046
break;

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,17 @@ static void instantiateIntelFPGABankBitsAttr(
555555
S.AddIntelFPGABankBitsAttr(New, *Attr, Args.data(), Args.size());
556556
}
557557

558+
static void instantiateIntelFPGAForcePow2DepthAttr(
559+
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
560+
const IntelFPGAForcePow2DepthAttr *Attr, Decl *New) {
561+
EnterExpressionEvaluationContext Unevaluated(
562+
S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
563+
ExprResult Result = S.SubstExpr(Attr->getValue(), TemplateArgs);
564+
if (!Result.isInvalid())
565+
S.AddOneConstantValueAttr<IntelFPGAForcePow2DepthAttr>(
566+
New, *Attr, Result.getAs<Expr>());
567+
}
568+
558569
static void instantiateSYCLIntelPipeIOAttr(
559570
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
560571
const SYCLIntelPipeIOAttr *Attr, Decl *New) {
@@ -699,6 +710,11 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
699710
instantiateIntelFPGABankBitsAttr(*this, TemplateArgs, IntelFPGABankBits,
700711
New);
701712
}
713+
if (const auto *IntelFPGAForcePow2Depth =
714+
dyn_cast<IntelFPGAForcePow2DepthAttr>(TmplAttr)) {
715+
instantiateIntelFPGAForcePow2DepthAttr(*this, TemplateArgs,
716+
IntelFPGAForcePow2Depth, New);
717+
}
702718
if (const auto *SYCLIntelPipeIO = dyn_cast<SYCLIntelPipeIOAttr>(TmplAttr)) {
703719
instantiateSYCLIntelPipeIOAttr(*this, TemplateArgs, SYCLIntelPipeIO, New);
704720
continue;

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

+25-5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
// CHECK-DEVICE: [[ANN_numbanks_4:@.str]] = {{.*}}{memory:DEFAULT}{sizeinfo:4}{numbanks:4}
66
// CHECK-BOTH: @_ZZ15attrs_on_staticvE15static_annotate = internal{{.*}}constant i32 30, align 4
77
// CHECK-BOTH: [[ANN_annotate:@.str[.0-9]*]] = {{.*}}foobar
8+
// CHECK-BOTH: @_ZZ15attrs_on_staticvE16static_force_p2d = internal{{.*}}constant i32 40, align 4
9+
// CHECK-DEVICE: [[ANN_force_pow2_depth_0:@.str[.0-9]*]] = {{.*}}{memory:DEFAULT}{sizeinfo:4}{force_pow2_depth:0}
810
// CHECK-DEVICE: [[ANN_register:@.str.[0-9]*]] = {{.*}}{register:1}
911
// CHECK-DEVICE: [[ANN_memory_default:@.str.[0-9]*]] = {{.*}}{memory:DEFAULT}{sizeinfo:4}
1012
// CHECK-DEVICE: [[ANN_mlab_sizeinfo_500:@.str.[0-9]*]] = {{.*}}{memory:MLAB}{sizeinfo:4,500}
@@ -22,22 +24,25 @@
2224
// CHECK-DEVICE: [[ANN_bankbits_bankwidth:@.str.[0-9]*]] = {{.*}}{memory:DEFAULT}{sizeinfo:4,10,2}{bankwidth:16}{numbanks:2}{bank_bits:0}
2325
// CHECK-DEVICE: [[ANN_memory_blockram:@.str.[0-9]*]] = {{.*}}{memory:BLOCK_RAM}{sizeinfo:4}
2426
// CHECK-DEVICE: [[ANN_memory_mlab:@.str.[0-9]*]] = {{.*}}{memory:MLAB}{sizeinfo:4}
27+
// CHECK-DEVICE: [[ANN_force_pow2_depth_1:@.str.[0-9]*]] = {{.*}}{memory:DEFAULT}{sizeinfo:4}{force_pow2_depth:1}
2528
// CHECK-DEVICE: [[ANN_private_copies_4:@.str.[0-9]*]] = {{.*}}{memory:DEFAULT}{sizeinfo:4}{private_copies:4}
2629
// CHECK-DEVICE: [[ANN_max_replicates_4:@.str.[0-9]*]] = {{.*}}{max_replicates:4}
2730

2831
// CHECK-BOTH: @llvm.global.annotations
2932
// CHECK-DEVICE-SAME: { i8* addrspacecast (i8 addrspace(1)* bitcast (i32 addrspace(1)* @_ZZ15attrs_on_staticvE15static_numbanks to i8 addrspace(1)*) to i8*)
30-
// CHECK-DEVICE-SAME: [[ANN_numbanks_4]]{{.*}} i32 39
33+
// CHECK-DEVICE-SAME: [[ANN_numbanks_4]]{{.*}} i32 43
3134
// CHECK-DEVICE-SAME: { i8* addrspacecast (i8 addrspace(1)* bitcast (i32 addrspace(1)* @_ZZ15attrs_on_staticvE15static_annotate to i8 addrspace(1)*) to i8*)
3235
// CHECK-HOST-SAME: { i8* bitcast (i32* @_ZZ15attrs_on_staticvE15static_annotate to i8*)
33-
// CHECK-BOTH-SAME: [[ANN_annotate]]{{.*}} i32 40
34-
36+
// CHECK-BOTH-SAME: [[ANN_annotate]]{{.*}} i32 44
37+
// CHECK-DEVICE-SAME: { i8* addrspacecast (i8 addrspace(1)* bitcast (i32 addrspace(1)* @_ZZ15attrs_on_staticvE16static_force_p2d to i8 addrspace(1)*) to i8*)
38+
// CHECK-DEVICE-SAME: [[ANN_force_pow2_depth_0]]{{.*}} i32 45
3539
// CHECK-HOST-NOT: llvm.var.annotation
3640
// CHECK-HOST-NOT: llvm.ptr.annotation
3741

3842
void attrs_on_static() {
3943
const static int static_numbanks [[intelfpga::numbanks(4)]] = 20;
4044
const static int static_annotate [[clang::annotate("foobar")]] = 30;
45+
const static int static_force_p2d [[intelfpga::force_pow2_depth(0)]] = 40;
4146
}
4247

4348
void attrs_on_var() {
@@ -105,6 +110,10 @@ void attrs_on_var() {
105110
// CHECK-DEVICE: %[[VAR_BANK_BITS_WIDTH1:bank_bits_width[0-9]+]] = bitcast{{.*}}%bank_bits_width
106111
// CHECK-DEVICE: @llvm.var.annotation{{.*}}%[[VAR_BANK_BITS_WIDTH1]],{{.*}}[[ANN_bankbits_bankwidth]]
107112
[[intelfpga::bank_bits(0), intelfpga::bankwidth(16)]] int bank_bits_width[10][2];
113+
// CHECK-DEVICE: %[[VAR_FP2D:[0-9]+]] = bitcast{{.*}}%force_p2d
114+
// CHECK-DEVICE: %[[VAR_FP2D1:force_p2d[0-9]+]] = bitcast{{.*}}%force_p2d
115+
// CHECK-DEVICE: llvm.var.annotation{{.*}}%[[VAR_FP2D1]],{{.*}}[[ANN_force_pow2_depth_0]]
116+
int force_p2d [[intelfpga::force_pow2_depth(0)]];
108117
}
109118

110119
void attrs_on_struct() {
@@ -123,6 +132,7 @@ void attrs_on_struct() {
123132
int maxreplicates [[intelfpga::max_replicates(2)]];
124133
int dualport [[intelfpga::simple_dual_port]];
125134
int bankbits [[intelfpga::bank_bits(4, 5)]];
135+
int force_p2d [[intelfpga::force_pow2_depth(1)]];
126136
} s;
127137

128138
// CHECK-DEVICE: %[[FIELD_NUMBANKS:.*]] = getelementptr inbounds %struct.{{.*}}.attrs_on_struct{{.*}}
@@ -167,12 +177,15 @@ void attrs_on_struct() {
167177
// CHECK-DEVICE: %[[FIELD_BANKBITS:.*]] = getelementptr inbounds %struct.{{.*}}.attrs_on_struct{{.*}}
168178
// CHECK-DEVICE: call i32* @llvm.ptr.annotation.p0i32{{.*}}%[[FIELD_BANKBITS]]{{.*}}[[ANN_bankbits_4_5]]
169179
s.bankbits = 0;
180+
// CHECK-DEVICE: %[[FIELD_FP2D:.*]] = getelementptr inbounds %struct.{{.*}}.attrs_on_struct{{.*}}
181+
// CHECK-DEVICE: call i32* @llvm.ptr.annotation.p0i32{{.*}}%[[FIELD_FP2D]]{{.*}}[[ANN_force_pow2_depth_1]]
182+
s.force_p2d = 0;
170183
}
171184

172185
// CHECK-HOST-NOT: llvm.var.annotation
173186
// CHECK-HOST-NOT: llvm.ptr.annotation
174187

175-
template <int A, int B>
188+
template <int A, int B, int C>
176189
void attrs_with_template_param() {
177190
// CHECK-DEVICE: %[[TEMPL_NUMBANKS:numbanks[0-9]+]] = bitcast{{.*}}%numbanks
178191
// CHECK-DEVICE: @llvm.var.annotation{{.*}}%[[TEMPL_NUMBANKS]],{{.*}}[[ANN_numbanks_4]]
@@ -189,13 +202,17 @@ void attrs_with_template_param() {
189202
// CHECK-DEVICE: %[[TEMPL_BANKBITS:bankbits[0-9]+]] = bitcast{{.*}}%bankbits
190203
// CHECK-DEVICE: @llvm.var.annotation{{.*}}%[[TEMPL_BANKBITS]],{{.*}}[[ANN_bankbits_4_5]]
191204
int bankbits [[intelfpga::bank_bits(A, B)]];
205+
// CHECK-DEVICE: %[[TEMPL_FP2D:force_p2d[0-9]+]] = bitcast{{.*}}%force_p2d
206+
// CHECK-DEVICE: @llvm.var.annotation{{.*}}%[[TEMPL_FP2D]]{{.*}}[[ANN_force_pow2_depth_1]]
207+
int force_p2d [[intelfpga::force_pow2_depth(C)]];
192208

193209
struct templ_on_struct_fields {
194210
int numbanks [[intelfpga::numbanks(A)]] ;
195211
int bankwidth [[intelfpga::bankwidth(A)]];
196212
int privatecopies [[intelfpga::private_copies(A)]];
197213
int maxreplicates [[intelfpga::max_replicates(A)]];
198214
int bankbits [[intelfpga::bank_bits(A, B)]];
215+
int force_p2d [[intelfpga::force_pow2_depth(C)]];
199216
} s;
200217

201218
// CHECK-DEVICE: %[[FIELD_NUMBANKS:.*]] = getelementptr inbounds %struct.{{.*}}.templ_on_struct_fields{{.*}}
@@ -213,6 +230,9 @@ void attrs_with_template_param() {
213230
// CHECK-DEVICE: %[[FIELD_BANKBITS:.*]] = getelementptr inbounds %struct.{{.*}}.templ_on_struct_fields{{.*}}
214231
// CHECK-DEVICE: call i32* @llvm.ptr.annotation.p0i32{{.*}}%[[FIELD_BANKBITS]]{{.*}}[[ANN_bankbits_4_5]]
215232
s.bankbits = 0;
233+
// CHECK-DEVICE: %[[FIELD_FP2D:.*]] = getelementptr inbounds %struct.{{.*}}.templ_on_struct_fields{{.*}}
234+
// CHECK-DEVICE: call i32* @llvm.ptr.annotation.p0i32{{.*}}%[[FIELD_FP2D]]{{.*}}[[ANN_force_pow2_depth_1]]
235+
s.force_p2d = 0;
216236
}
217237

218238
void field_addrspace_cast() {
@@ -246,7 +266,7 @@ int main() {
246266
attrs_on_var();
247267
attrs_on_struct();
248268
field_addrspace_cast();
249-
attrs_with_template_param<4,5>();
269+
attrs_with_template_param<4, 5, 1>();
250270
});
251271
return 0;
252272
}

0 commit comments

Comments
 (0)