r210667 - Add loop unroll pragma support

Eli Bendersky eliben at google.com
Wed Jun 11 10:56:26 PDT 2014


Author: eliben
Date: Wed Jun 11 12:56:26 2014
New Revision: 210667

URL: http://llvm.org/viewvc/llvm-project?rev=210667&view=rev
Log:
Add loop unroll pragma support

http://reviews.llvm.org/D4089

Patch by Mark Heffernan.


Modified:
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/lib/CodeGen/CGStmt.cpp
    cfe/trunk/lib/Parse/ParsePragma.cpp
    cfe/trunk/lib/Sema/SemaStmtAttr.cpp
    cfe/trunk/test/CodeGen/pragma-loop.cpp
    cfe/trunk/test/PCH/pragma-loop.cpp
    cfe/trunk/test/Parser/pragma-loop.cpp

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=210667&r1=210666&r2=210667&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Wed Jun 11 12:56:26 2014
@@ -1766,6 +1766,8 @@ def LoopHint : Attr {
   /// 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 @@ def LoopHint : Attr {
 
   /// 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 @@ def LoopHint : Attr {
     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 @@ def LoopHint : Attr {
   // 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);

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=210667&r1=210666&r2=210667&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Wed Jun 11 12:56:26 2014
@@ -895,7 +895,8 @@ def err_omp_more_one_clause : Error<
 
 // 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 {

Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=210667&r1=210666&r2=210667&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Wed Jun 11 12:56:26 2014
@@ -550,6 +550,12 @@ void CodeGenFunction::EmitCondBrHints(ll
     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 @@ void CodeGenFunction::EmitCondBrHints(ll
       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;

Modified: cfe/trunk/lib/Parse/ParsePragma.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParsePragma.cpp?rev=210667&r1=210666&r2=210667&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParsePragma.cpp (original)
+++ cfe/trunk/lib/Parse/ParsePragma.cpp Wed Jun 11 12:56:26 2014
@@ -1641,8 +1641,10 @@ void PragmaOptimizeHandler::HandlePragma
 ///  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 @@ void PragmaOptimizeHandler::HandlePragma
 /// 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) {
@@ -1679,9 +1688,15 @@ void PragmaLoopHintHandler::HandlePragma
     Token Option = Tok;
     IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
 
-    if (!OptionInfo->isStr("vectorize") && !OptionInfo->isStr("interleave") &&
-        !OptionInfo->isStr("vectorize_width") &&
-        !OptionInfo->isStr("interleave_count")) {
+    bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
+        .Case("vectorize", true)
+        .Case("interleave", true)
+        .Case("unroll", true)
+        .Case("vectorize_width", true)
+        .Case("interleave_count", true)
+        .Case("unroll_count", true)
+        .Default(false);
+    if (!OptionValid) {
       PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
           << /*MissingOption=*/false << OptionInfo;
       return;

Modified: cfe/trunk/lib/Sema/SemaStmtAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmtAttr.cpp?rev=210667&r1=210666&r2=210667&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmtAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmtAttr.cpp Wed Jun 11 12:56:26 2014
@@ -67,10 +67,13 @@ static Attr *handleLoopHintAttr(Sema &S,
           .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 @@ static Attr *handleLoopHintAttr(Sema &S,
       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,9 +115,24 @@ static Attr *handleLoopHintAttr(Sema &S,
 
 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 array
+  // accumulate the hints encountered while iterating through the
+  // attributes to check for compatibility.
+  struct {
+    int EnableOptionId;
+    int NumericOptionId;
+    bool EnabledIsSet;
+    bool ValueIsSet;
+    bool Enabled;
+    int Value;
+  } Options[] = {
+    {LoopHintAttr::Vectorize, LoopHintAttr::VectorizeWidth},
+    {LoopHintAttr::Interleave, LoopHintAttr::InterleaveCount},
+    {LoopHintAttr::Unroll, LoopHintAttr::UnrollCount}
+  };
 
   for (const auto *I : Attrs) {
     const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(I);
@@ -122,76 +141,64 @@ CheckForIncompatibleAttributes(Sema &S,
     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;
+    };
 
+    auto &CategoryState = Options[Category];
     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 (CategoryState.EnabledIsSet) {
+        // Cannot specify enable/disable state twice.
         S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
             << /*Duplicate=*/true << LoopHintAttr::getOptionName(Option)
-            << LoopHintAttr::getValueName(PrevValue)
+            << LoopHintAttr::getValueName(CategoryState.Enabled)
             << LoopHintAttr::getOptionName(Option)
-            << LoopHintAttr::getValueName(Value);
-      }
-
-      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);
+            << LoopHintAttr::getValueName(ValueInt);
       }
+      CategoryState.EnabledIsSet = true;
+      CategoryState.Enabled = 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 (CategoryState.ValueIsSet) {
+        // Cannot specify numeric hint twice.
         S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
             << /*Duplicate=*/true << LoopHintAttr::getOptionName(Option)
-            << PrevValueInt << LoopHintAttr::getOptionName(Option) << ValueInt;
+            << CategoryState.Value << LoopHintAttr::getOptionName(Option)
+            << ValueInt;
       }
+      CategoryState.ValueIsSet = true;
+      CategoryState.Value = ValueInt;
     }
 
-    PrevOptionValue[Option] = ValueInt;
+    if (CategoryState.EnabledIsSet && !CategoryState.Enabled &&
+        CategoryState.ValueIsSet) {
+      // Disable hints are not compatible with numeric hints of the
+      // same category.
+      S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
+          << /*Duplicate=*/false
+          << LoopHintAttr::getOptionName(CategoryState.EnableOptionId)
+          << LoopHintAttr::getValueName(CategoryState.Enabled)
+          << LoopHintAttr::getOptionName(CategoryState.NumericOptionId)
+          << CategoryState.Value;
+    }
   }
 }
 

Modified: cfe/trunk/test/CodeGen/pragma-loop.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/pragma-loop.cpp?rev=210667&r1=210666&r2=210667&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/pragma-loop.cpp (original)
+++ cfe/trunk/test/CodeGen/pragma-loop.cpp Wed Jun 11 12:56:26 2014
@@ -8,6 +8,7 @@ void while_test(int *List, int Length) {
 #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 while_test(int *List, int Length) {
 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 do_test(int *List, int Length) {
 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 @@ void for_range_test() {
 
 // 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 @@ void disable_test(int *List, int Length)
 
 #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 @@ void for_define_test(int *List, int Leng
 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 @@ void for_template_test(A *List, int Leng
 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 @@ void for_template_define_test(A *List, i
 
 #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 @@ void template_test(double *List, int Len
   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:.*]]}

Modified: cfe/trunk/test/PCH/pragma-loop.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/pragma-loop.cpp?rev=210667&r1=210666&r2=210667&view=diff
==============================================================================
--- cfe/trunk/test/PCH/pragma-loop.cpp (original)
+++ cfe/trunk/test/PCH/pragma-loop.cpp Wed Jun 11 12:56:26 2014
@@ -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 @@ public:
     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 @@ public:
     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 @@ public:
     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++;

Modified: cfe/trunk/test/Parser/pragma-loop.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/pragma-loop.cpp?rev=210667&r1=210666&r2=210667&view=diff
==============================================================================
--- cfe/trunk/test/Parser/pragma-loop.cpp (original)
+++ cfe/trunk/test/Parser/pragma-loop.cpp Wed Jun 11 12:56:26 2014
@@ -8,23 +8,26 @@ void test(int *List, int Length) {
 
 #pragma clang loop vectorize(enable)
 #pragma clang loop interleave(enable)
+#pragma clang loop unroll(enable)
   while (i + 1 < Length) {
     List[i] = i;
   }
 
 #pragma clang loop vectorize_width(4)
 #pragma clang loop interleave_count(8)
+#pragma clang loop unroll_count(16)
   while (i < Length) {
     List[i] = i;
   }
 
 #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,19 +38,22 @@ void test(int *List, int Length) {
   }
 
   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];
   }
 
 /* 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,24 +67,28 @@ void test(int *List, int Length) {
 
 /* 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;
   }
 
 /* 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;
   }
 
 /* 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;
   }
 
 /* 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 @@ void test(int *List, int Length) {
 #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,14 +120,18 @@ void test(int *List, int Length) {
 #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;
   }
 
-/* expected-error {{incompatible directives 'vectorize_width(4)' and 'vectorize(disable)'}} */ #pragma clang loop vectorize(disable)
+/* expected-error {{incompatible directives 'vectorize(disable)' and 'vectorize_width(4)'}} */ #pragma clang loop vectorize(disable)
 #pragma clang loop vectorize_width(4)
-/* expected-error {{incompatible directives 'interleave_count(4)' and 'interleave(disable)'}} */ #pragma clang loop interleave(disable)
+/* expected-error {{incompatible directives 'interleave(disable)' and 'interleave_count(4)'}} */ #pragma clang loop interleave(disable)
 #pragma clang loop interleave_count(4)
+/* expected-error {{incompatible directives 'unroll(disable)' and 'unroll_count(4)'}} */ #pragma clang loop unroll(disable)
+#pragma clang loop unroll_count(4)
   while (i-10 < Length) {
     List[i] = i;
   }
@@ -124,6 +140,8 @@ void test(int *List, int Length) {
 #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;
   }





More information about the cfe-commits mailing list