summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaStmtAttr.cpp
diff options
context:
space:
mode:
authorTyler Nowicki <tnowicki@apple.com>2014-07-30 20:54:33 +0000
committerTyler Nowicki <tnowicki@apple.com>2014-07-30 20:54:33 +0000
commit229c2a388573e4e5cb5cf5f1e29e3b55949b0297 (patch)
tree43fb822a53dce513e3a835a478894280de371869 /lib/Sema/SemaStmtAttr.cpp
parent9f12dc464fb4c0952a13a00883326910f1a0ec58 (diff)
Add a state variable to the loop hint attribute.
This patch is necessary to support constant expressions which replaces the integer value in the loop hint attribute with an expression. The integer value was also storing the pragma’s state for options like vectorize(enable/disable) and the pragma unroll and nounroll directive. The state variable is introduced to hold the state of those options/pragmas. This moves the validation of the state (keywords) from SemaStmtAttr handler to the loop hint annotation token handler. Reviewed by Aaron Ballman git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@214333 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaStmtAttr.cpp')
-rw-r--r--lib/Sema/SemaStmtAttr.cpp104
1 files changed, 46 insertions, 58 deletions
diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp
index 595aa3656e..4cb0fde11d 100644
--- a/lib/Sema/SemaStmtAttr.cpp
+++ b/lib/Sema/SemaStmtAttr.cpp
@@ -47,13 +47,11 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
SourceRange) {
IdentifierLoc *PragmaNameLoc = A.getArgAsIdent(0);
IdentifierLoc *OptionLoc = A.getArgAsIdent(1);
- IdentifierInfo *OptionInfo = OptionLoc->Ident;
- IdentifierLoc *ValueLoc = A.getArgAsIdent(2);
- IdentifierInfo *ValueInfo = ValueLoc ? ValueLoc->Ident : nullptr;
+ IdentifierLoc *StateLoc = A.getArgAsIdent(2);
Expr *ValueExpr = A.getArgAsExpr(3);
- assert(OptionInfo && "Attribute must have valid option info.");
-
+ bool PragmaUnroll = PragmaNameLoc->Ident->getName() == "unroll";
+ bool PragmaNoUnroll = PragmaNameLoc->Ident->getName() == "nounroll";
if (St->getStmtClass() != Stmt::DoStmtClass &&
St->getStmtClass() != Stmt::ForStmtClass &&
St->getStmtClass() != Stmt::CXXForRangeStmtClass &&
@@ -69,13 +67,16 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
LoopHintAttr::OptionType Option;
LoopHintAttr::Spelling Spelling;
- if (PragmaNameLoc->Ident->getName() == "unroll") {
- Option = ValueLoc ? LoopHintAttr::UnrollCount : LoopHintAttr::Unroll;
+ if (PragmaUnroll) {
+ Option = ValueExpr ? LoopHintAttr::UnrollCount : LoopHintAttr::Unroll;
Spelling = LoopHintAttr::Pragma_unroll;
- } else if (PragmaNameLoc->Ident->getName() == "nounroll") {
+ } else if (PragmaNoUnroll) {
Option = LoopHintAttr::Unroll;
Spelling = LoopHintAttr::Pragma_nounroll;
} else {
+ assert(OptionLoc && OptionLoc->Ident &&
+ "Attribute must have valid option info.");
+ IdentifierInfo *OptionInfo = OptionLoc->Ident;
Option = llvm::StringSwitch<LoopHintAttr::OptionType>(OptionInfo->getName())
.Case("vectorize", LoopHintAttr::Vectorize)
.Case("vectorize_width", LoopHintAttr::VectorizeWidth)
@@ -87,35 +88,10 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
Spelling = LoopHintAttr::Pragma_clang_loop;
}
- int ValueInt = -1;
- if (Option == LoopHintAttr::Unroll &&
- Spelling == LoopHintAttr::Pragma_unroll) {
- if (ValueInfo)
- ValueInt = (ValueInfo->isStr("disable") ? 0 : 1);
- } else if (Option == LoopHintAttr::Unroll &&
- Spelling == LoopHintAttr::Pragma_nounroll) {
- ValueInt = 0;
- } else if (Option == LoopHintAttr::Vectorize ||
- Option == LoopHintAttr::Interleave ||
- Option == LoopHintAttr::Unroll) {
- // Unrolling uses the keyword "full" rather than "enable" to indicate full
- // unrolling.
- const char *TrueKeyword =
- Option == LoopHintAttr::Unroll ? "full" : "enable";
- if (!ValueInfo) {
- S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_keyword)
- << TrueKeyword;
- return nullptr;
- }
- if (ValueInfo->isStr("disable"))
- ValueInt = 0;
- else if (ValueInfo->getName() == TrueKeyword)
- ValueInt = 1;
- else {
- S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_keyword)
- << TrueKeyword;
- return nullptr;
- }
+ int ValueInt = 1;
+ LoopHintAttr::LoopHintState State = LoopHintAttr::Default;
+ if (PragmaNoUnroll) {
+ State = LoopHintAttr::Disable;
} else if (Option == LoopHintAttr::VectorizeWidth ||
Option == LoopHintAttr::InterleaveCount ||
Option == LoopHintAttr::UnrollCount) {
@@ -124,28 +100,39 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
llvm::APSInt ValueAPS;
if (!ValueExpr || !ValueExpr->isIntegerConstantExpr(ValueAPS, S.Context) ||
(ValueInt = ValueAPS.getSExtValue()) < 1) {
- S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_value);
+ S.Diag(A.getLoc(), diag::err_pragma_loop_invalid_value);
return nullptr;
}
- } else
- llvm_unreachable("Unknown loop hint option");
+ } else if (Option == LoopHintAttr::Vectorize ||
+ Option == LoopHintAttr::Interleave ||
+ Option == LoopHintAttr::Unroll) {
+ // Default state is assumed if StateLoc is not specified, such as with
+ // '#pragma unroll'.
+ if (StateLoc && StateLoc->Ident) {
+ if (StateLoc->Ident->isStr("disable"))
+ State = LoopHintAttr::Disable;
+ else
+ State = LoopHintAttr::Enable;
+ }
+ }
- return LoopHintAttr::CreateImplicit(S.Context, Spelling, Option, ValueInt,
- A.getRange());
+ return LoopHintAttr::CreateImplicit(S.Context, Spelling, Option, State,
+ ValueInt, A.getRange());
}
-static void CheckForIncompatibleAttributes(
- Sema &S, const SmallVectorImpl<const Attr *> &Attrs) {
- // There are 3 categories of loop hints attributes: vectorize, interleave, and
- // unroll. Each comes in two variants: a boolean form and a numeric form. The
- // boolean hints selectively enables/disables the transformation for the loop
- // (for unroll, a nonzero value indicates full unrolling rather than enabling
- // the transformation). The numeric hint provides an integer hint (for
- // example, unroll count) to the transformer. The following array accumulates
- // the hints encountered while iterating through the attributes to check for
- // compatibility.
+static void
+CheckForIncompatibleAttributes(Sema &S,
+ const SmallVectorImpl<const Attr *> &Attrs) {
+ // There are 3 categories of loop hints attributes: vectorize, interleave,
+ // and unroll. Each comes in two variants: a state form and a numeric form.
+ // The state form selectively defaults/enables/disables the transformation
+ // for the loop (for unroll, default indicates full unrolling rather than
+ // enabling the transformation). The numeric form form provides an integer
+ // hint (for example, unroll count) to the transformer. The following array
+ // accumulates the hints encountered while iterating through the attributes
+ // to check for compatibility.
struct {
- const LoopHintAttr *EnableAttr;
+ const LoopHintAttr *StateAttr;
const LoopHintAttr *NumericAttr;
} HintAttrs[] = {{nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}};
@@ -179,8 +166,8 @@ static void CheckForIncompatibleAttributes(
if (Option == LoopHintAttr::Vectorize ||
Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll) {
// Enable|disable hint. For example, vectorize(enable).
- PrevAttr = CategoryState.EnableAttr;
- CategoryState.EnableAttr = LH;
+ PrevAttr = CategoryState.StateAttr;
+ CategoryState.StateAttr = LH;
} else {
// Numeric hint. For example, vectorize_width(8).
PrevAttr = CategoryState.NumericAttr;
@@ -195,14 +182,15 @@ static void CheckForIncompatibleAttributes(
<< /*Duplicate=*/true << PrevAttr->getDiagnosticName(Policy)
<< LH->getDiagnosticName(Policy);
- if (CategoryState.EnableAttr && CategoryState.NumericAttr &&
- (Category == Unroll || !CategoryState.EnableAttr->getValue())) {
+ if (CategoryState.StateAttr && CategoryState.NumericAttr &&
+ (Category == Unroll ||
+ CategoryState.StateAttr->getState() == LoopHintAttr::Disable)) {
// Disable hints are not compatible with numeric hints of the same
// category. As a special case, numeric unroll hints are also not
// compatible with "enable" form of the unroll pragma, unroll(full).
S.Diag(OptionLoc, diag::err_pragma_loop_compatibility)
<< /*Duplicate=*/false
- << CategoryState.EnableAttr->getDiagnosticName(Policy)
+ << CategoryState.StateAttr->getDiagnosticName(Policy)
<< CategoryState.NumericAttr->getDiagnosticName(Policy);
}
}