Skip to content

Commit bce10fb

Browse files
authored
[SYCL][FPGA] Refactor of [[intel::bankwidth()]] and [[intel::numbanks()]] attributes (#4513)
This patch 1. refactors two FPGA memory attributes to align with upstream: [[intel::bankwidth()]] [[intel::numbanks()]] 2. refactors the way we handle duplicate attributes and mutually exclusive attributes logic when present on a given declaration. 3. handles redeclarations or template instantiations properly. 4. adds test 5. removes generic function "AddOneConstantPowerTwoValueAttr" Signed-off-by: Soumi Manna <[email protected]>
1 parent 6e9fa89 commit bce10fb

File tree

7 files changed

+325
-89
lines changed

7 files changed

+325
-89
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2170,7 +2170,7 @@ def : MutualExclusions<[IntelFPGADoublePump, IntelFPGASinglePump,
21702170
IntelFPGARegister]>;
21712171

21722172
// One integral argument.
2173-
def IntelFPGABankWidth : Attr {
2173+
def IntelFPGABankWidth : InheritableAttr {
21742174
let Spellings = [CXX11<"intelfpga","bankwidth">,
21752175
CXX11<"intel","bankwidth">];
21762176
let Args = [ExprArgument<"Value">];
@@ -2181,7 +2181,7 @@ def IntelFPGABankWidth : Attr {
21812181
}
21822182
def : MutualExclusions<[IntelFPGARegister, IntelFPGABankWidth]>;
21832183

2184-
def IntelFPGANumBanks : Attr {
2184+
def IntelFPGANumBanks : InheritableAttr {
21852185
let Spellings = [CXX11<"intelfpga","numbanks">,
21862186
CXX11<"intel","numbanks">];
21872187
let Args = [ExprArgument<"Value">];
@@ -2260,6 +2260,7 @@ def IntelFPGABankBits : Attr {
22602260
let Documentation = [IntelFPGABankBitsDocs];
22612261
}
22622262
def : MutualExclusions<[IntelFPGARegister, IntelFPGABankBits]>;
2263+
def : MutualExclusions<[IntelFPGARegister, IntelFPGANumBanks]>;
22632264

22642265
def IntelFPGAForcePow2Depth : InheritableAttr {
22652266
let Spellings = [CXX11<"intelfpga","force_pow2_depth">,

clang/include/clang/Sema/Sema.h

Lines changed: 8 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -10406,9 +10406,6 @@ class Sema final {
1040610406
/// attribute to be added (usually because of a pragma).
1040710407
void AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD, SourceLocation Loc);
1040810408

10409-
template <typename AttrType>
10410-
void AddOneConstantPowerTwoValueAttr(Decl *D, const AttributeCommonInfo &CI,
10411-
Expr *E);
1041210409
void AddIntelFPGABankBitsAttr(Decl *D, const AttributeCommonInfo &CI,
1041310410
Expr **Exprs, unsigned Size);
1041410411
template <typename AttrType>
@@ -10472,6 +10469,14 @@ class Sema final {
1047210469
SYCLIntelMaxGlobalWorkDimAttr *
1047310470
MergeSYCLIntelMaxGlobalWorkDimAttr(Decl *D,
1047410471
const SYCLIntelMaxGlobalWorkDimAttr &A);
10472+
void AddIntelFPGABankWidthAttr(Decl *D, const AttributeCommonInfo &CI,
10473+
Expr *E);
10474+
IntelFPGABankWidthAttr *
10475+
MergeIntelFPGABankWidthAttr(Decl *D, const IntelFPGABankWidthAttr &A);
10476+
void AddIntelFPGANumBanksAttr(Decl *D, const AttributeCommonInfo &CI,
10477+
Expr *E);
10478+
IntelFPGANumBanksAttr *
10479+
MergeIntelFPGANumBanksAttr(Decl *D, const IntelFPGANumBanksAttr &A);
1047510480
/// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
1047610481
void AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
1047710482
bool IsPackExpansion);
@@ -13536,53 +13541,6 @@ void Sema::addIntelTripleArgAttr(Decl *D, const AttributeCommonInfo &CI,
1353613541
WorkGroupAttrType(Context, CI, XDimExpr, YDimExpr, ZDimExpr));
1353713542
}
1353813543

13539-
template <typename AttrType>
13540-
void Sema::AddOneConstantPowerTwoValueAttr(Decl *D,
13541-
const AttributeCommonInfo &CI,
13542-
Expr *E) {
13543-
AttrType TmpAttr(Context, CI, E);
13544-
13545-
if (!E->isValueDependent()) {
13546-
llvm::APSInt Value;
13547-
ExprResult ICE = VerifyIntegerConstantExpression(E, &Value);
13548-
if (ICE.isInvalid())
13549-
return;
13550-
if (!Value.isStrictlyPositive()) {
13551-
Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
13552-
<< CI << /*positive*/ 0;
13553-
return;
13554-
}
13555-
if (!Value.isPowerOf2()) {
13556-
Diag(CI.getLoc(), diag::err_attribute_argument_not_power_of_two)
13557-
<< &TmpAttr;
13558-
return;
13559-
}
13560-
if (IntelFPGANumBanksAttr::classof(&TmpAttr)) {
13561-
if (auto *BBA = D->getAttr<IntelFPGABankBitsAttr>()) {
13562-
unsigned NumBankBits = BBA->args_size();
13563-
if (NumBankBits != Value.ceilLogBase2()) {
13564-
Diag(TmpAttr.getLocation(), diag::err_bankbits_numbanks_conflicting);
13565-
return;
13566-
}
13567-
}
13568-
}
13569-
E = ICE.get();
13570-
}
13571-
13572-
if (!D->hasAttr<IntelFPGAMemoryAttr>())
13573-
D->addAttr(IntelFPGAMemoryAttr::CreateImplicit(
13574-
Context, IntelFPGAMemoryAttr::Default));
13575-
13576-
// We are adding a user NumBanks, drop any implicit default.
13577-
if (IntelFPGANumBanksAttr::classof(&TmpAttr)) {
13578-
if (auto *NBA = D->getAttr<IntelFPGANumBanksAttr>())
13579-
if (NBA->isImplicit())
13580-
D->dropAttr<IntelFPGANumBanksAttr>();
13581-
}
13582-
13583-
D->addAttr(::new (Context) AttrType(Context, CI, E));
13584-
}
13585-
1358613544
/// RAII object that enters a new expression evaluation context.
1358713545
class EnterExpressionEvaluationContext {
1358813546
Sema &Actions;

clang/lib/Sema/SemaDecl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2704,6 +2704,10 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
27042704
NewAttr = S.MergeSYCLIntelMaxGlobalWorkDimAttr(D, *A);
27052705
else if (const auto *BTFA = dyn_cast<BTFTagAttr>(Attr))
27062706
NewAttr = S.mergeBTFTagAttr(D, *BTFA);
2707+
else if (const auto *A = dyn_cast<IntelFPGABankWidthAttr>(Attr))
2708+
NewAttr = S.MergeIntelFPGABankWidthAttr(D, *A);
2709+
else if (const auto *A = dyn_cast<IntelFPGANumBanksAttr>(Attr))
2710+
NewAttr = S.MergeIntelFPGANumBanksAttr(D, *A);
27072711
else if (Attr->shouldInheritEvenIfAlreadyPresent() || !DeclHasAttr(D, Attr))
27082712
NewAttr = cast<InheritableAttr>(Attr->clone(S.Context));
27092713

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 167 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6384,10 +6384,6 @@ static bool checkIntelFPGARegisterAttrCompatibility(Sema &S, Decl *D,
63846384
if (!MA->isImplicit() &&
63856385
checkAttrMutualExclusion<IntelFPGAMemoryAttr>(S, D, Attr))
63866386
InCompat = true;
6387-
if (auto *NBA = D->getAttr<IntelFPGANumBanksAttr>())
6388-
if (!NBA->isImplicit() &&
6389-
checkAttrMutualExclusion<IntelFPGANumBanksAttr>(S, D, Attr))
6390-
InCompat = true;
63916387

63926388
return InCompat;
63936389
}
@@ -6404,21 +6400,178 @@ static void handleIntelFPGARegisterAttr(Sema &S, Decl *D, const ParsedAttr &A) {
64046400
handleSimpleAttribute<IntelFPGARegisterAttr>(S, D, A);
64056401
}
64066402

6407-
/// Handle the [[intelfpga::bankwidth]] and [[intelfpga::numbanks]] attributes.
6403+
/// Handle the [[intel::bankwidth]] and [[intel::numbanks]] attributes.
64086404
/// These require a single constant power of two greater than zero.
64096405
/// These are incompatible with the register attribute.
64106406
/// The numbanks and bank_bits attributes are related. If bank_bits exists
64116407
/// when handling numbanks they are checked for consistency.
6412-
template <typename AttrType>
6413-
static void handleOneConstantPowerTwoValueAttr(Sema &S, Decl *D,
6414-
const ParsedAttr &A) {
6415-
checkForDuplicateAttribute<AttrType>(S, D, A);
6416-
if (checkAttrMutualExclusion<IntelFPGARegisterAttr>(S, D, A))
6417-
return;
64186408

6409+
void Sema::AddIntelFPGABankWidthAttr(Decl *D, const AttributeCommonInfo &CI,
6410+
Expr *E) {
6411+
if (!E->isValueDependent()) {
6412+
// Validate that we have an integer constant expression and then store the
6413+
// converted constant expression into the semantic attribute so that we
6414+
// don't have to evaluate it again later.
6415+
llvm::APSInt ArgVal;
6416+
ExprResult Res = VerifyIntegerConstantExpression(E, &ArgVal);
6417+
if (Res.isInvalid())
6418+
return;
6419+
E = Res.get();
6420+
6421+
// This attribute requires a strictly positive value.
6422+
if (ArgVal <= 0) {
6423+
Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
6424+
<< CI << /*positive*/ 0;
6425+
return;
6426+
}
6427+
6428+
// This attribute requires a single constant power of two greater than zero.
6429+
if (!ArgVal.isPowerOf2()) {
6430+
Diag(E->getExprLoc(), diag::err_attribute_argument_not_power_of_two)
6431+
<< CI;
6432+
return;
6433+
}
6434+
6435+
// Check to see if there's a duplicate attribute with different values
6436+
// already applied to the declaration.
6437+
if (const auto *DeclAttr = D->getAttr<IntelFPGABankWidthAttr>()) {
6438+
// If the other attribute argument is instantiation dependent, we won't
6439+
// have converted it to a constant expression yet and thus we test
6440+
// whether this is a null pointer.
6441+
if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
6442+
if (ArgVal != DeclExpr->getResultAsAPSInt()) {
6443+
Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
6444+
Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
6445+
}
6446+
// Drop the duplicate attribute.
6447+
return;
6448+
}
6449+
}
6450+
}
6451+
6452+
// If the declaration does not have an [[intel::fpga_memory]]
6453+
// attribute, this creates one as an implicit attribute.
6454+
if (!D->hasAttr<IntelFPGAMemoryAttr>())
6455+
D->addAttr(IntelFPGAMemoryAttr::CreateImplicit(
6456+
Context, IntelFPGAMemoryAttr::Default));
6457+
6458+
D->addAttr(::new (Context) IntelFPGABankWidthAttr(Context, CI, E));
6459+
}
6460+
6461+
IntelFPGABankWidthAttr *
6462+
Sema::MergeIntelFPGABankWidthAttr(Decl *D, const IntelFPGABankWidthAttr &A) {
6463+
// Check to see if there's a duplicate attribute with different values
6464+
// already applied to the declaration.
6465+
if (const auto *DeclAttr = D->getAttr<IntelFPGABankWidthAttr>()) {
6466+
const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue());
6467+
const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue());
6468+
if (DeclExpr && MergeExpr &&
6469+
DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
6470+
Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
6471+
Diag(A.getLoc(), diag::note_previous_attribute);
6472+
return nullptr;
6473+
}
6474+
}
6475+
6476+
return ::new (Context) IntelFPGABankWidthAttr(Context, A, A.getValue());
6477+
}
6478+
6479+
static void handleIntelFPGABankWidthAttr(Sema &S, Decl *D,
6480+
const ParsedAttr &A) {
6481+
S.CheckDeprecatedSYCLAttributeSpelling(A);
6482+
6483+
S.AddIntelFPGABankWidthAttr(D, A, A.getArgAsExpr(0));
6484+
}
6485+
6486+
void Sema::AddIntelFPGANumBanksAttr(Decl *D, const AttributeCommonInfo &CI,
6487+
Expr *E) {
6488+
if (!E->isValueDependent()) {
6489+
// Validate that we have an integer constant expression and then store the
6490+
// converted constant expression into the semantic attribute so that we
6491+
// don't have to evaluate it again later.
6492+
llvm::APSInt ArgVal;
6493+
ExprResult Res = VerifyIntegerConstantExpression(E, &ArgVal);
6494+
if (Res.isInvalid())
6495+
return;
6496+
E = Res.get();
6497+
6498+
// This attribute requires a strictly positive value.
6499+
if (ArgVal <= 0) {
6500+
Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer)
6501+
<< CI << /*positive*/ 0;
6502+
return;
6503+
}
6504+
6505+
// This attribute requires a single constant power of two greater than zero.
6506+
if (!ArgVal.isPowerOf2()) {
6507+
Diag(E->getExprLoc(), diag::err_attribute_argument_not_power_of_two)
6508+
<< CI;
6509+
return;
6510+
}
6511+
6512+
// Check or add the related BankBits attribute.
6513+
if (auto *BBA = D->getAttr<IntelFPGABankBitsAttr>()) {
6514+
unsigned NumBankBits = BBA->args_size();
6515+
if (NumBankBits != ArgVal.ceilLogBase2()) {
6516+
Diag(E->getExprLoc(), diag::err_bankbits_numbanks_conflicting) << CI;
6517+
return;
6518+
}
6519+
}
6520+
6521+
// Check to see if there's a duplicate attribute with different values
6522+
// already applied to the declaration.
6523+
if (const auto *DeclAttr = D->getAttr<IntelFPGANumBanksAttr>()) {
6524+
// If the other attribute argument is instantiation dependent, we won't
6525+
// have converted it to a constant expression yet and thus we test
6526+
// whether this is a null pointer.
6527+
if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
6528+
if (ArgVal != DeclExpr->getResultAsAPSInt()) {
6529+
Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
6530+
Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
6531+
}
6532+
// Drop the duplicate attribute.
6533+
return;
6534+
}
6535+
}
6536+
}
6537+
6538+
// If the declaration does not have an [[intel::fpga_memory]]
6539+
// attribute, this creates one as an implicit attribute.
6540+
if (!D->hasAttr<IntelFPGAMemoryAttr>())
6541+
D->addAttr(IntelFPGAMemoryAttr::CreateImplicit(
6542+
Context, IntelFPGAMemoryAttr::Default));
6543+
6544+
// We are adding a user NumBanks attribute, drop any implicit default.
6545+
if (auto *NBA = D->getAttr<IntelFPGANumBanksAttr>()) {
6546+
if (NBA->isImplicit())
6547+
D->dropAttr<IntelFPGANumBanksAttr>();
6548+
}
6549+
6550+
D->addAttr(::new (Context) IntelFPGANumBanksAttr(Context, CI, E));
6551+
}
6552+
6553+
IntelFPGANumBanksAttr *
6554+
Sema::MergeIntelFPGANumBanksAttr(Decl *D, const IntelFPGANumBanksAttr &A) {
6555+
// Check to see if there's a duplicate attribute with different values
6556+
// already applied to the declaration.
6557+
if (const auto *DeclAttr = D->getAttr<IntelFPGANumBanksAttr>()) {
6558+
const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue());
6559+
const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue());
6560+
if (DeclExpr && MergeExpr &&
6561+
DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
6562+
Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
6563+
Diag(A.getLoc(), diag::note_previous_attribute);
6564+
return nullptr;
6565+
}
6566+
}
6567+
6568+
return ::new (Context) IntelFPGANumBanksAttr(Context, A, A.getValue());
6569+
}
6570+
6571+
static void handleIntelFPGANumBanksAttr(Sema &S, Decl *D, const ParsedAttr &A) {
64196572
S.CheckDeprecatedSYCLAttributeSpelling(A);
64206573

6421-
S.AddOneConstantPowerTwoValueAttr<AttrType>(D, A, A.getArgAsExpr(0));
6574+
S.AddIntelFPGANumBanksAttr(D, A, A.getArgAsExpr(0));
64226575
}
64236576

64246577
static void handleIntelFPGASimpleDualPortAttr(Sema &S, Decl *D,
@@ -10119,10 +10272,10 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
1011910272
handleIntelFPGARegisterAttr(S, D, AL);
1012010273
break;
1012110274
case ParsedAttr::AT_IntelFPGABankWidth:
10122-
handleOneConstantPowerTwoValueAttr<IntelFPGABankWidthAttr>(S, D, AL);
10275+
handleIntelFPGABankWidthAttr(S, D, AL);
1012310276
break;
1012410277
case ParsedAttr::AT_IntelFPGANumBanks:
10125-
handleOneConstantPowerTwoValueAttr<IntelFPGANumBanksAttr>(S, D, AL);
10278+
handleIntelFPGANumBanksAttr(S, D, AL);
1012610279
break;
1012710280
case ParsedAttr::AT_IntelFPGAPrivateCopies:
1012810281
handleIntelFPGAPrivateCopiesAttr(S, D, AL);

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -593,8 +593,7 @@ static void instantiateIntelFPGABankWidthAttr(
593593
S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
594594
ExprResult Result = S.SubstExpr(Attr->getValue(), TemplateArgs);
595595
if (!Result.isInvalid())
596-
S.AddOneConstantPowerTwoValueAttr<IntelFPGABankWidthAttr>(
597-
New, *Attr, Result.getAs<Expr>());
596+
S.AddIntelFPGABankWidthAttr(New, *Attr, Result.getAs<Expr>());
598597
}
599598

600599
static void instantiateIntelFPGANumBanksAttr(
@@ -604,8 +603,7 @@ static void instantiateIntelFPGANumBanksAttr(
604603
S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
605604
ExprResult Result = S.SubstExpr(Attr->getValue(), TemplateArgs);
606605
if (!Result.isInvalid())
607-
S.AddOneConstantPowerTwoValueAttr<IntelFPGANumBanksAttr>(
608-
New, *Attr, Result.getAs<Expr>());
606+
S.AddIntelFPGANumBanksAttr(New, *Attr, Result.getAs<Expr>());
609607
}
610608

611609
static void instantiateIntelFPGABankBitsAttr(

0 commit comments

Comments
 (0)