summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaStmtAttr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaStmtAttr.cpp')
-rw-r--r--lib/Sema/SemaStmtAttr.cpp99
1 files changed, 69 insertions, 30 deletions
diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp
index e39a65c6ce0cf..a8e54b36b29b3 100644
--- a/lib/Sema/SemaStmtAttr.cpp
+++ b/lib/Sema/SemaStmtAttr.cpp
@@ -16,7 +16,6 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Lookup.h"
-#include "clang/Sema/LoopHint.h"
#include "clang/Sema/ScopeInfo.h"
#include "llvm/ADT/StringExtras.h"
@@ -29,7 +28,7 @@ static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const ParsedAttr &A,
A.getAttributeSpellingListIndex());
if (!isa<NullStmt>(St)) {
S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_wrong_target)
- << Attr.getSpelling() << St->getLocStart();
+ << Attr.getSpelling() << St->getBeginLoc();
if (isa<SwitchCase>(St)) {
SourceLocation L = S.getLocForEndOfToken(Range.getEnd());
S.Diag(L, diag::note_fallthrough_insert_semi_fixit)
@@ -56,8 +55,7 @@ static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const ParsedAttr &A,
static Attr *handleSuppressAttr(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange Range) {
if (A.getNumArgs() < 1) {
- S.Diag(A.getLoc(), diag::err_attribute_too_few_arguments)
- << A.getName() << 1;
+ S.Diag(A.getLoc(), diag::err_attribute_too_few_arguments) << A << 1;
return nullptr;
}
@@ -87,6 +85,9 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
bool PragmaUnroll = PragmaNameLoc->Ident->getName() == "unroll";
bool PragmaNoUnroll = PragmaNameLoc->Ident->getName() == "nounroll";
+ bool PragmaUnrollAndJam = PragmaNameLoc->Ident->getName() == "unroll_and_jam";
+ bool PragmaNoUnrollAndJam =
+ PragmaNameLoc->Ident->getName() == "nounroll_and_jam";
if (St->getStmtClass() != Stmt::DoStmtClass &&
St->getStmtClass() != Stmt::ForStmtClass &&
St->getStmtClass() != Stmt::CXXForRangeStmtClass &&
@@ -95,8 +96,10 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
llvm::StringSwitch<const char *>(PragmaNameLoc->Ident->getName())
.Case("unroll", "#pragma unroll")
.Case("nounroll", "#pragma nounroll")
+ .Case("unroll_and_jam", "#pragma unroll_and_jam")
+ .Case("nounroll_and_jam", "#pragma nounroll_and_jam")
.Default("#pragma clang loop");
- S.Diag(St->getLocStart(), diag::err_pragma_loop_precedes_nonloop) << Pragma;
+ S.Diag(St->getBeginLoc(), diag::err_pragma_loop_precedes_nonloop) << Pragma;
return nullptr;
}
@@ -118,6 +121,20 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
Option = LoopHintAttr::Unroll;
State = LoopHintAttr::Enable;
}
+ } else if (PragmaNoUnrollAndJam) {
+ // #pragma nounroll_and_jam
+ Option = LoopHintAttr::UnrollAndJam;
+ State = LoopHintAttr::Disable;
+ } else if (PragmaUnrollAndJam) {
+ if (ValueExpr) {
+ // #pragma unroll_and_jam N
+ Option = LoopHintAttr::UnrollAndJamCount;
+ State = LoopHintAttr::Numeric;
+ } else {
+ // #pragma unroll_and_jam
+ Option = LoopHintAttr::UnrollAndJam;
+ State = LoopHintAttr::Enable;
+ }
} else {
// #pragma clang loop ...
assert(OptionLoc && OptionLoc->Ident &&
@@ -130,19 +147,24 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
.Case("interleave_count", LoopHintAttr::InterleaveCount)
.Case("unroll", LoopHintAttr::Unroll)
.Case("unroll_count", LoopHintAttr::UnrollCount)
+ .Case("pipeline", LoopHintAttr::PipelineDisabled)
+ .Case("pipeline_initiation_interval",
+ LoopHintAttr::PipelineInitiationInterval)
.Case("distribute", LoopHintAttr::Distribute)
.Default(LoopHintAttr::Vectorize);
if (Option == LoopHintAttr::VectorizeWidth ||
Option == LoopHintAttr::InterleaveCount ||
- Option == LoopHintAttr::UnrollCount) {
+ Option == LoopHintAttr::UnrollCount ||
+ Option == LoopHintAttr::PipelineInitiationInterval) {
assert(ValueExpr && "Attribute must have a valid value expression.");
- if (S.CheckLoopHintExpr(ValueExpr, St->getLocStart()))
+ if (S.CheckLoopHintExpr(ValueExpr, St->getBeginLoc()))
return nullptr;
State = LoopHintAttr::Numeric;
} else if (Option == LoopHintAttr::Vectorize ||
Option == LoopHintAttr::Interleave ||
Option == LoopHintAttr::Unroll ||
- Option == LoopHintAttr::Distribute) {
+ Option == LoopHintAttr::Distribute ||
+ Option == LoopHintAttr::PipelineDisabled) {
assert(StateLoc && StateLoc->Ident && "Loop hint must have an argument");
if (StateLoc->Ident->isStr("disable"))
State = LoopHintAttr::Disable;
@@ -165,21 +187,20 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
static void
CheckForIncompatibleAttributes(Sema &S,
const SmallVectorImpl<const Attr *> &Attrs) {
- // There are 4 categories of loop hints attributes: vectorize, interleave,
- // unroll and distribute. Except for distribute they come 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.
+ // There are 6 categories of loop hints attributes: vectorize, interleave,
+ // unroll, unroll_and_jam, pipeline and distribute. Except for distribute they
+ // come 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 *StateAttr;
const LoopHintAttr *NumericAttr;
- } HintAttrs[] = {{nullptr, nullptr},
- {nullptr, nullptr},
- {nullptr, nullptr},
- {nullptr, nullptr}};
+ } HintAttrs[] = {{nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr},
+ {nullptr, nullptr}, {nullptr, nullptr}, {nullptr, nullptr}};
for (const auto *I : Attrs) {
const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(I);
@@ -189,7 +210,14 @@ CheckForIncompatibleAttributes(Sema &S,
continue;
LoopHintAttr::OptionType Option = LH->getOption();
- enum { Vectorize, Interleave, Unroll, Distribute } Category;
+ enum {
+ Vectorize,
+ Interleave,
+ Unroll,
+ UnrollAndJam,
+ Distribute,
+ Pipeline
+ } Category;
switch (Option) {
case LoopHintAttr::Vectorize:
case LoopHintAttr::VectorizeWidth:
@@ -203,16 +231,27 @@ CheckForIncompatibleAttributes(Sema &S,
case LoopHintAttr::UnrollCount:
Category = Unroll;
break;
+ case LoopHintAttr::UnrollAndJam:
+ case LoopHintAttr::UnrollAndJamCount:
+ Category = UnrollAndJam;
+ break;
case LoopHintAttr::Distribute:
// Perform the check for duplicated 'distribute' hints.
Category = Distribute;
break;
+ case LoopHintAttr::PipelineDisabled:
+ case LoopHintAttr::PipelineInitiationInterval:
+ Category = Pipeline;
+ break;
};
+ assert(Category < sizeof(HintAttrs) / sizeof(HintAttrs[0]));
auto &CategoryState = HintAttrs[Category];
const LoopHintAttr *PrevAttr;
if (Option == LoopHintAttr::Vectorize ||
Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll ||
+ Option == LoopHintAttr::UnrollAndJam ||
+ Option == LoopHintAttr::PipelineDisabled ||
Option == LoopHintAttr::Distribute) {
// Enable|Disable|AssumeSafety hint. For example, vectorize(enable).
PrevAttr = CategoryState.StateAttr;
@@ -232,7 +271,7 @@ CheckForIncompatibleAttributes(Sema &S,
<< LH->getDiagnosticName(Policy);
if (CategoryState.StateAttr && CategoryState.NumericAttr &&
- (Category == Unroll ||
+ (Category == Unroll || Category == UnrollAndJam ||
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
@@ -257,8 +296,7 @@ static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A,
unsigned NumArgs = A.getNumArgs();
if (NumArgs > 1) {
- S.Diag(A.getLoc(), diag::err_attribute_too_many_arguments) << A.getName()
- << 1;
+ S.Diag(A.getLoc(), diag::err_attribute_too_many_arguments) << A << 1;
return nullptr;
}
@@ -270,7 +308,7 @@ static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A,
if (!E->isIntegerConstantExpr(ArgVal, S.Context)) {
S.Diag(A.getLoc(), diag::err_attribute_argument_type)
- << A.getName() << AANT_ArgumentIntegerConstant << E->getSourceRange();
+ << A << AANT_ArgumentIntegerConstant << E->getSourceRange();
return nullptr;
}
@@ -279,7 +317,7 @@ static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A,
if (Val <= 0) {
S.Diag(A.getRange().getBegin(),
diag::err_attribute_requires_positive_integer)
- << A.getName();
+ << A << /* positive */ 0;
return nullptr;
}
UnrollFactor = Val;
@@ -292,9 +330,10 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange Range) {
switch (A.getKind()) {
case ParsedAttr::UnknownAttribute:
- S.Diag(A.getLoc(), A.isDeclspecAttribute() ?
- diag::warn_unhandled_ms_attribute_ignored :
- diag::warn_unknown_attribute_ignored) << A.getName();
+ S.Diag(A.getLoc(), A.isDeclspecAttribute()
+ ? (unsigned)diag::warn_unhandled_ms_attribute_ignored
+ : (unsigned)diag::warn_unknown_attribute_ignored)
+ << A.getName();
return nullptr;
case ParsedAttr::AT_FallThrough:
return handleFallThroughAttr(S, St, A, Range);
@@ -308,7 +347,7 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
// if we're here, then we parsed a known attribute, but didn't recognize
// it as a statement attribute => it is declaration attribute
S.Diag(A.getRange().getBegin(), diag::err_decl_attribute_invalid_on_stmt)
- << A.getName() << St->getLocStart();
+ << A.getName() << St->getBeginLoc();
return nullptr;
}
}