Adding a new #pragma for the vectorize and interleave optimization hints.

Patch thanks to Tyler Nowicki!

llvm-svn: 210330
diff --git a/clang/test/CodeGen/pragma-loop.cpp b/clang/test/CodeGen/pragma-loop.cpp
new file mode 100644
index 0000000..b00b0c0
--- /dev/null
+++ b/clang/test/CodeGen/pragma-loop.cpp
@@ -0,0 +1,120 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s

+

+// Verify while loop is recognized after sequence of pragma clang loop directives.

+void while_test(int *List, int Length) {

+  // CHECK: define {{.*}} @_Z10while_test

+  int i = 0;

+

+#pragma clang loop vectorize(enable)

+#pragma clang loop interleave_count(4)

+#pragma clang loop vectorize_width(4)

+  while (i < Length) {

+    // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_1:.*]]

+    List[i] = i * 2;

+    i++;

+  }

+}

+

+// Verify do loop is recognized after multi-option pragma clang loop directive.

+void do_test(int *List, int Length) {

+  int i = 0;

+

+#pragma clang loop vectorize_width(8) interleave_count(4)

+  do {

+    // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_2:.*]]

+    List[i] = i * 2;

+    i++;

+  } while (i < Length);

+}

+

+// Verify for loop is recognized after sequence of pragma clang loop directives.

+void for_test(int *List, int Length) {

+#pragma clang loop interleave(enable)

+#pragma clang loop interleave_count(4)

+  for (int i = 0; i < Length; i++) {

+    // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_3:.*]]

+    List[i] = i * 2;

+  }

+}

+

+// Verify c++11 for range loop is recognized after

+// sequence of pragma clang loop directives.

+void for_range_test() {

+  double List[100];

+

+#pragma clang loop vectorize_width(2) interleave_count(2)

+  for (int i : List) {

+    // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_4:.*]]

+    List[i] = i;

+  }

+}

+

+// Verify disable pragma clang loop directive generates correct metadata

+void disable_test(int *List, int Length) {

+#pragma clang loop vectorize(disable)

+  for (int i = 0; i < Length; i++) {

+    // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_5:.*]]

+    List[i] = i * 2;

+  }

+}

+

+#define VECWIDTH 2

+#define INTCOUNT 2

+

+// 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)

+  for (int i = 0; i < Length; i++) {

+    // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_6:.*]]

+    List[i] = i * Value;

+  }

+}

+

+// Verify metadata is generated when template is used.

+template <typename A>

+void for_template_test(A *List, int Length, A Value) {

+

+#pragma clang loop vectorize_width(8) interleave_count(8)

+  for (int i = 0; i < Length; i++) {

+    // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_7:.*]]

+    List[i] = i * Value;

+  }

+}

+

+// Verify define is resolved correctly when template is used.

+template <typename A>

+void for_template_define_test(A *List, int Length, A Value) {

+#pragma clang loop vectorize_width(VECWIDTH) interleave_count(INTCOUNT)

+  for (int i = 0; i < Length; i++) {

+    // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_8:.*]]

+    List[i] = i * Value;

+  }

+}

+

+#undef VECWIDTH

+#undef INTCOUNT

+

+// Use templates defined above. Test verifies metadata is generated correctly.

+void template_test(double *List, int Length) {

+  double Value = 10;

+

+  for_template_test<double>(List, Length, Value);

+  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: ![[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: ![[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: ![[WIDTH_2]] = metadata !{metadata !"llvm.vectorizer.width", i32 2}

+// CHECK: ![[LOOP_5]] = metadata !{metadata ![[LOOP_5]], 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:.*]]}

diff --git a/clang/test/PCH/pragma-loop.cpp b/clang/test/PCH/pragma-loop.cpp
new file mode 100644
index 0000000..41bbf72
--- /dev/null
+++ b/clang/test/PCH/pragma-loop.cpp
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -emit-pch -o %t.a %s

+// RUN: %clang_cc1 -include-pch %t.a %s -ast-print -o - | FileCheck %s

+

+// 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 interleave_count(8)

+// CHECK: #pragma clang loop vectorize_width(4)

+// CHECK: #pragma clang loop interleave(disable)

+// CHECK: #pragma clang loop vectorize(enable)

+// CHECK: #pragma clang loop interleave(enable)

+// CHECK: #pragma clang loop vectorize(disable)

+

+#ifndef HEADER

+#define HEADER

+

+class pragma_test {

+public:

+  inline void run1(int *List, int Length) {

+    int i = 0;

+#pragma clang loop vectorize_width(4)

+#pragma clang loop interleave_count(8)

+    while (i < Length) {

+      List[i] = i;

+      i++;

+    }

+  }

+

+  inline void run2(int *List, int Length) {

+    int i = 0;

+#pragma clang loop vectorize(enable)

+#pragma clang loop interleave(disable)

+    while (i - 1 < Length) {

+      List[i] = i;

+      i++;

+    }

+  }

+

+  inline void run3(int *List, int Length) {

+    int i = 0;

+#pragma clang loop vectorize(disable)

+#pragma clang loop interleave(enable)

+    while (i - 3 < Length) {

+      List[i] = i;

+      i++;

+    }

+  }

+};

+

+#else

+

+void test() {

+  int List[100];

+

+  pragma_test pt;

+

+  pt.run1(List, 100);

+  pt.run2(List, 100);

+  pt.run3(List, 100);

+}

+

+#endif

diff --git a/clang/test/Parser/pragma-loop.cpp b/clang/test/Parser/pragma-loop.cpp
new file mode 100644
index 0000000..e515eb4
--- /dev/null
+++ b/clang/test/Parser/pragma-loop.cpp
@@ -0,0 +1,132 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s

+

+// Note that this puts the expected lines before the directives to work around

+// limitations in the -verify mode.

+

+void test(int *List, int Length) {

+  int i = 0;

+

+#pragma clang loop vectorize(enable)

+#pragma clang loop interleave(enable)

+  while (i + 1 < Length) {

+    List[i] = i;

+  }

+

+#pragma clang loop vectorize_width(4)

+#pragma clang loop interleave_count(8)

+  while (i < Length) {

+    List[i] = i;

+  }

+

+#pragma clang loop vectorize(disable)

+#pragma clang loop interleave(disable)

+  while (i - 1 < Length) {

+    List[i] = i;

+  }

+

+#pragma clang loop vectorize_width(4) interleave_count(8)

+  while (i - 2 < Length) {

+    List[i] = i;

+  }

+

+#pragma clang loop interleave_count(16)

+  while (i - 3 < Length) {

+    List[i] = i;

+  }

+

+  int VList[Length];

+#pragma clang loop vectorize(disable) interleave(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 vectorize(enable

+/* expected-error {{expected ')'}} */ #pragma clang loop interleave(enable

+

+/* expected-error {{expected ')'}} */ #pragma clang loop vectorize_width(4

+/* expected-error {{expected ')'}} */ #pragma clang loop interleave_count(4

+

+/* expected-error {{missing option}} */ #pragma clang loop

+/* expected-error {{invalid option 'badkeyword'}} */ #pragma clang loop badkeyword

+/* expected-error {{invalid option 'badkeyword'}} */ #pragma clang loop badkeyword(enable)

+/* expected-error {{invalid option 'badkeyword'}} */ #pragma clang loop vectorize(enable) badkeyword(4)

+/* expected-warning {{extra tokens at end of '#pragma clang loop'}} */ #pragma clang loop vectorize(enable) ,

+

+  while (i-4 < Length) {

+    List[i] = i;

+  }

+

+/* 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)

+  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)

+  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)

+  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)

+  while (i-7 < Length) {

+    List[i] = i;

+  }

+

+#pragma clang loop vectorize(enable)

+/* expected-error {{expected a for, while, or do-while loop to follow the '#pragma clang loop' directive}} */ int j = Length;

+  List[0] = List[1];

+

+  while (j-1 < Length) {

+    List[j] = j;

+  }

+

+// FIXME: A bug in ParsedAttributes causes the order of the attributes to be

+// processed in reverse. Consequently, the errors occur on the first of pragma

+// of the next three tests rather than the last, and the order of the kinds

+// is also reversed.

+

+/* expected-error {{incompatible directives 'vectorize(disable)' and 'vectorize_width(4)'}} */ #pragma clang loop vectorize_width(4)

+#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)

+  while (i-8 < Length) {

+    List[i] = i;

+  }

+

+/* expected-error {{duplicate directives 'vectorize(disable)' and 'vectorize(enable)'}} */ #pragma clang loop vectorize(enable)

+#pragma clang loop vectorize(disable)

+/* expected-error {{duplicate directives 'interleave(disable)' and 'interleave(enable)'}} */ #pragma clang loop interleave(enable)

+#pragma clang loop interleave(disable)

+  while (i-9 < Length) {

+    List[i] = i;

+  }

+

+/* expected-error {{incompatible directives 'vectorize_width(4)' and 'vectorize(disable)'}} */ #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)

+#pragma clang loop interleave_count(4)

+  while (i-10 < Length) {

+    List[i] = i;

+  }

+

+/* expected-error {{duplicate directives 'vectorize_width(4)' and 'vectorize_width(8)'}} */ #pragma clang loop vectorize_width(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)

+  while (i-11 < Length) {

+    List[i] = i;

+  }

+

+#pragma clang loop interleave(enable)

+/* expected-error {{expected statement}} */ }