Skip to content

Commit fbffaab

Browse files
vmaksimovladimirlaz
authored andcommitted
[SYCL] Enable FPGA memory attributes
This patch introduces the following FPGA memory attributes: * register * memory * numbanks * bankwidth Signed-off-by: Vladimir Lazarev <[email protected]> Signed-off-by: Viktoria Maksimova <[email protected]>
1 parent 0738099 commit fbffaab

13 files changed

+733
-0
lines changed

clang/include/clang/Basic/Attr.td

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

1390+
def IntelFPGAConstVar : SubsetSubject<Var,
1391+
[{S->getKind() != Decl::ImplicitParam &&
1392+
S->getKind() != Decl::ParmVar &&
1393+
S->getKind() != Decl::NonTypeTemplateParm &&
1394+
(S->getType().isConstQualified() ||
1395+
S->getType().getAddressSpace() ==
1396+
LangAS::opencl_constant)}],
1397+
"constant variables">;
1398+
1399+
def IntelFPGALocalStaticSlaveMemVar : SubsetSubject<Var,
1400+
[{S->getKind() != Decl::ImplicitParam &&
1401+
S->getKind() != Decl::NonTypeTemplateParm &&
1402+
(S->getStorageClass() == SC_Static ||
1403+
S->hasLocalStorage())}],
1404+
"local variables, static variables, slave memory arguments">;
1405+
1406+
def IntelFPGALocalOrStaticVar : SubsetSubject<Var,
1407+
[{S->getKind() != Decl::ImplicitParam &&
1408+
S->getKind() != Decl::ParmVar &&
1409+
S->getKind() != Decl::NonTypeTemplateParm &&
1410+
(S->getStorageClass() == SC_Static ||
1411+
S->hasLocalStorage())}],
1412+
"local variables, static variables">;
1413+
1414+
def IntelFPGAMemory : Attr {
1415+
let Spellings = [GNU<"memory">, CXX11<"intelfpga", "memory">];
1416+
let Args = [EnumArgument<"Kind", "MemoryKind",
1417+
["MLAB", "BLOCK_RAM", ""],
1418+
["MLAB", "BlockRAM", "Default"], 1>];
1419+
let AdditionalMembers = [{
1420+
static void generateValidStrings(SmallString<256> &Str) {
1421+
auto Last = BlockRAM;
1422+
for (int I = 0; I <= Last; ++I) {
1423+
Str += ConvertMemoryKindToStr(static_cast<MemoryKind>(I));
1424+
if (I != Last) Str += " ";
1425+
}
1426+
}
1427+
}];
1428+
let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar,
1429+
Field], ErrorDiag>;
1430+
let LangOpts = [SYCL];
1431+
let Documentation = [IntelFPGAMemoryAttrDocs];
1432+
}
1433+
1434+
def IntelFPGARegister : Attr {
1435+
let Spellings = [GNU<"register">, CXX11<"intelfpga", "register">];
1436+
let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalOrStaticVar,
1437+
Field], ErrorDiag>;
1438+
let LangOpts = [SYCL];
1439+
let Documentation = [IntelFPGARegisterAttrDocs];
1440+
}
1441+
1442+
// One integral argument.
1443+
def IntelFPGABankWidth : Attr {
1444+
let Spellings = [GNU<"bankwidth">, CXX11<"intelfpga","bankwidth">];
1445+
let Args = [ExprArgument<"Value">];
1446+
let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar,
1447+
Field], ErrorDiag>;
1448+
let LangOpts = [SYCL];
1449+
let Documentation = [IntelFPGABankWidthAttrDocs];
1450+
let AdditionalMembers = [{
1451+
static unsigned getMinValue() {
1452+
return 1;
1453+
}
1454+
static unsigned getMaxValue() {
1455+
return 1024*1024;
1456+
}
1457+
}];
1458+
}
1459+
1460+
def IntelFPGANumBanks : Attr {
1461+
let Spellings = [GNU<"numbanks">, CXX11<"intelfpga","numbanks">];
1462+
let Args = [ExprArgument<"Value">];
1463+
let Subjects = SubjectList<[IntelFPGAConstVar, IntelFPGALocalStaticSlaveMemVar,
1464+
Field], ErrorDiag>;
1465+
let LangOpts = [SYCL];
1466+
let Documentation = [IntelFPGANumBanksAttrDocs];
1467+
let AdditionalMembers = [{
1468+
static unsigned getMinValue() {
1469+
return 1;
1470+
}
1471+
static unsigned getMaxValue() {
1472+
return 1024*1024;
1473+
}
1474+
}];
1475+
}
1476+
13901477
def Naked : InheritableAttr {
13911478
let Spellings = [GCC<"naked">, Declspec<"naked">];
13921479
let Subjects = SubjectList<[Function]>;

clang/include/clang/Basic/AttrDocs.td

+41
Original file line numberDiff line numberDiff line change
@@ -1668,6 +1668,47 @@ as ``-mlong-calls`` and ``-mno-long-calls``.
16681668
}];
16691669
}
16701670

1671+
def IntelFPGAMemoryAttrDocs : Documentation {
1672+
let Category = DocCatVariable;
1673+
let Heading = "memory (IntelFGPA)";
1674+
let Content = [{
1675+
This attribute may be attached to a variable or struct member declaration and
1676+
instructs the backend to implement the variable or struct member in memory
1677+
rather than promoting to register(s). If the optional parameter is specified
1678+
it indicates what type of memory to use.
1679+
}];
1680+
}
1681+
1682+
def IntelFPGARegisterAttrDocs : Documentation {
1683+
let Category = DocCatVariable;
1684+
let Heading = "register (IntelFGPA)";
1685+
let Content = [{
1686+
This attribute may be attached to a variable or struct member declaration and
1687+
instructs the backend to promote the variable or struct member to register(s)
1688+
if possible.
1689+
}];
1690+
}
1691+
1692+
def IntelFPGABankWidthAttrDocs : Documentation {
1693+
let Category = DocCatVariable;
1694+
let Heading = "bankwidth (IntelFGPA)";
1695+
let Content = [{
1696+
This attribute may be attached to a variable or struct member declaration and
1697+
instructs the backend to implement the variable or struct member in a memory
1698+
with banks that are N bytes wide.
1699+
}];
1700+
}
1701+
1702+
def IntelFPGANumBanksAttrDocs : Documentation {
1703+
let Category = DocCatVariable;
1704+
let Heading = "numbanks (IntelFGPA)";
1705+
let Content = [{
1706+
This attribute may be attached to a variable or struct member declaration and
1707+
instructs the backend to implement the variable or struct member in a memory
1708+
with N banks.
1709+
}];
1710+
}
1711+
16711712
def RISCVInterruptDocs : Documentation {
16721713
let Category = DocCatFunction;
16731714
let Heading = "interrupt (RISCV)";

clang/include/clang/Basic/DiagnosticSemaKinds.td

+6
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,12 @@ def warn_double_const_requires_fp64 : Warning<
123123
def err_half_const_requires_fp16 : Error<
124124
"half precision constant requires cl_khr_fp16">;
125125

126+
// Intel FPGA extensions
127+
def err_attribute_argument_not_power_of_two : Error<
128+
"%0 attribute argument must be a constant power of two greater than zero">;
129+
def err_intel_fpga_memory_arg_invalid : Error<
130+
"%0 attribute requires either no argument or one of: %1">;
131+
126132
// C99 variable-length arrays
127133
def ext_vla : Extension<"variable length arrays are a C99 feature">,
128134
InGroup<VLAExtension>;

clang/include/clang/Sema/Sema.h

+7
Original file line numberDiff line numberDiff line change
@@ -8751,6 +8751,13 @@ class Sema {
87518751
/// attribute to be added (usually because of a pragma).
87528752
void AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD, SourceLocation Loc);
87538753

8754+
template <typename AttrType>
8755+
bool checkRangedIntegralArgument(Expr *E, const AttrType *TmpAttr,
8756+
ExprResult &Result);
8757+
template <typename AttrType>
8758+
void AddOneConstantPowerTwoValueAttr(SourceRange AttrRange, Decl *D, Expr *E,
8759+
unsigned SpellingListIndex);
8760+
87548761
/// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
87558762
void AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
87568763
unsigned SpellingListIndex, bool IsPackExpansion);

clang/lib/CodeGen/CGDecl.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -1607,6 +1607,18 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
16071607
(void)DI->EmitDeclareOfAutoVariable(&D, address.getPointer(), Builder);
16081608
}
16091609

1610+
// Emit Intel FPGA attribute annotation for a local variable.
1611+
if (getLangOpts().SYCLIsDevice) {
1612+
SmallString<256> AnnotStr;
1613+
CGM.generateIntelFPGAAnnotation(&D, AnnotStr);
1614+
if (!AnnotStr.empty()) {
1615+
llvm::Value *V = address.getPointer();
1616+
EmitAnnotationCall(CGM.getIntrinsic(llvm::Intrinsic::var_annotation),
1617+
Builder.CreateBitCast(V, CGM.Int8PtrTy, V->getName()),
1618+
AnnotStr, D.getLocation());
1619+
}
1620+
}
1621+
16101622
if (D.hasAttr<AnnotateAttr>() && HaveInsertPoint())
16111623
EmitVarAnnotations(&D, address.getPointer());
16121624

clang/lib/CodeGen/CGExpr.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -3958,6 +3958,14 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
39583958
if (field->hasAttr<AnnotateAttr>())
39593959
addr = EmitFieldAnnotations(field, addr);
39603960

3961+
// Emit attribute annotation for a field.
3962+
if (getLangOpts().SYCLIsDevice) {
3963+
SmallString<256> AnnotStr;
3964+
CGM.generateIntelFPGAAnnotation(field, AnnotStr);
3965+
if (!AnnotStr.empty())
3966+
addr = EmitIntelFPGAFieldAnnotations(field, addr, AnnotStr);
3967+
}
3968+
39613969
LValue LV = MakeAddrLValue(addr, FieldType, FieldBaseInfo, FieldTBAAInfo);
39623970
LV.getQuals().addCVRQualifiers(RecordCVR);
39633971

clang/lib/CodeGen/CodeGenFunction.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -2293,6 +2293,23 @@ Address CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D,
22932293
return Address(V, Addr.getAlignment());
22942294
}
22952295

2296+
Address CodeGenFunction::EmitIntelFPGAFieldAnnotations(const FieldDecl *D,
2297+
Address Addr,
2298+
StringRef AnnotStr) {
2299+
llvm::Value *V = Addr.getPointer();
2300+
llvm::Type *VTy = V->getType();
2301+
llvm::Function *F =
2302+
CGM.getIntrinsic(llvm::Intrinsic::ptr_annotation, CGM.Int8PtrTy);
2303+
// FIXME Always emit the cast inst so we can differentiate between
2304+
// annotation on the first field of a struct and annotation on the struct
2305+
// itself.
2306+
if (VTy != CGM.Int8PtrTy)
2307+
V = Builder.CreateBitCast(V, CGM.Int8PtrTy);
2308+
V = EmitAnnotationCall(F, V, AnnotStr, D->getLocation());
2309+
V = Builder.CreateBitCast(V, VTy);
2310+
return Address(V, Addr.getAlignment());
2311+
}
2312+
22962313
CodeGenFunction::CGCapturedStmtInfo::~CGCapturedStmtInfo() { }
22972314

22982315
CodeGenFunction::SanitizerScope::SanitizerScope(CodeGenFunction *CGF)

clang/lib/CodeGen/CodeGenFunction.h

+4
Original file line numberDiff line numberDiff line change
@@ -4009,6 +4009,10 @@ class CodeGenFunction : public CodeGenTypeCache {
40094009
/// annotation result.
40104010
Address EmitFieldAnnotations(const FieldDecl *D, Address V);
40114011

4012+
/// Emit Intel FPGA field annotations for the given field and value. Returns
4013+
/// the annotation result.
4014+
Address EmitIntelFPGAFieldAnnotations(const FieldDecl *D, Address V,
4015+
StringRef AnnotStr);
40124016
//===--------------------------------------------------------------------===//
40134017
// Internal Helpers
40144018
//===--------------------------------------------------------------------===//

clang/lib/CodeGen/CodeGenModule.cpp

+64
Original file line numberDiff line numberDiff line change
@@ -3512,6 +3512,55 @@ void CodeGenModule::maybeSetTrivialComdat(const Decl &D,
35123512
GO.setComdat(TheModule.getOrInsertComdat(GO.getName()));
35133513
}
35143514

3515+
void CodeGenModule::generateIntelFPGAAnnotation(
3516+
const Decl *D, llvm::SmallString<256> &AnnotStr) {
3517+
llvm::raw_svector_ostream Out(AnnotStr);
3518+
if (D->hasAttr<IntelFPGARegisterAttr>())
3519+
Out << "{register:1}";
3520+
if (auto const *MA = D->getAttr<IntelFPGAMemoryAttr>()) {
3521+
IntelFPGAMemoryAttr::MemoryKind Kind = MA->getKind();
3522+
Out << "{memory:";
3523+
switch (Kind) {
3524+
case IntelFPGAMemoryAttr::MLAB:
3525+
case IntelFPGAMemoryAttr::BlockRAM:
3526+
Out << IntelFPGAMemoryAttr::ConvertMemoryKindToStr(Kind);
3527+
break;
3528+
case IntelFPGAMemoryAttr::Default:
3529+
Out << "DEFAULT";
3530+
break;
3531+
}
3532+
Out << '}';
3533+
}
3534+
if (const auto *BWA = D->getAttr<IntelFPGABankWidthAttr>()) {
3535+
llvm::APSInt BWAInt = BWA->getValue()->EvaluateKnownConstInt(getContext());
3536+
Out << '{' << BWA->getSpelling() << ':' << BWAInt << '}';
3537+
}
3538+
if (const auto *NBA = D->getAttr<IntelFPGANumBanksAttr>()) {
3539+
llvm::APSInt BWAInt = NBA->getValue()->EvaluateKnownConstInt(getContext());
3540+
Out << '{' << NBA->getSpelling() << ':' << BWAInt << '}';
3541+
}
3542+
}
3543+
3544+
void CodeGenModule::addGlobalIntelFPGAAnnotation(const VarDecl *VD,
3545+
llvm::GlobalValue *GV) {
3546+
SmallString<256> AnnotStr;
3547+
generateIntelFPGAAnnotation(VD, AnnotStr);
3548+
if (!AnnotStr.empty()) {
3549+
// Get the globals for file name, annotation, and the line number.
3550+
llvm::Constant *AnnoGV = EmitAnnotationString(AnnotStr),
3551+
*UnitGV = EmitAnnotationUnit(VD->getLocation()),
3552+
*LineNoCst = EmitAnnotationLineNo(VD->getLocation());
3553+
3554+
llvm::Constant *C =
3555+
llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(GV, Int8PtrTy);
3556+
// Create the ConstantStruct for the global annotation.
3557+
llvm::Constant *Fields[4] = {
3558+
C, llvm::ConstantExpr::getBitCast(AnnoGV, Int8PtrTy),
3559+
llvm::ConstantExpr::getBitCast(UnitGV, Int8PtrTy), LineNoCst};
3560+
Annotations.push_back(llvm::ConstantStruct::getAnon(Fields));
3561+
}
3562+
}
3563+
35153564
/// Pass IsTentative as true if you want to create a tentative definition.
35163565
void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
35173566
bool IsTentative) {
@@ -3638,6 +3687,21 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
36383687
if (D->hasAttr<AnnotateAttr>())
36393688
AddGlobalAnnotations(D, GV);
36403689

3690+
// Emit Intel FPGA attribute annotation for a file-scope static variable.
3691+
if (getLangOpts().SYCLIsDevice)
3692+
addGlobalIntelFPGAAnnotation(D, GV);
3693+
3694+
if (D->getType().isRestrictQualified()) {
3695+
llvm::LLVMContext &Context = getLLVMContext();
3696+
3697+
// Common metadata nodes.
3698+
llvm::NamedMDNode *GlobalsRestrict =
3699+
getModule().getOrInsertNamedMetadata("globals.restrict");
3700+
llvm::Metadata *Args[] = {llvm::ValueAsMetadata::get(GV)};
3701+
llvm::MDNode *Node = llvm::MDNode::get(Context, Args);
3702+
GlobalsRestrict->addOperand(Node);
3703+
}
3704+
36413705
// Set the llvm linkage type as appropriate.
36423706
llvm::GlobalValue::LinkageTypes Linkage =
36433707
getLLVMLinkageVarDefinition(D, GV->isConstant());

clang/lib/CodeGen/CodeGenModule.h

+4
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,10 @@ class CodeGenModule : public CodeGenTypeCache {
976976
llvm::FunctionType *FnType = nullptr, bool DontDefer = false,
977977
ForDefinition_t IsForDefinition = NotForDefinition);
978978

979+
void generateIntelFPGAAnnotation(const Decl *D,
980+
llvm::SmallString<256> &AnnotStr);
981+
void addGlobalIntelFPGAAnnotation(const VarDecl *VD, llvm::GlobalValue *GV);
982+
979983
/// Given a builtin id for a function like "__builtin_fabsf", return a
980984
/// Function* for "fabsf".
981985
llvm::Constant *getBuiltinLibFunction(const FunctionDecl *FD,

0 commit comments

Comments
 (0)