[OPENMP] Codegen for 'reduction' clause in 'parallel' directive.

Emit a code for reduction clause. Next code should be emitted for reductions:

static kmp_critical_name lock = { 0 };

void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
  ...
  *(Type<i> *)lhs[i] = RedOp<i>(*(Type<i> *)lhs[i], *(Type<i> *)rhs[i]);
  ...
}

... void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n> - 1]};
switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), RedList, reduce_func, &<lock>)) {
case 1:
  ...
  <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
  ...
  __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
  break;
case 2:
  ...
  Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
  ...
  break;
default:
  ;
}
Reduction variables are a kind of a private variables, they have private copies, but initial values are chosen in accordance with the reduction operation.

Differential Revision: http://reviews.llvm.org/D8915

llvm-svn: 234583
diff --git a/clang/test/OpenMP/simd_reduction_messages.cpp b/clang/test/OpenMP/simd_reduction_messages.cpp
index 347a5c1..1bf39cb 100644
--- a/clang/test/OpenMP/simd_reduction_messages.cpp
+++ b/clang/test/OpenMP/simd_reduction_messages.cpp
@@ -11,7 +11,7 @@
 extern S1 a;
 class S2 {
   mutable int a;
-  S2 &operator+=(const S2 &arg) { return (*this); }
+  S2 &operator+(const S2 &arg) { return (*this); } // expected-note 4 {{implicitly declared private here}}
 
 public:
   S2() : a(0) {}
@@ -28,17 +28,17 @@
 public:
   S3() : a(0) {}
   S3(const S3 &s3) : a(s3.a) {}
-  S3 operator+=(const S3 &arg1) { return arg1; }
+  S3 operator+(const S3 &arg1) { return arg1; }
 };
-int operator+=(const S3 &arg1, const S3 &arg2) { return 5; }
+int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
 S3 c;               // expected-note 2 {{'c' defined here}}
 const S3 ca[5];     // expected-note 2 {{'ca' defined here}}
 extern const int f; // expected-note 4 {{'f' declared here}}
-class S4 {          // expected-note {{'S4' declared here}}
+class S4 {
   int a;
-  S4();
+  S4(); // expected-note {{implicitly declared private here}}
   S4(const S4 &s4);
-  S4 &operator+=(const S4 &arg) { return (*this); }
+  S4 &operator+(const S4 &arg) { return (*this); }
 
 public:
   S4(int v) : a(v) {}
@@ -46,26 +46,26 @@
 S4 &operator&=(S4 &arg1, S4 &arg2) { return arg1; }
 class S5 {
   int a;
-  S5() : a(0) {}
+  S5() : a(0) {} // expected-note {{implicitly declared private here}}
   S5(const S5 &s5) : a(s5.a) {}
-  S5 &operator+=(const S5 &arg);
+  S5 &operator+(const S5 &arg);
 
 public:
   S5(int v) : a(v) {}
 };
-class S6 {
+class S6 { // expected-note 2 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
   int a;
 
 public:
   S6() : a(6) {}
   operator int() { return 6; }
-} o; // expected-note 2 {{'o' defined here}}
+} o;
 
 S3 h, k;
 #pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
 
 template <class T>       // expected-note {{declared here}}
-T tmain(T argc) {        // expected-note 2 {{'argc' defined here}}
+T tmain(T argc) {
   const T d = T();       // expected-note 4 {{'d' defined here}}
   const T da[5] = {T()}; // expected-note 2 {{'da' defined here}}
   T qa[5] = {T()};
@@ -74,7 +74,7 @@
   S3 &p = k;                       // expected-note 2 {{'p' defined here}}
   const T &r = da[(int)i];         // expected-note 2 {{'r' defined here}}
   T &q = qa[(int)i];               // expected-note 2 {{'q' defined here}}
-  T fl;                            // expected-note {{'fl' defined here}}
+  T fl;
 #pragma omp simd reduction // expected-error {{expected '(' after 'reduction'}}
   for (int i = 0; i < 10; ++i)
     foo();
@@ -96,10 +96,10 @@
 #pragma omp simd reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
   for (int i = 0; i < 10; ++i)
     foo();
-#pragma omp simd reduction(& : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{variable of type 'float' is not valid for specified reduction operation}}
+#pragma omp simd reduction(& : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
   for (int i = 0; i < 10; ++i)
     foo();
-#pragma omp simd reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{variable of type 'float' is not valid for specified reduction operation}}
+#pragma omp simd reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
   for (int i = 0; i < 10; ++i)
     foo();
 #pragma omp simd reduction(|| : argc ? i : argc) // expected-error 2 {{expected variable name}}
@@ -114,7 +114,7 @@
 #pragma omp simd reduction(^ : T) // expected-error {{'T' does not refer to a value}}
   for (int i = 0; i < 10; ++i)
     foo();
-#pragma omp simd reduction(+ : a, b, c, d, f) // expected-error {{reduction variable with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}}
+#pragma omp simd reduction(+ : a, b, c, d, f) // expected-error {{reduction variable with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 3 {{'operator+' is a private member of 'S2'}}
   for (int i = 0; i < 10; ++i)
     foo();
 #pragma omp simd reduction(min : a, b, c, d, f) // expected-error {{reduction variable with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}}
@@ -132,7 +132,7 @@
 #pragma omp simd reduction(- : da) // expected-error {{a reduction variable with array type 'const int [5]'}} expected-error {{a reduction variable with array type 'const float [5]'}}
   for (int i = 0; i < 10; ++i)
     foo();
-#pragma omp simd reduction(^ : fl) // expected-error {{variable of type 'float' is not valid for specified reduction operation}}
+#pragma omp simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
   for (int i = 0; i < 10; ++i)
     foo();
 #pragma omp simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
@@ -144,7 +144,7 @@
 #pragma omp simd reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
   for (int i = 0; i < 10; ++i)
     foo();
-#pragma omp simd reduction(+ : o) // expected-error {{variable of type 'class S6' is not valid for specified reduction operation}}
+#pragma omp simd reduction(+ : o) // expected-error {{no viable overloaded '='}}
   for (int i = 0; i < 10; ++i)
     foo();
 #pragma omp simd private(i), reduction(+ : j), reduction(+ : q) // expected-error 4 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
@@ -184,14 +184,14 @@
   const int d = 5;       // expected-note 2 {{'d' defined here}}
   const int da[5] = {0}; // expected-note {{'da' defined here}}
   int qa[5] = {0};
-  S4 e(4); // expected-note {{'e' defined here}}
-  S5 g(5); // expected-note {{'g' defined here}}
+  S4 e(4);
+  S5 g(5);
   int i;
   int &j = i;                      // expected-note 2 {{'j' defined here}}
   S3 &p = k;                       // expected-note 2 {{'p' defined here}}
   const int &r = da[i];            // expected-note {{'r' defined here}}
   int &q = qa[i];                  // expected-note {{'q' defined here}}
-  float fl;                        // expected-note {{'fl' defined here}}
+  float fl;
 #pragma omp simd reduction // expected-error {{expected '(' after 'reduction'}}
   for (int i = 0; i < 10; ++i)
     foo();
@@ -231,7 +231,7 @@
 #pragma omp simd reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
   for (int i = 0; i < 10; ++i)
     foo();
-#pragma omp simd reduction(+ : a, b, c, d, f) // expected-error {{reduction variable with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}}
+#pragma omp simd reduction(+ : a, b, c, d, f) // expected-error {{reduction variable with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
   for (int i = 0; i < 10; ++i)
     foo();
 #pragma omp simd reduction(min : a, b, c, d, f) // expected-error {{reduction variable with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}}
@@ -249,7 +249,7 @@
 #pragma omp simd reduction(- : da) // expected-error {{a reduction variable with array type 'const int [5]'}}
   for (int i = 0; i < 10; ++i)
     foo();
-#pragma omp simd reduction(^ : fl) // expected-error {{variable of type 'float' is not valid for specified reduction operation}}
+#pragma omp simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
   for (int i = 0; i < 10; ++i)
     foo();
 #pragma omp simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
@@ -258,13 +258,13 @@
 #pragma omp simd reduction(&& : S2::S2sc) // expected-error {{const-qualified variable cannot be reduction}}
   for (int i = 0; i < 10; ++i)
     foo();
-#pragma omp simd reduction(& : e, g) // expected-error {{reduction variable must have an accessible, unambiguous default constructor}} expected-error {{variable of type 'S5' is not valid for specified reduction operation}}
+#pragma omp simd reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
   for (int i = 0; i < 10; ++i)
     foo();
 #pragma omp simd reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
   for (int i = 0; i < 10; ++i)
     foo();
-#pragma omp simd reduction(+ : o) // expected-error {{variable of type 'class S6' is not valid for specified reduction operation}}
+#pragma omp simd reduction(+ : o) // expected-error {{no viable overloaded '='}}
   for (int i = 0; i < 10; ++i)
     foo();
 #pragma omp simd private(i), reduction(+ : j), reduction(+ : q) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}