Hi TylerNowicki, eliben, aaron.ballman, rsmith,
Piggy-backing on the support for "#pragma clang loop vectorize..." which was
added recently by Tyler. This patch adds support for loop unrolling pragmas.
The pragmas must immediately precede a loop statement and take the following
forms:
#pragma clang loop unroll(enable) // unroll the loop completely
#pragma clang loop unroll(disable) // do not unroll the loop.
#pragma clang loop unroll_count(N) // unroll the loop N times
if both unroll(enable) and unroll_count(N) are specified then the unroll_count
takes precedence (ie, unroll the loop N times).
Tyler, I changed the logic a bit in CheckForIncompatibleAttributes,
specifically it now rejects any combination of the disable form of the pragma
and the numeric form (eg, vectorize(disable) and vectorize_width(N)). As a
special case, it previously allowed this combination if the numeric value is 1.
The logic seems cleaner without that special case. Lemme know if that's
reasonable.
I'll be sending out a LLVM patch which consumes the generated metadata right
after this.
http://reviews.llvm.org/D4089
Files:
include/clang/Basic/Attr.td
include/clang/Basic/DiagnosticParseKinds.td
lib/CodeGen/CGStmt.cpp
lib/Parse/ParsePragma.cpp
lib/Sema/SemaStmtAttr.cpp
test/CodeGen/pragma-loop.cpp
test/PCH/pragma-loop.cpp
test/Parser/pragma-loop.cpp
Index: include/clang/Basic/Attr.td
===================================================================
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -1766,6 +1766,8 @@
/// vectorize_width: vectorize loop operations with width 'value'.
/// interleave: interleave multiple loop iterations if 'value != 0'.
/// interleave_count: interleaves 'value' loop interations.
+ /// unroll: unroll loop if 'value != 0'.
+ /// unroll_count: unrolls loop 'value' times.
/// FIXME: Add Pragma spelling to tablegen and
/// use it here.
@@ -1773,8 +1775,10 @@
/// State of the loop optimization specified by the spelling.
let Args = [EnumArgument<"Option", "OptionType",
- ["vectorize", "vectorize_width", "interleave", "interleave_count"],
- ["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount"]>,
+ ["vectorize", "vectorize_width", "interleave", "interleave_count",
+ "unroll", "unroll_count"],
+ ["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount",
+ "Unroll", "UnrollCount"]>,
DefaultIntArgument<"Value", 1>];
let AdditionalMembers = [{
@@ -1784,6 +1788,8 @@
case VectorizeWidth: return "vectorize_width";
case Interleave: return "interleave";
case InterleaveCount: return "interleave_count";
+ case Unroll: return "unroll";
+ case UnrollCount: return "unroll_count";
}
llvm_unreachable("Unhandled LoopHint option.");
}
@@ -1797,7 +1803,8 @@
// FIXME: Modify pretty printer to print this pragma.
void print(raw_ostream &OS, const PrintingPolicy &Policy) const {
OS << "#pragma clang loop " << getOptionName(option) << "(";
- if (option == VectorizeWidth || option == InterleaveCount)
+ if (option == VectorizeWidth || option == InterleaveCount ||
+ option == UnrollCount)
OS << value;
else
OS << getValueName(value);
Index: include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -895,7 +895,8 @@
// Pragma loop support.
def err_pragma_loop_invalid_option : Error<
- "%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, vectorize_width, interleave, or interleave_count">;
+ "%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, "
+ "vectorize_width, interleave, interleave_count, unroll, or unroll_count">;
} // end of Parse Issue category.
let CategoryName = "Modules Issue" in {
Index: lib/CodeGen/CGStmt.cpp
===================================================================
--- lib/CodeGen/CGStmt.cpp
+++ lib/CodeGen/CGStmt.cpp
@@ -550,6 +550,12 @@
case LoopHintAttr::InterleaveCount:
MetadataName = "llvm.vectorizer.unroll";
break;
+ case LoopHintAttr::Unroll:
+ MetadataName = "llvm.loopunroll.enable";
+ break;
+ case LoopHintAttr::UnrollCount:
+ MetadataName = "llvm.loopunroll.count";
+ break;
}
llvm::Value *Value;
@@ -572,6 +578,14 @@
Name = llvm::MDString::get(Context, MetadataName);
Value = llvm::ConstantInt::get(Int32Ty, ValueInt);
break;
+ case LoopHintAttr::Unroll:
+ Name = llvm::MDString::get(Context, MetadataName);
+ Value = (ValueInt == 0) ? Builder.getFalse() : Builder.getTrue();
+ break;
+ case LoopHintAttr::UnrollCount:
+ Name = llvm::MDString::get(Context, MetadataName);
+ Value = llvm::ConstantInt::get(Int32Ty, ValueInt);
+ break;
}
SmallVector<llvm::Value *, 2> OpValues;
Index: lib/Parse/ParsePragma.cpp
===================================================================
--- lib/Parse/ParsePragma.cpp
+++ lib/Parse/ParsePragma.cpp
@@ -1641,8 +1641,10 @@
/// loop-hint:
/// 'vectorize' '(' loop-hint-keyword ')'
/// 'interleave' '(' loop-hint-keyword ')'
+/// 'unroll' '(' loop-hint-keyword ')'
/// 'vectorize_width' '(' loop-hint-value ')'
/// 'interleave_count' '(' loop-hint-value ')'
+/// 'unroll_count' '(' loop-hint-value ')'
///
/// loop-hint-keyword:
/// 'enable'
@@ -1661,6 +1663,13 @@
/// possible and profitable, and 0 is invalid. The loop vectorizer currently
/// only works on inner loops.
///
+/// The unroll and unroll_count directives control the concatenation
+/// unroller. Specifying unroll(enable) instructs llvm to try to
+/// unroll the loop completely, and unroll(disable) disables unrolling
+/// for the loop. Specifying unroll_count(_value_) instructs llvm to
+/// try to unroll the loop the number of times indicated by the value.
+/// If unroll(enable) and unroll_count are both specified only
+/// unroll_count takes effect.
void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &Tok) {
@@ -1680,8 +1689,9 @@
IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
if (!OptionInfo->isStr("vectorize") && !OptionInfo->isStr("interleave") &&
- !OptionInfo->isStr("vectorize_width") &&
- !OptionInfo->isStr("interleave_count")) {
+ !OptionInfo->isStr("unroll") && !OptionInfo->isStr("vectorize_width") &&
+ !OptionInfo->isStr("interleave_count") &&
+ !OptionInfo->isStr("unroll_count")) {
PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
<< /*MissingOption=*/false << OptionInfo;
return;
Index: lib/Sema/SemaStmtAttr.cpp
===================================================================
--- lib/Sema/SemaStmtAttr.cpp
+++ lib/Sema/SemaStmtAttr.cpp
@@ -67,10 +67,13 @@
.Case("vectorize_width", LoopHintAttr::VectorizeWidth)
.Case("interleave", LoopHintAttr::Interleave)
.Case("interleave_count", LoopHintAttr::InterleaveCount)
+ .Case("unroll", LoopHintAttr::Unroll)
+ .Case("unroll_count", LoopHintAttr::UnrollCount)
.Default(LoopHintAttr::Vectorize);
int ValueInt;
- if (Option == LoopHintAttr::Vectorize || Option == LoopHintAttr::Interleave) {
+ if (Option == LoopHintAttr::Vectorize || Option == LoopHintAttr::Interleave ||
+ Option == LoopHintAttr::Unroll) {
if (!ValueInfo) {
S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_keyword)
<< /*MissingKeyword=*/true << "";
@@ -87,7 +90,8 @@
return nullptr;
}
} else if (Option == LoopHintAttr::VectorizeWidth ||
- Option == LoopHintAttr::InterleaveCount) {
+ Option == LoopHintAttr::InterleaveCount ||
+ Option == LoopHintAttr::UnrollCount) {
// FIXME: We should support template parameters for the loop hint value.
// See bug report #19610.
llvm::APSInt ValueAPS;
@@ -111,10 +115,26 @@
static void
CheckForIncompatibleAttributes(Sema &S, SmallVectorImpl<const Attr *> &Attrs) {
- int PrevOptionValue[4] = {-1, -1, -1, -1};
- int OptionId[4] = {LoopHintAttr::Vectorize, LoopHintAttr::VectorizeWidth,
- LoopHintAttr::Interleave, LoopHintAttr::InterleaveCount};
+ // There are 3 categories of loop hints: vectorize, interleave, and
+ // unroll. Each comes in two variants: an enable/disable form and a
+ // form which takes a numeric argument. For example:
+ // unroll(enable|disable) and unroll_count(N). The following arrays
+ // accumulate the hints encountered while iterating through the
+ // attributes to check for compatibility
+ //
+ // Accumulated state of enable|disable hints for each hint category.
+ bool EnabledIsSet[3] = {false, false, false};
+ int EnabledValue[3];
+ // Accumulated state of numeric hints for each hint category.
+ bool NumericValueIsSet[3] = {false, false, false};
+ int NumericValue[3];
+ int EnableOptionId[3] = {LoopHintAttr::Vectorize, LoopHintAttr::Interleave,
+ LoopHintAttr::Unroll};
+ int NumericOptionId[3] = {LoopHintAttr::VectorizeWidth,
+ LoopHintAttr::InterleaveCount,
+ LoopHintAttr::UnrollCount};
+
for (const auto *I : Attrs) {
const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(I);
@@ -122,76 +142,69 @@
if (!LH)
continue;
- int State, Value;
int Option = LH->getOption();
int ValueInt = LH->getValue();
+ int Category;
switch (Option) {
case LoopHintAttr::Vectorize:
case LoopHintAttr::VectorizeWidth:
- State = 0;
- Value = 1;
+ Category = 0;
break;
case LoopHintAttr::Interleave:
case LoopHintAttr::InterleaveCount:
- State = 2;
- Value = 3;
+ Category = 1;
break;
- }
+ case LoopHintAttr::Unroll:
+ case LoopHintAttr::UnrollCount:
+ Category = 2;
+ break;
+ };
SourceLocation ValueLoc = LH->getRange().getEnd();
-
- // Compatibility testing is split into two cases.
- // 1. if the current loop hint sets state (enable/disable) - check against
- // previous state and value.
- // 2. if the current loop hint sets a value - check against previous state
- // and value.
-
- if (Option == State) {
- if (PrevOptionValue[State] != -1) {
- // Cannot specify state twice.
- int PrevValue = PrevOptionValue[State];
+ if (Option == LoopHintAttr::Vectorize ||
+ Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll) {
+ // Enable|disable hint. For example, vectorize(enable).
+ if (EnabledIsSet[Category]) {
+ // Cannot specify enable/disable state twice.
S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
<< /*Duplicate=*/true << LoopHintAttr::getOptionName(Option)
- << LoopHintAttr::getValueName(PrevValue)
+ << LoopHintAttr::getValueName(EnabledValue[Category])
<< LoopHintAttr::getOptionName(Option)
- << LoopHintAttr::getValueName(Value);
+ << LoopHintAttr::getValueName(ValueInt);
}
-
- if (PrevOptionValue[Value] != -1) {
- // Compare state with previous width/count.
- int PrevOption = OptionId[Value];
- int PrevValueInt = PrevOptionValue[Value];
- if ((ValueInt == 0 && PrevValueInt > 1) ||
- (ValueInt == 1 && PrevValueInt <= 1))
- S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
- << /*Duplicate=*/false << LoopHintAttr::getOptionName(PrevOption)
- << PrevValueInt << LoopHintAttr::getOptionName(Option)
- << LoopHintAttr::getValueName(ValueInt);
+ if (NumericValueIsSet[Category] && ValueInt == 0) {
+ // Disable hints (ValueInt == 0) are not compatible with
+ // numeric hints of the same category.
+ S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
+ << /*Duplicate=*/false
+ << LoopHintAttr::getOptionName(NumericOptionId[Category])
+ << NumericValue[Category] << LoopHintAttr::getOptionName(Option)
+ << LoopHintAttr::getValueName(ValueInt);
}
+ EnabledIsSet[Category] = true;
+ EnabledValue[Category] = ValueInt;
} else {
- if (PrevOptionValue[State] != -1) {
- // Compare width/count value with previous state.
- int PrevOption = OptionId[State];
- int PrevValueInt = PrevOptionValue[State];
- if ((ValueInt > 1 && PrevValueInt == 0) ||
- (ValueInt <= 1 && PrevValueInt == 1))
- S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
- << /*Duplicate=*/false << LoopHintAttr::getOptionName(PrevOption)
- << LoopHintAttr::getValueName(PrevValueInt)
- << LoopHintAttr::getOptionName(Option) << ValueInt;
- }
-
- if (PrevOptionValue[Value] != -1) {
- // Cannot specify a width/count twice.
- int PrevValueInt = PrevOptionValue[Value];
+ // Numeric hint. For example, unroll_count(8).
+ if (NumericValueIsSet[Category]) {
+ // Cannot specify numeric hint twice.
S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
<< /*Duplicate=*/true << LoopHintAttr::getOptionName(Option)
- << PrevValueInt << LoopHintAttr::getOptionName(Option) << ValueInt;
+ << NumericValue[Category] << LoopHintAttr::getOptionName(Option)
+ << ValueInt;
}
+ if (EnabledIsSet[Category] && EnabledValue[Category] == 0) {
+ // Disable hints are not compatible with numeric hints of the
+ // same category.
+ S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
+ << /*Duplicate=*/false
+ << LoopHintAttr::getOptionName(EnableOptionId[Category])
+ << LoopHintAttr::getValueName(EnabledValue[Category])
+ << LoopHintAttr::getOptionName(Option) << ValueInt;
+ }
+ NumericValueIsSet[Category] = true;
+ NumericValue[Category] = ValueInt;
}
-
- PrevOptionValue[Option] = ValueInt;
}
}
Index: test/CodeGen/pragma-loop.cpp
===================================================================
--- test/CodeGen/pragma-loop.cpp
+++ test/CodeGen/pragma-loop.cpp
@@ -8,6 +8,7 @@
#pragma clang loop vectorize(enable)
#pragma clang loop interleave_count(4)
#pragma clang loop vectorize_width(4)
+#pragma clang loop unroll(enable)
while (i < Length) {
// CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_1:.*]]
List[i] = i * 2;
@@ -19,7 +20,7 @@
void do_test(int *List, int Length) {
int i = 0;
-#pragma clang loop vectorize_width(8) interleave_count(4)
+#pragma clang loop vectorize_width(8) interleave_count(4) unroll(disable)
do {
// CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_2:.*]]
List[i] = i * 2;
@@ -31,6 +32,7 @@
void for_test(int *List, int Length) {
#pragma clang loop interleave(enable)
#pragma clang loop interleave_count(4)
+#pragma clang loop unroll_count(8)
for (int i = 0; i < Length; i++) {
// CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_3:.*]]
List[i] = i * 2;
@@ -51,7 +53,7 @@
// Verify disable pragma clang loop directive generates correct metadata
void disable_test(int *List, int Length) {
-#pragma clang loop vectorize(disable)
+#pragma clang loop vectorize(disable) unroll(disable)
for (int i = 0; i < Length; i++) {
// CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_5:.*]]
List[i] = i * 2;
@@ -60,10 +62,12 @@
#define VECWIDTH 2
#define INTCOUNT 2
+#define UNROLLCOUNT 8
// Verify defines are correctly resolved in pragma clang loop directive
void for_define_test(int *List, int Length, int Value) {
#pragma clang loop vectorize_width(VECWIDTH) interleave_count(INTCOUNT)
+#pragma clang loop unroll_count(UNROLLCOUNT)
for (int i = 0; i < Length; i++) {
// CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_6:.*]]
List[i] = i * Value;
@@ -74,7 +78,7 @@
template <typename A>
void for_template_test(A *List, int Length, A Value) {
-#pragma clang loop vectorize_width(8) interleave_count(8)
+#pragma clang loop vectorize_width(8) interleave_count(8) unroll_count(8)
for (int i = 0; i < Length; i++) {
// CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_7:.*]]
List[i] = i * Value;
@@ -85,6 +89,7 @@
template <typename A>
void for_template_define_test(A *List, int Length, A Value) {
#pragma clang loop vectorize_width(VECWIDTH) interleave_count(INTCOUNT)
+#pragma clang loop unroll_count(UNROLLCOUNT)
for (int i = 0; i < Length; i++) {
// CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_8:.*]]
List[i] = i * Value;
@@ -93,6 +98,7 @@
#undef VECWIDTH
#undef INTCOUNT
+#undef UNROLLCOUNT
// Use templates defined above. Test verifies metadata is generated correctly.
void template_test(double *List, int Length) {
@@ -102,19 +108,22 @@
for_template_define_test<double>(List, Length, Value);
}
-// CHECK: ![[LOOP_1]] = metadata !{metadata ![[LOOP_1]], metadata ![[WIDTH_4:.*]], metadata ![[UNROLL_4:.*]], metadata ![[ENABLE_1:.*]]}
+// CHECK: ![[LOOP_1]] = metadata !{metadata ![[LOOP_1]], metadata ![[UNROLLENABLE_1:.*]], metadata ![[WIDTH_4:.*]], metadata ![[INTERLEAVE_4:.*]], metadata ![[INTENABLE_1:.*]]}
+// CHECK: ![[UNROLLENABLE_1]] = metadata !{metadata !"llvm.loopunroll.enable", i1 true}
// CHECK: ![[WIDTH_4]] = metadata !{metadata !"llvm.vectorizer.width", i32 4}
-// CHECK: ![[UNROLL_4]] = metadata !{metadata !"llvm.vectorizer.unroll", i32 4}
-// CHECK: ![[ENABLE_1]] = metadata !{metadata !"llvm.vectorizer.enable", i1 true}
-// CHECK: ![[LOOP_2]] = metadata !{metadata ![[LOOP_2:.*]], metadata ![[UNROLL_4:.*]], metadata ![[WIDTH_8:.*]]}
+// CHECK: ![[INTERLEAVE_4]] = metadata !{metadata !"llvm.vectorizer.unroll", i32 4}
+// CHECK: ![[INTENABLE_1]] = metadata !{metadata !"llvm.vectorizer.enable", i1 true}
+// CHECK: ![[LOOP_2]] = metadata !{metadata ![[LOOP_2:.*]], metadata ![[UNROLLENABLE_0:.*]], metadata ![[INTERLEAVE_4:.*]], metadata ![[WIDTH_8:.*]]}
+// CHECK: ![[UNROLLENABLE_0]] = metadata !{metadata !"llvm.loopunroll.enable", i1 false}
// CHECK: ![[WIDTH_8]] = metadata !{metadata !"llvm.vectorizer.width", i32 8}
-// CHECK: ![[LOOP_3]] = metadata !{metadata ![[LOOP_3]], metadata ![[UNROLL_4:.*]], metadata ![[ENABLE_1:.*]]}
-// CHECK: ![[LOOP_4]] = metadata !{metadata ![[LOOP_4]], metadata ![[UNROLL_2:.*]], metadata ![[WIDTH_2:.*]]}
-// CHECK: ![[UNROLL_2]] = metadata !{metadata !"llvm.vectorizer.unroll", i32 2}
+// CHECK: ![[LOOP_3]] = metadata !{metadata ![[LOOP_3]], metadata ![[UNROLL_8:.*]], metadata ![[INTERLEAVE_4:.*]], metadata ![[ENABLE_1:.*]]}
+// CHECK: ![[UNROLL_8]] = metadata !{metadata !"llvm.loopunroll.count", i32 8}
+// CHECK: ![[LOOP_4]] = metadata !{metadata ![[LOOP_4]], metadata ![[INTERLEAVE_2:.*]], metadata ![[WIDTH_2:.*]]}
+// CHECK: ![[INTERLEAVE_2]] = metadata !{metadata !"llvm.vectorizer.unroll", i32 2}
// CHECK: ![[WIDTH_2]] = metadata !{metadata !"llvm.vectorizer.width", i32 2}
-// CHECK: ![[LOOP_5]] = metadata !{metadata ![[LOOP_5]], metadata ![[WIDTH_1:.*]]}
+// CHECK: ![[LOOP_5]] = metadata !{metadata ![[LOOP_5]], metadata ![[UNROLLENABLE_0:.*]], metadata ![[WIDTH_1:.*]]}
// CHECK: ![[WIDTH_1]] = metadata !{metadata !"llvm.vectorizer.width", i32 1}
-// CHECK: ![[LOOP_6]] = metadata !{metadata ![[LOOP_6]], metadata ![[UNROLL_2:.*]], metadata ![[WIDTH_2:.*]]}
-// CHECK: ![[LOOP_7]] = metadata !{metadata ![[LOOP_7]], metadata ![[UNROLL_8:.*]], metadata ![[WIDTH_8:.*]]}
-// CHECK: ![[UNROLL_8]] = metadata !{metadata !"llvm.vectorizer.unroll", i32 8}
-// CHECK: ![[LOOP_8]] = metadata !{metadata ![[LOOP_8]], metadata ![[UNROLL_2:.*]], metadata ![[WIDTH_2:.*]]}
+// CHECK: ![[LOOP_6]] = metadata !{metadata ![[LOOP_6]], metadata ![[UNROLL_8:.*]], metadata ![[INTERLEAVE_2:.*]], metadata ![[WIDTH_2:.*]]}
+// CHECK: ![[LOOP_7]] = metadata !{metadata ![[LOOP_7]], metadata ![[UNROLL_8:.*]], metadata ![[INTERLEAVE_8:.*]], metadata ![[WIDTH_8:.*]]}
+// CHECK: ![[INTERLEAVE_8]] = metadata !{metadata !"llvm.vectorizer.unroll", i32 8}
+// CHECK: ![[LOOP_8]] = metadata !{metadata ![[LOOP_8]], metadata ![[UNROLL_8:.*]], metadata ![[INTERLEAVE_2:.*]], metadata ![[WIDTH_2:.*]]}
Index: test/PCH/pragma-loop.cpp
===================================================================
--- test/PCH/pragma-loop.cpp
+++ test/PCH/pragma-loop.cpp
@@ -4,10 +4,13 @@
// FIXME: A bug in ParsedAttributes causes the order of the attributes to be
// reversed. The checks are consequently in the reverse order below.
+// CHECK: #pragma clang loop unroll_count(16)
// CHECK: #pragma clang loop interleave_count(8)
// CHECK: #pragma clang loop vectorize_width(4)
+// CHECK: #pragma clang loop unroll(disable)
// CHECK: #pragma clang loop interleave(disable)
// CHECK: #pragma clang loop vectorize(enable)
+// CHECK: #pragma clang loop unroll(enable)
// CHECK: #pragma clang loop interleave(enable)
// CHECK: #pragma clang loop vectorize(disable)
@@ -20,6 +23,7 @@
int i = 0;
#pragma clang loop vectorize_width(4)
#pragma clang loop interleave_count(8)
+#pragma clang loop unroll_count(16)
while (i < Length) {
List[i] = i;
i++;
@@ -30,6 +34,7 @@
int i = 0;
#pragma clang loop vectorize(enable)
#pragma clang loop interleave(disable)
+#pragma clang loop unroll(disable)
while (i - 1 < Length) {
List[i] = i;
i++;
@@ -40,6 +45,7 @@
int i = 0;
#pragma clang loop vectorize(disable)
#pragma clang loop interleave(enable)
+#pragma clang loop unroll(enable)
while (i - 3 < Length) {
List[i] = i;
i++;
Index: test/Parser/pragma-loop.cpp
===================================================================
--- test/Parser/pragma-loop.cpp
+++ test/Parser/pragma-loop.cpp
@@ -8,6 +8,7 @@
#pragma clang loop vectorize(enable)
#pragma clang loop interleave(enable)
+#pragma clang loop unroll(enable)
while (i + 1 < Length) {
List[i] = i;
}
@@ -14,6 +15,7 @@
#pragma clang loop vectorize_width(4)
#pragma clang loop interleave_count(8)
+#pragma clang loop unroll_count(16)
while (i < Length) {
List[i] = i;
}
@@ -20,11 +22,12 @@
#pragma clang loop vectorize(disable)
#pragma clang loop interleave(disable)
+#pragma clang loop unroll(disable)
while (i - 1 < Length) {
List[i] = i;
}
-#pragma clang loop vectorize_width(4) interleave_count(8)
+#pragma clang loop vectorize_width(4) interleave_count(8) unroll_count(16)
while (i - 2 < Length) {
List[i] = i;
}
@@ -35,7 +38,7 @@
}
int VList[Length];
-#pragma clang loop vectorize(disable) interleave(disable)
+#pragma clang loop vectorize(disable) interleave(disable) unroll(disable)
for (int j : VList) {
VList[j] = List[j];
}
@@ -42,12 +45,15 @@
/* expected-error {{expected '('}} */ #pragma clang loop vectorize
/* expected-error {{expected '('}} */ #pragma clang loop interleave
+/* expected-error {{expected '('}} */ #pragma clang loop unroll
/* expected-error {{expected ')'}} */ #pragma clang loop vectorize(enable
/* expected-error {{expected ')'}} */ #pragma clang loop interleave(enable
+/* expected-error {{expected ')'}} */ #pragma clang loop unroll(enable
/* expected-error {{expected ')'}} */ #pragma clang loop vectorize_width(4
/* expected-error {{expected ')'}} */ #pragma clang loop interleave_count(4
+/* expected-error {{expected ')'}} */ #pragma clang loop unroll_count(4
/* expected-error {{missing option}} */ #pragma clang loop
/* expected-error {{invalid option 'badkeyword'}} */ #pragma clang loop badkeyword
@@ -61,6 +67,7 @@
/* expected-error {{invalid value 0; expected a positive integer value}} */ #pragma clang loop vectorize_width(0)
/* expected-error {{invalid value 0; expected a positive integer value}} */ #pragma clang loop interleave_count(0)
+/* expected-error {{invalid value 0; expected a positive integer value}} */ #pragma clang loop unroll_count(0)
while (i-5 < Length) {
List[i] = i;
}
@@ -67,6 +74,7 @@
/* expected-error {{invalid value -1294967296; expected a positive integer value}} */ #pragma clang loop vectorize_width(3000000000)
/* expected-error {{invalid value -1294967296; expected a positive integer value}} */ #pragma clang loop interleave_count(3000000000)
+/* expected-error {{invalid value -1294967296; expected a positive integer value}} */ #pragma clang loop unroll_count(3000000000)
while (i-6 < Length) {
List[i] = i;
}
@@ -73,6 +81,7 @@
/* expected-error {{missing value; expected a positive integer value}} */ #pragma clang loop vectorize_width(badvalue)
/* expected-error {{missing value; expected a positive integer value}} */ #pragma clang loop interleave_count(badvalue)
+/* expected-error {{missing value; expected a positive integer value}} */ #pragma clang loop unroll_count(badvalue)
while (i-6 < Length) {
List[i] = i;
}
@@ -79,6 +88,7 @@
/* expected-error {{invalid keyword 'badidentifier'; expected 'enable' or 'disable'}} */ #pragma clang loop vectorize(badidentifier)
/* expected-error {{invalid keyword 'badidentifier'; expected 'enable' or 'disable'}} */ #pragma clang loop interleave(badidentifier)
+/* expected-error {{invalid keyword 'badidentifier'; expected 'enable' or 'disable'}} */ #pragma clang loop unroll(badidentifier)
while (i-7 < Length) {
List[i] = i;
}
@@ -100,6 +110,8 @@
#pragma clang loop vectorize(disable)
/* expected-error {{incompatible directives 'interleave(disable)' and 'interleave_count(4)'}} */ #pragma clang loop interleave_count(4)
#pragma clang loop interleave(disable)
+/* expected-error {{incompatible directives 'unroll(disable)' and 'unroll_count(4)'}} */ #pragma clang loop unroll_count(4)
+#pragma clang loop unroll(disable)
while (i-8 < Length) {
List[i] = i;
}
@@ -108,6 +120,8 @@
#pragma clang loop vectorize(disable)
/* expected-error {{duplicate directives 'interleave(disable)' and 'interleave(enable)'}} */ #pragma clang loop interleave(enable)
#pragma clang loop interleave(disable)
+/* expected-error {{duplicate directives 'unroll(disable)' and 'unroll(enable)'}} */ #pragma clang loop unroll(enable)
+#pragma clang loop unroll(disable)
while (i-9 < Length) {
List[i] = i;
}
@@ -116,6 +130,8 @@
#pragma clang loop vectorize_width(4)
/* expected-error {{incompatible directives 'interleave_count(4)' and 'interleave(disable)'}} */ #pragma clang loop interleave(disable)
#pragma clang loop interleave_count(4)
+/* expected-error {{incompatible directives 'unroll_count(4)' and 'unroll(disable)'}} */ #pragma clang loop unroll(disable)
+#pragma clang loop unroll_count(4)
while (i-10 < Length) {
List[i] = i;
}
@@ -124,6 +140,8 @@
#pragma clang loop vectorize_width(4)
/* expected-error {{duplicate directives 'interleave_count(4)' and 'interleave_count(8)'}} */ #pragma clang loop interleave_count(8)
#pragma clang loop interleave_count(4)
+/* expected-error {{duplicate directives 'unroll_count(4)' and 'unroll_count(8)'}} */ #pragma clang loop unroll_count(8)
+#pragma clang loop unroll_count(4)
while (i-11 < Length) {
List[i] = i;
}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits