[UnrollAndJam] Add unroll_and_jam pragma handling
This adds support for the unroll_and_jam pragma, to go with the recently
added unroll and jam pass. The name of the pragma is the same as is used
in the Intel compiler, and most of the code works the same as for unroll.
#pragma clang loop unroll_and_jam has been separated into a different
patch. This part adds #pragma unroll_and_jam with an optional count, and
#pragma no_unroll_and_jam to disable the transform.
Differential Revision: https://reviews.llvm.org/D47267
llvm-svn: 338566
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index e39a65c..6eb9b28 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -87,6 +87,9 @@
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,6 +98,8 @@
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;
return nullptr;
@@ -118,6 +123,20 @@
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 &&
@@ -165,20 +184,22 @@
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 5 categories of loop hints attributes: vectorize, interleave,
+ // unroll, unroll_and_jam 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},
{nullptr, nullptr}};
for (const auto *I : Attrs) {
@@ -189,7 +210,7 @@
continue;
LoopHintAttr::OptionType Option = LH->getOption();
- enum { Vectorize, Interleave, Unroll, Distribute } Category;
+ enum { Vectorize, Interleave, Unroll, UnrollAndJam, Distribute } Category;
switch (Option) {
case LoopHintAttr::Vectorize:
case LoopHintAttr::VectorizeWidth:
@@ -203,16 +224,22 @@
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;
};
+ 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::Distribute) {
// Enable|Disable|AssumeSafety hint. For example, vectorize(enable).
PrevAttr = CategoryState.StateAttr;
@@ -232,7 +259,7 @@
<< 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