aboutsummaryrefslogtreecommitdiff
path: root/libgomp/testsuite
diff options
context:
space:
mode:
Diffstat (limited to 'libgomp/testsuite')
-rw-r--r--libgomp/testsuite/libgomp.c++/depend-1.C31
-rw-r--r--libgomp/testsuite/libgomp.c++/depend-iterator-1.C167
-rw-r--r--libgomp/testsuite/libgomp.c++/depobj-1.C103
-rw-r--r--libgomp/testsuite/libgomp.c++/for-16.C218
-rw-r--r--libgomp/testsuite/libgomp.c++/for-21.C291
-rw-r--r--libgomp/testsuite/libgomp.c++/for-22.C314
-rw-r--r--libgomp/testsuite/libgomp.c++/for-23.C416
-rw-r--r--libgomp/testsuite/libgomp.c++/for-24.C427
-rw-r--r--libgomp/testsuite/libgomp.c++/for-25.C420
-rw-r--r--libgomp/testsuite/libgomp.c++/for-26.C422
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-1.C63
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-10.C125
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-11.C237
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-12.C321
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-13.C342
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-14.C72
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-15.C75
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-16.C130
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-17.C300
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-18.C325
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-19.C343
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-2.C119
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-3.C126
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-4.C238
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-5.C320
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-6.C341
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-7.C145
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-8.C70
-rw-r--r--libgomp/testsuite/libgomp.c++/task-reduction-9.C128
-rw-r--r--libgomp/testsuite/libgomp.c++/taskloop-reduction-1.C153
-rw-r--r--libgomp/testsuite/libgomp.c++/taskloop-reduction-2.C253
-rw-r--r--libgomp/testsuite/libgomp.c++/taskloop-reduction-3.C314
-rw-r--r--libgomp/testsuite/libgomp.c++/taskloop-reduction-4.C315
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/cancel-parallel-1.c42
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/cancel-taskgroup-3.c68
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/depend-iterator-1.c115
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/depend-iterator-2.c63
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/depend-mutexinout-1.c28
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/depend-mutexinout-2.c59
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/depobj-1.c99
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/display-affinity-1.c91
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/for-10.c4
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/for-11.c4
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/for-12.c4
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/for-13.c99
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/for-14.c110
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/for-15.c115
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/for-2.h290
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/for-7.c4
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/for-8.c4
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/for-9.c4
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/master-combined-1.c66
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/pause-1.c23
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/pause-2.c41
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/pr66199-10.c60
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/pr66199-11.c38
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/pr66199-12.c60
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/pr66199-13.c64
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/pr66199-14.c39
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/simd-1.c71
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/task-reduction-1.c58
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/task-reduction-11.c56
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/task-reduction-12.c67
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/task-reduction-2.c90
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/task-reduction-3.c218
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/task-reduction-4.c70
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/task-reduction-5.c65
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/task-reduction-6.c125
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/task-reduction-7.c216
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/task-reduction-8.c141
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/task-reduction-9.c217
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-1.c119
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-2.c212
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-3.c45
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-4.c65
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/taskwait-depend-1.c29
-rw-r--r--libgomp/testsuite/libgomp.c/cancel-for-2.c6
-rw-r--r--libgomp/testsuite/libgomp.c/task-reduction-1.c137
-rw-r--r--libgomp/testsuite/libgomp.c/task-reduction-2.c86
-rw-r--r--libgomp/testsuite/libgomp.c/teams-1.c27
-rw-r--r--libgomp/testsuite/libgomp.c/teams-2.c123
-rw-r--r--libgomp/testsuite/libgomp.c/thread-limit-4.c57
-rw-r--r--libgomp/testsuite/libgomp.c/thread-limit-5.c11
-rw-r--r--libgomp/testsuite/libgomp.fortran/display-affinity-1.f9034
84 files changed, 11600 insertions, 3 deletions
diff --git a/libgomp/testsuite/libgomp.c++/depend-1.C b/libgomp/testsuite/libgomp.c++/depend-1.C
new file mode 100644
index 0000000..71a24d1
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/depend-1.C
@@ -0,0 +1,31 @@
+extern "C" void abort ();
+int a, b, c, d, e;
+
+void
+foo (int &x, bool y)
+{
+ #pragma omp task depend (out: x)
+ a = 1;
+ #pragma omp task depend (out: y ? b : c)
+ (y ? b : c) = 2;
+ #pragma omp task depend (inout: --d)
+ d += 4;
+ #pragma omp task depend (in : a, (y ? b : c), d)
+ e = a + b * 10 + c * 100 + d * 1000;
+}
+
+int
+main ()
+{
+ #pragma omp parallel
+ #pragma omp single
+ foo (a, true);
+ if (e != 1 + 20 + 0 + 3000)
+ abort ();
+ a = b = c = d = e = 0;
+ #pragma omp parallel
+ #pragma omp single
+ foo (a, false);
+ if (e != 1 + 0 + 200 + 3000)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/depend-iterator-1.C b/libgomp/testsuite/libgomp.c++/depend-iterator-1.C
new file mode 100644
index 0000000..2cff5e8
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/depend-iterator-1.C
@@ -0,0 +1,167 @@
+extern "C" void abort ();
+int arr[64], arr2[64], arr3[64];
+
+int *
+foo (int x, int y, long z)
+{
+ int v;
+ switch (x)
+ {
+ case 1:
+ if (z != 0 || y < 0 || y >= 64)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = arr2[y];
+ arr2[y]++;
+ }
+ if (v != 0) abort ();
+ return &arr[y];
+ case 2:
+ if (y < 0 || y > 60 || (y & 3) || z < 0 || z >= 4)
+ abort ();
+ #pragma omp atomic
+ arr2[y + z] = arr2[y + z] + 4;
+ return &arr[y + z];
+ case 3:
+ if (z < 0 || z > 60 || (z & 3) || y < 0 || y >= 4)
+ abort ();
+ #pragma omp atomic
+ arr2[y + z] = arr2[y + z] + 16;
+ return &arr[y + z];
+ case 4:
+ if (y != 0 || z > 64 || z <= 0)
+ abort ();
+ #pragma omp atomic
+ arr2[z - 1] = arr2[z - 1] + 64;
+ return &arr[z - 1];
+ case 5:
+ if ((y & 3) != 0 || y < 64 || y >= 96
+ || (z & 127) != 0 || z < 512 || z >= 1024)
+ abort ();
+ y = (y - 64) + (z - 512) / 128;
+ #pragma omp atomic
+ arr2[y] = arr2[y] + 256;
+ return &arr[y];
+ case 6:
+ if ((y & 3) != 0 || y <= 64 || y > 96
+ || (z & 127) != 1 || z <= 513 || z > 1025)
+ abort ();
+ y = (y - 68) + (z - 641) / 128;
+ #pragma omp atomic
+ arr2[y] = arr2[y] + 1024;
+ return &arr[y];
+ default:
+ abort ();
+ }
+}
+
+volatile int beg, end, step, step2;
+volatile unsigned int begu, endu;
+
+template <int N>
+void
+bar ()
+{
+ #pragma omp parallel
+ #pragma omp master
+ {
+ int i;
+ for (i = 0; i < 64; i++)
+ #pragma omp task depend (iterator (j=i:i+1) , out : foo (1, j, 0)[0])
+ arr[i] = i;
+ #pragma omp task depend (iterator (int k=beg:end:step,long int l=0:4:1) , inout : \
+ foo (2, k, l)[0], foo (3, l, k)[0]) private (i)
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i)
+ abort ();
+ else
+ arr[i] = arr[i] + 1;
+ #pragma omp task depend (iterator (int *p=&arr3[64]:&arr3[0]:-1), inout : \
+ foo (4, 0, p - &arr3[0])[0]) depend (in : beg)
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i + 1)
+ abort ();
+ else
+ arr[i] = arr[i] + 2;
+ #pragma omp task depend (iterator (unsigned n=begu:endu:step2, unsigned int o = 512: 1024U: (unsigned char) 128), inout : \
+ foo (5, n + 128, o)[0])
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i + 3)
+ abort ();
+ else
+ arr[i] = arr[i] + 4;
+ #pragma omp task depend (iterator (int unsigned p=endu:begu:step,unsigned q= 1025U:513U:(signed char) -128), in : \
+ foo (6, p + 128, q)[0])
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i + 7)
+ abort ();
+ else
+ arr[i] = arr[i] + 8;
+ }
+}
+
+template <typename A, typename B, typename C, typename D, typename E, typename F>
+void
+baz (A beg, A end, A step, D begu, D endu, A step2)
+{
+ #pragma omp parallel
+ #pragma omp master
+ {
+ int i;
+ for (i = 0; i < 64; i++)
+ #pragma omp task depend (iterator (A j=i:i+1),out : foo (1, j, 0)[0])
+ arr[i] = i;
+ #pragma omp task depend (iterator (A k=beg:end:step,B l=0:4:1), inout : \
+ foo (2, k, l)[0], foo (3, l, k)[0]) private (i)
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i)
+ abort ();
+ else
+ arr[i] = arr[i] + 1;
+ #pragma omp task depend (iterator (C p=&arr3[64]:&arr3[0]:-1), in : \
+ foo (4, 0, p - &arr3[0])[0]) depend (in : beg)
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i + 1)
+ abort ();
+ else
+ arr[i] = arr[i] + 2;
+ #pragma omp task depend (iterator (D n=begu:endu:step2, D o = 512: 1024U:(E) 128), inout : \
+ foo (5, n + 128, o)[0])
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i + 3)
+ abort ();
+ else
+ arr[i] = arr[i] + 4;
+ #pragma omp task depend (iterator (D p=endu:begu:step,D q= 1025U:513U:(F) -128), in : \
+ foo (6, p + 128, q)[0])
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i + 7)
+ abort ();
+ else
+ arr[i] = arr[i] + 8;
+ }
+}
+
+int
+main ()
+{
+ int m;
+ beg = 60;
+ end = -4;
+ step = -4;
+ step2 = 4;
+ begu = -64U;
+ endu = -32U;
+ bar<0> ();
+ for (m = 0; m < 64; m++)
+ if (arr[m] != m + 15 || arr2[m] != (m < 32 ? 1365 : 85))
+ abort ();
+ else
+ arr[m] = arr2[m] = 0;
+ baz<int, long int, int *, unsigned int, unsigned char, signed char> (beg, end, step, begu, endu, step2);
+ for (m = 0; m < 64; m++)
+ if (arr[m] != m + 15 || arr2[m] != (m < 32 ? 1365 : 85))
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/depobj-1.C b/libgomp/testsuite/libgomp.c++/depobj-1.C
new file mode 100644
index 0000000..91edf8c
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/depobj-1.C
@@ -0,0 +1,103 @@
+#include <stdlib.h>
+#include <omp.h>
+
+void
+dep (omp_depend_t &d1, omp_depend_t *d2)
+{
+ int x = 1;
+ #pragma omp depobj (d1) depend(in: x)
+ #pragma omp depobj (*d2) depend(in: x)
+
+ #pragma omp depobj (d2[0]) update(out)
+ #pragma omp parallel
+ #pragma omp single
+ {
+ #pragma omp task shared (x) depend(depobj:*d2)
+ x = 2;
+ #pragma omp task shared (x) depend(depobj : d1)
+ if (x != 2)
+ abort ();
+ }
+ #pragma omp depobj (d2[0]) destroy
+ #pragma omp depobj (d1) destroy
+}
+
+template <typename T>
+void
+dep2 (T &d2)
+{
+ T d1;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ int x = 1;
+ #pragma omp depobj (d1) depend(out: x)
+ #pragma omp depobj (*&d2) depend (in:x)
+ #pragma omp depobj(d2)update(in)
+ #pragma omp task shared (x) depend(depobj :d1)
+ x = 2;
+ #pragma omp task shared (x) depend(depobj: d2)
+ if (x != 2)
+ abort ();
+ #pragma omp taskwait
+ #pragma omp depobj(d1)destroy
+ #pragma omp depobj((&d2)[0]) destroy
+ }
+}
+
+template <typename T>
+void
+dep3 (void)
+{
+ T d[2];
+ #pragma omp parallel
+ {
+ int x = 1;
+ #pragma omp single
+ {
+ #pragma omp depobj(d[0]) depend(out:x)
+ #pragma omp depobj(d[1]) depend(in: x)
+ #pragma omp task shared (x) depend(depobj:*d)
+ x = 2;
+ #pragma omp task shared (x) depend(depobj:*(d + 1))
+ if (x != 2)
+ abort ();
+ }
+ }
+ #pragma omp depobj(d[0]) destroy
+ #pragma omp depobj(d[1]) destroy
+}
+
+int xx;
+omp_depend_t dd1, dd2;
+
+template <int N>
+void
+antidep (void)
+{
+ xx = 1;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ #pragma omp task shared(xx) depend(depobj:dd2)
+ if (xx != 1)
+ abort ();
+ #pragma omp task shared(xx) depend(depobj:dd1)
+ xx = 2;
+ }
+}
+
+int
+main ()
+{
+ omp_depend_t d1, d2, d3;
+ dep (d1, &d2);
+ dep2 <omp_depend_t> (d3);
+ dep3 <omp_depend_t> ();
+ #pragma omp depobj (dd1) depend (inout: xx)
+ #pragma omp depobj (dd2) depend (in : xx)
+ antidep <0> ();
+ #pragma omp depobj (dd2) destroy
+ #pragma omp depobj (dd1) destroy
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/for-16.C b/libgomp/testsuite/libgomp.c++/for-16.C
new file mode 100644
index 0000000..e7e5b85
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/for-16.C
@@ -0,0 +1,218 @@
+// PR c++/86443
+// { dg-do run }
+// { dg-additional-options "-std=c++17" }
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+extern "C" void abort ();
+
+template <typename T>
+class I
+{
+public:
+ typedef ptrdiff_t difference_type;
+ I ();
+ ~I ();
+ I (T *);
+ I (const I &);
+ T &operator * ();
+ T *operator -> ();
+ T &operator [] (const difference_type &) const;
+ I &operator = (const I &);
+ I &operator ++ ();
+ I operator ++ (int);
+ I &operator -- ();
+ I operator -- (int);
+ I &operator += (const difference_type &);
+ I &operator -= (const difference_type &);
+ I operator + (const difference_type &) const;
+ I operator - (const difference_type &) const;
+ template <typename S> friend bool operator == (I<S> &, I<S> &);
+ template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator < (I<S> &, I<S> &);
+ template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator <= (I<S> &, I<S> &);
+ template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator > (I<S> &, I<S> &);
+ template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator >= (I<S> &, I<S> &);
+ template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+ template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+ T *p;
+};
+template <typename T> I<T>::I () : p (0) {}
+template <typename T> I<T>::~I () {}
+template <typename T> I<T>::I (T *x) : p (x) {}
+template <typename T> I<T>::I (const I &x) : p (x.p) {}
+template <typename T> T &I<T>::operator * () { return *p; }
+template <typename T> T *I<T>::operator -> () { return p; }
+template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
+template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
+template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
+template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
+template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
+template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
+template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
+template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
+template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
+template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
+template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
+template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
+template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
+template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
+template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
+template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
+template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
+
+template <typename T>
+class J
+{
+public:
+ J(const I<T> &x, const I<T> &y) : b (x), e (y) {}
+ const I<T> &begin ();
+ const I<T> &end ();
+private:
+ I<T> b, e;
+};
+
+template <typename T> const I<T> &J<T>::begin () { return b; }
+template <typename T> const I<T> &J<T>::end () { return e; }
+
+int results[2000];
+
+template <typename T>
+void
+baz (I<T> &i)
+{
+ if (*i < 0 || *i >= 2000)
+ abort ();
+ results[*i]++;
+}
+
+void
+baz (int i)
+{
+ if (i < 0 || i >= 2000)
+ abort ();
+ results[i]++;
+}
+
+void
+f1 (J<int> j)
+{
+#pragma omp distribute parallel for default(none)
+ for (I<int> i = j.begin (); i < j.end (); i += 3)
+ baz (*i);
+}
+
+void
+f2 (J<int> j)
+{
+ I<int> i;
+#pragma omp distribute parallel for default(none)
+ for (i = j.begin (); i < j.end (); ++i)
+ baz (*i);
+}
+
+template <int N>
+void
+f3 (J<int> j)
+{
+#pragma omp distribute parallel for default(none)
+ for (I<int> i = j.begin (); i < j.end (); i += 6)
+ baz (*i);
+}
+
+template <int N>
+void
+f4 (J<int> j)
+{
+ I<int> i;
+#pragma omp distribute parallel for default(none)
+ for (i = j.begin (); i < j.end (); i += 9)
+ baz (*i);
+}
+
+template <typename T>
+void
+f5 (J<T> j)
+{
+#pragma omp distribute parallel for default(none)
+ for (I<T> i = j.begin (); i < j.end (); i += 4)
+ baz (*i);
+}
+
+template <typename T>
+void
+f6 (J<T> j)
+{
+ I<T> i;
+#pragma omp distribute parallel for default(none)
+ for (i = j.begin (); i < j.end (); i += 7)
+ baz (*i);
+}
+
+#define check(expr) \
+ for (int i = 0; i < 2000; i++) \
+ if (expr) \
+ { \
+ if (results[i] != 1) \
+ abort (); \
+ results[i] = 0; \
+ } \
+ else if (results[i]) \
+ abort ()
+
+int
+main ()
+{
+ int a[2000];
+ for (int i = 0; i < 2000; i++)
+ a[i] = i;
+ #pragma omp teams
+ {
+ J<int> j (&a[75], &a[1945]);
+ f1 (j);
+ }
+ check (i >= 75 && i < 1945 && (i - 75) % 3 == 0);
+ #pragma omp teams
+ {
+ J<int> j (&a[63], &a[1949]);
+ f2 (j);
+ }
+ check (i >= 63 && i < 1949);
+ #pragma omp teams
+ {
+ J<int> j (&a[58], &a[1979]);
+ f3 <2> (j);
+ }
+ check (i >= 58 && i < 1979 && (i - 58) % 6 == 0);
+ #pragma omp teams
+ {
+ J<int> j (&a[59], &a[1981]);
+ f4 <9> (j);
+ }
+ check (i >= 59 && i < 1981 && (i - 59) % 9 == 0);
+ #pragma omp teams
+ {
+ J<int> j (&a[52], &a[1972]);
+ f5 (j);
+ }
+ check (i >= 52 && i < 1972 && (i - 52) % 4 == 0);
+ #pragma omp teams
+ {
+ J<int> j (&a[31], &a[1827]);
+ f6 (j);
+ }
+ check (i >= 31 && i < 1827 && (i - 31) % 7 == 0);
+}
diff --git a/libgomp/testsuite/libgomp.c++/for-21.C b/libgomp/testsuite/libgomp.c++/for-21.C
new file mode 100644
index 0000000..fc0cb0a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/for-21.C
@@ -0,0 +1,291 @@
+// { dg-do run }
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+extern "C" void abort ();
+
+template <typename T>
+class I
+{
+public:
+ typedef ptrdiff_t difference_type;
+ I ();
+ ~I ();
+ I (T *);
+ I (const I &);
+ T &operator * ();
+ T *operator -> ();
+ T &operator [] (const difference_type &) const;
+ I &operator = (const I &);
+ I &operator ++ ();
+ I operator ++ (int);
+ I &operator -- ();
+ I operator -- (int);
+ I &operator += (const difference_type &);
+ I &operator -= (const difference_type &);
+ I operator + (const difference_type &) const;
+ I operator - (const difference_type &) const;
+ template <typename S> friend bool operator == (I<S> &, I<S> &);
+ template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator < (I<S> &, I<S> &);
+ template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator <= (I<S> &, I<S> &);
+ template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator > (I<S> &, I<S> &);
+ template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator >= (I<S> &, I<S> &);
+ template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+ template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+ T *p;
+};
+template <typename T> I<T>::I () : p (0) {}
+template <typename T> I<T>::~I () {}
+template <typename T> I<T>::I (T *x) : p (x) {}
+template <typename T> I<T>::I (const I &x) : p (x.p) {}
+template <typename T> T &I<T>::operator * () { return *p; }
+template <typename T> T *I<T>::operator -> () { return p; }
+template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
+template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
+template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
+template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
+template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
+template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
+template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
+template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
+template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
+template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
+template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
+template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
+template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
+template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
+template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
+template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
+template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
+
+template <typename T>
+class J
+{
+public:
+ J(const I<T> &x, const I<T> &y) : b (x), e (y) {}
+ const I<T> &begin ();
+ const I<T> &end ();
+private:
+ I<T> b, e;
+};
+
+template <typename T> const I<T> &J<T>::begin () { return b; }
+template <typename T> const I<T> &J<T>::end () { return e; }
+
+int results[2000];
+
+template <typename T>
+void
+baz (I<T> &i)
+{
+ if (*i < 0 || *i >= 2000)
+ abort ();
+ results[*i]++;
+}
+
+void
+f1 (const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for
+ for (I<int> i = x; i != y; i++)
+ baz (i);
+}
+
+void
+f2 (const I<int> &x, const I<int> &y)
+{
+ I<int> i;
+#pragma omp parallel for private(i)
+ for (i = x; i != y - 1; i = 2 - 8 + 7 + i)
+ baz (i);
+}
+
+template <typename T>
+void
+f3 (const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for
+ for (I<int> i = x; i != y; i = i + 9 - 8)
+ baz (i);
+}
+
+template <typename T>
+void
+f4 (const I<int> &x, const I<int> &y)
+{
+ I<int> i;
+#pragma omp parallel for lastprivate(i)
+ for (i = x + 2000 - 64; i != y + 10; --i)
+ baz (i);
+}
+
+void
+f5 (const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for
+ for (I<int> i = x + 2000 - 64; i != y + 10; i--)
+ baz (i);
+}
+
+template <int N>
+void
+f6 (const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for
+ for (I<int> i = x + 2000 - 64; i != y + 10; i = i - 12 + 11)
+ {
+ I<int> j = i + N;
+ baz (j);
+ }
+}
+
+template <int N>
+void
+f7 (I<int> i, const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for
+ for (i = x - 10; i != y + 10; i += N)
+ baz (i);
+}
+
+template <int N>
+void
+f8 (J<int> j)
+{
+ I<int> i;
+#pragma omp parallel for
+ for (i = j.begin (); i != j.end () + N; i += 1)
+ baz (i);
+}
+
+template <typename T, int N>
+void
+f9 (const I<T> &x, const I<T> &y)
+{
+#pragma omp parallel for
+ for (I<T> i = x; i != y; i = i - N)
+ baz (i);
+}
+
+template <typename T, int N>
+void
+f10 (const I<T> &x, const I<T> &y)
+{
+ I<T> i;
+#pragma omp parallel for
+ for (i = x; i != y; i = i + N)
+ baz (i);
+}
+
+template <typename T>
+void
+f11 (const T &x, const T &y)
+{
+#pragma omp parallel
+ {
+#pragma omp for nowait
+ for (T i = x; i != y; i++)
+ baz (i);
+#pragma omp single
+ {
+ T j = y + 3;
+ baz (j);
+ }
+ }
+}
+
+template <typename T>
+void
+f12 (const T &x, const T &y)
+{
+ T i;
+#pragma omp parallel for
+ for (i = x; i != y; --i)
+ baz (i);
+}
+
+template <int N>
+struct K
+{
+ template <typename T>
+ static void
+ f13 (const T &x, const T &y)
+ {
+#pragma omp parallel for
+ for (T i = x; i != y + N; i += N)
+ baz (i);
+ }
+};
+
+#define check(expr) \
+ for (int i = 0; i < 2000; i++) \
+ if (expr) \
+ { \
+ if (results[i] != 1) \
+ abort (); \
+ results[i] = 0; \
+ } \
+ else if (results[i]) \
+ abort ()
+
+int
+main ()
+{
+ int a[2000];
+ long b[2000];
+ for (int i = 0; i < 2000; i++)
+ {
+ a[i] = i;
+ b[i] = i;
+ }
+ f1 (&a[10], &a[1990]);
+ check (i >= 10 && i < 1990);
+ f2 (&a[0], &a[1999]);
+ check (i < 1998);
+ f3<char> (&a[20], &a[1837]);
+ check (i >= 20 && i < 1837);
+ f4<int> (&a[0], &a[30]);
+ check (i > 40 && i <= 2000 - 64);
+ f5 (&a[0], &a[100]);
+ check (i > 110 && i <= 2000 - 64);
+ f6<-10> (&a[10], &a[110]);
+ check (i > 110 && i <= 2000 - 64);
+ f7<1> (I<int> (), &a[12], &a[1800]);
+ check (i >= 2 && i < 1810);
+ f8<121> (J<int> (&a[14], &a[1803]));
+ check (i >= 14 && i < 1924);
+ f9<int, -1> (&a[33], &a[1967]);
+ check (i >= 33 && i < 1967);
+ f10<int, -1> (&a[1939], &a[17]);
+ check (i > 17 && i <= 1939);
+ f11<I<int> > (&a[16], &a[1981]);
+ check ((i >= 16 && i < 1981) || i == 1984);
+ f12<I<int> > (&a[1761], &a[37]);
+ check (i > 37 && i <= 1761);
+ K<1>::f13<I<int> > (&a[1], &a[1935]);
+ check (i >= 1 && i < 1936);
+ f9<long, 1 - 2> (&b[33], &b[1967]);
+ check (i >= 33 && i < 1967);
+ f10<long, -1> (&b[1939], &b[17]);
+ check (i > 17 && i <= 1939);
+ f11<I<long> > (&b[16], &b[1981]);
+ check ((i >= 16 && i < 1981) || i == 1984);
+ f12<I<long> > (&b[1761], &b[37]);
+ check (i > 37 && i <= 1761);
+ K<1>::f13<I<long> > (&b[1], &b[1935]);
+ check (i >= 1 && i < 1936);
+}
diff --git a/libgomp/testsuite/libgomp.c++/for-22.C b/libgomp/testsuite/libgomp.c++/for-22.C
new file mode 100644
index 0000000..35fcf1f
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/for-22.C
@@ -0,0 +1,314 @@
+// { dg-do run }
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+extern "C" void abort ();
+
+template <typename T>
+class I
+{
+public:
+ typedef ptrdiff_t difference_type;
+ I ();
+ ~I ();
+ I (T *);
+ I (const I &);
+ T &operator * ();
+ T *operator -> ();
+ T &operator [] (const difference_type &) const;
+ I &operator = (const I &);
+ I &operator ++ ();
+ I operator ++ (int);
+ I &operator -- ();
+ I operator -- (int);
+ I &operator += (const difference_type &);
+ I &operator -= (const difference_type &);
+ I operator + (const difference_type &) const;
+ I operator - (const difference_type &) const;
+ template <typename S> friend bool operator == (I<S> &, I<S> &);
+ template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator < (I<S> &, I<S> &);
+ template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator <= (I<S> &, I<S> &);
+ template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator > (I<S> &, I<S> &);
+ template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator >= (I<S> &, I<S> &);
+ template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+ template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+ T *p;
+};
+template <typename T> I<T>::I () : p (0) {}
+template <typename T> I<T>::~I () { p = (T *) 0; }
+template <typename T> I<T>::I (T *x) : p (x) {}
+template <typename T> I<T>::I (const I &x) : p (x.p) {}
+template <typename T> T &I<T>::operator * () { return *p; }
+template <typename T> T *I<T>::operator -> () { return p; }
+template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
+template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
+template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
+template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
+template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
+template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
+template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
+template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
+template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
+template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
+template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
+template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
+template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
+template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
+template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
+template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
+template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
+
+template <typename T>
+class J
+{
+public:
+ J(const I<T> &x, const I<T> &y) : b (x), e (y) {}
+ const I<T> &begin ();
+ const I<T> &end ();
+private:
+ I<T> b, e;
+};
+
+template <typename T> const I<T> &J<T>::begin () { return b; }
+template <typename T> const I<T> &J<T>::end () { return e; }
+
+int results[2000];
+
+template <typename T>
+void
+baz (I<T> &i)
+{
+ if (*i < 0 || *i >= 2000)
+ abort ();
+ results[*i]++;
+}
+
+I<int>
+f1 (const I<int> &x, const I<int> &y)
+{
+ I<int> i;
+#pragma omp parallel shared(i)
+ {
+#pragma omp for lastprivate (i) schedule(runtime)
+ for (i = x; i != y; i++)
+ baz (i);
+#pragma omp single
+ i += 3;
+ }
+ return I<int> (i);
+}
+
+I<int>
+f2 (const I<int> &x, const I<int> &y)
+{
+ I<int> i;
+#pragma omp parallel for lastprivate(i)
+ for (i = x; i != y - 1; i = 2 - 8 + 7 + i)
+ baz (i);
+ return I<int> (i);
+}
+
+template <typename T>
+I<int>
+f3 (const I<int> &x, const I<int> &y)
+{
+ I<int> i;
+#pragma omp parallel
+ #pragma omp for lastprivate (i)
+ for (i = x; i != y; i = i + 9 - 8)
+ baz (i);
+ return i;
+}
+
+template <typename T>
+I<int>
+f4 (const I<int> &x, const I<int> &y)
+{
+ I<int> i;
+#pragma omp parallel for lastprivate(i)
+ for (i = x + 2000 - 64; i != y + 10; --i)
+ baz (i);
+ return I<int> (i);
+}
+
+template <typename T>
+I<int>
+f5 (const I<int> &x, const I<int> &y)
+{
+ I<int> i;
+#pragma omp parallel for lastprivate(i)
+ for (i = x + 2000 - 64; i != y + T (10); i--)
+ baz (i);
+ return i;
+}
+
+template <typename T>
+I<int>
+f6 (const I<int> &x, const I<int> &y)
+{
+ I<int> i;
+#pragma omp parallel for lastprivate (i)
+ for (i = x + 2000 - 64; i != y + 10; i = i - T (12) + T (11))
+ {
+ I<int> j = i + -10;
+ baz (j);
+ }
+ return I<int> (i);
+}
+
+template <int N>
+I<int>
+f7 (I<int> i, const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for lastprivate(i)
+ for (i = x - 10; i != y + 10; i += N)
+ baz (i);
+ return I<int> (i);
+}
+
+template <int N>
+I<int>
+f8 (J<int> j)
+{
+ I<int> i;
+#pragma omp parallel shared \
+(i)
+#pragma omp for lastprivate (i)
+ for (i = j.begin (); i != j.end () + N; i += 1)
+ baz (i);
+ return i;
+}
+
+I<int> i9;
+
+template <long N>
+I<int> &
+f9 (J<int> j)
+{
+#pragma omp parallel for lastprivate(i9)
+ for (i9 = j.begin (); i9 != j.end () - N; i9 = i9 - N)
+ baz (i9);
+ return i9;
+}
+
+template <typename T, int N>
+I<T>
+f10 (const I<T> &x, const I<T> &y)
+{
+ I<T> i;
+#pragma omp parallel for lastprivate (i)
+ for (i = x; i != y; i = i + N)
+ baz (i);
+ return i;
+}
+
+template <typename T, typename U>
+T
+f11 (T i, const T &x, const T &y)
+{
+#pragma omp parallel
+ {
+#pragma omp for lastprivate (i)
+ for (i = x + U (0); i != y + U (2 - 2); i = U(3) + U(-2) + i)
+ baz (i);
+#pragma omp single
+ {
+ T j = y + 3;
+ baz (j);
+ }
+ }
+ return i;
+}
+
+template <typename T>
+T
+f12 (const T &x, const T &y)
+{
+ T i;
+#pragma omp parallel for lastprivate (i)
+ for (i = x; i != y; --i)
+ baz (i);
+ return i;
+}
+
+#define check(expr) \
+ for (int i = 0; i < 2000; i++) \
+ if (expr) \
+ { \
+ if (results[i] != 1) \
+ abort (); \
+ results[i] = 0; \
+ } \
+ else if (results[i]) \
+ abort ()
+
+int
+main ()
+{
+ int a[2000];
+ long b[2000];
+ for (int i = 0; i < 2000; i++)
+ {
+ a[i] = i;
+ b[i] = i;
+ }
+ if (*f1 (&a[10], &a[1990]) != 1993)
+ abort ();
+ check (i >= 10 && i < 1990);
+ if (*f2 (&a[0], &a[1999]) != 1998)
+ abort ();
+ check (i < 1998);
+ if (*f3<char> (&a[20], &a[1837]) != 1837)
+ abort ();
+ check (i >= 20 && i < 1837);
+ if (*f4<int> (&a[0], &a[30]) != 40)
+ abort ();
+ check (i > 40 && i <= 2000 - 64);
+ if (*f5<int> (&a[0], &a[100]) != 110)
+ abort ();
+ check (i > 110 && i <= 2000 - 64);
+ if (*f6<int> (&a[10], &a[110]) != 120)
+ abort ();
+ check (i > 110 && i <= 2000 - 64);
+ if (*f7<1> (I<int> (), &a[12], &a[1800]) != 1810)
+ abort ();
+ check (i >= 2 && i < 1810);
+ if (*f8<121> (J<int> (&a[14], &a[1803])) != 1924)
+ abort ();
+ check (i >= 14 && i < 1924);
+ if (*f9<-1> (J<int> (&a[33], &a[1967])) != 1968)
+ abort ();
+ check (i >= 33 && i <= 1967);
+ if (*f10<int, -1> (&a[1939], &a[17]) != 17)
+ abort ();
+ check (i > 17 && i <= 1939);
+ if (*f11<I<int>, int> (I<int> (), &a[16], &a[1981]) != 1981)
+ abort ();
+ check ((i >= 16 && i < 1981) || i == 1984);
+ if (*f12<I<int> > (&a[1761], &a[37]) != 37)
+ abort ();
+ check (i > 37 && i <= 1761);
+ if (*f10<long, -1> (&b[1939], &b[17]) != 17)
+ abort ();
+ check (i > 17 && i <= 1939);
+ if (*f11<I<long>, long> (I<long> (), &b[16], &b[1981]) != 1981)
+ abort ();
+ check ((i >= 16 && i < 1981) || i == 1984);
+ if (*f12<I<long> > (&b[1761], &b[37]) != 37)
+ abort ();
+ check (i > 37 && i <= 1761);
+}
diff --git a/libgomp/testsuite/libgomp.c++/for-23.C b/libgomp/testsuite/libgomp.c++/for-23.C
new file mode 100644
index 0000000..e0d7b7a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/for-23.C
@@ -0,0 +1,416 @@
+// { dg-do run }
+// { dg-additional-options "-std=c++17" }
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+extern "C" void abort ();
+
+namespace std {
+ template<typename T> struct tuple_size;
+ template<int, typename> struct tuple_element;
+}
+
+template <typename T>
+class I
+{
+public:
+ typedef ptrdiff_t difference_type;
+ I ();
+ ~I ();
+ I (T *);
+ I (const I &);
+ T &operator * ();
+ T *operator -> ();
+ T &operator [] (const difference_type &) const;
+ I &operator = (const I &);
+ I &operator ++ ();
+ I operator ++ (int);
+ I &operator -- ();
+ I operator -- (int);
+ I &operator += (const difference_type &);
+ I &operator -= (const difference_type &);
+ I operator + (const difference_type &) const;
+ I operator - (const difference_type &) const;
+ template <typename S> friend bool operator == (I<S> &, I<S> &);
+ template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator < (I<S> &, I<S> &);
+ template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator <= (I<S> &, I<S> &);
+ template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator > (I<S> &, I<S> &);
+ template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator >= (I<S> &, I<S> &);
+ template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+ template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+ T *p;
+};
+template <typename T> I<T>::I () : p (0) {}
+template <typename T> I<T>::~I () {}
+template <typename T> I<T>::I (T *x) : p (x) {}
+template <typename T> I<T>::I (const I &x) : p (x.p) {}
+template <typename T> T &I<T>::operator * () { return *p; }
+template <typename T> T *I<T>::operator -> () { return p; }
+template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
+template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
+template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
+template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
+template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
+template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
+template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
+template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
+template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
+template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
+template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
+template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
+template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
+template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
+template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
+template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
+template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
+
+template <typename T>
+class J
+{
+public:
+ J(const I<T> &x, const I<T> &y) : b (x), e (y) {}
+ const I<T> &begin ();
+ const I<T> &end ();
+private:
+ I<T> b, e;
+};
+
+template <typename T> const I<T> &J<T>::begin () { return b; }
+template <typename T> const I<T> &J<T>::end () { return e; }
+
+template <typename T>
+class K
+{
+public:
+ K ();
+ ~K ();
+ template <int N> T &get () { if (N == 0) return c; else if (N == 1) return b; return a; }
+ T a, b, c;
+};
+
+template <typename T> K<T>::K () : a {}, b {}, c {} {}
+template <typename T> K<T>::~K () {}
+template <typename T> struct std::tuple_size<K<T>> { static constexpr int value = 3; };
+template <typename T, int N> struct std::tuple_element<N, K<T>> { using type = T; };
+
+template <typename T>
+class L
+{
+public:
+ L ();
+ ~L ();
+ T a, b, c;
+};
+
+template <typename T> L<T>::L () : a {}, b {}, c {} {}
+template <typename T> L<T>::~L () {}
+
+int a[2000];
+long b[40];
+short c[50];
+int d[1024];
+K<int> e[1089];
+L<int> f[1093];
+int results[2000];
+
+template <typename T>
+void
+baz (I<T> &i)
+{
+ if (*i < 0 || *i >= 2000)
+ abort ();
+ results[*i]++;
+}
+
+void
+baz (int i)
+{
+ if (i < 0 || i >= 2000)
+ abort ();
+ results[i]++;
+}
+
+void
+f1 ()
+{
+#pragma omp parallel for default(none) shared(a)
+ for (auto i : a)
+ baz (i);
+}
+
+void
+f2 ()
+{
+#pragma omp parallel for default(none) shared(a)
+ for (auto &i : a)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+void
+f3 ()
+{
+#pragma omp parallel for collapse(3) default(none) shared(b, c)
+ for (auto &i : b)
+ for (int j = 9; j < 10; j++)
+ for (auto k : c)
+ if (&i != &b[i] || i < 0 || i >= 40 || j != 9 || k < 0 || k >= 50)
+ abort ();
+ else
+ baz (i * 50 + k);
+}
+
+void
+f4 (J<int> j)
+{
+#pragma omp parallel for default(none) shared(j, a)
+ for (auto &i : j)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+void
+f5 ()
+{
+#pragma omp parallel for simd default(none) shared(d, results)
+ for (auto i : d)
+ results[i % 1024] += 2 * ((unsigned) i >> 10) + 1;
+}
+
+void
+f6 (J<K<int>> j)
+{
+#pragma omp parallel for default(none) shared(j, e)
+ for (auto & [k, l, m] : j)
+ if (&k != &e[m].c || &l != &e[m].b || &m != &e[m].a || k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+void
+f7 (J<L<int>> j)
+{
+#pragma omp parallel for default(none) shared(j, f)
+ for (auto & [k, l, m] : j)
+ if (&k != &f[k].a || &l != &f[k].b || &m != &f[k].c || l != k * 4 || m != k * 5)
+ abort ();
+ else
+ baz (k);
+}
+
+void
+f8 (J<K<int>> j)
+{
+#pragma omp parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+void
+f9 (J<L<int>> j)
+{
+#pragma omp parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (l != k * 4 || m != k * 5)
+ abort ();
+ else
+ baz (k);
+}
+
+template <int N>
+void
+f10 ()
+{
+#pragma omp parallel for default(none) shared(a)
+ for (auto i : a)
+ baz (i);
+}
+
+template <int N>
+void
+f11 ()
+{
+#pragma omp parallel for default(none) shared(a)
+ for (auto &i : a)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+template <int N>
+void
+f12 ()
+{
+#pragma omp parallel for collapse(3) default(none) shared(a, b, c)
+ for (auto &i : b)
+ for (I<int> j = I<int> (&a[9]); j < I<int> (&a[10]); j++)
+ for (auto k : c)
+ if (&i != &b[i] || i < 0 || i >= 40 || *j != 9 || k < 0 || k >= 50)
+ abort ();
+ else
+ baz (i * 50 + k);
+}
+
+template <typename T>
+void
+f13 (J<T> j)
+{
+#pragma omp parallel for default(none) shared(j, a)
+ for (auto &i : j)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+template <int N>
+void
+f14 ()
+{
+#pragma omp parallel for simd default(none) shared(d, results)
+ for (auto i : d)
+ results[i % N] += 2 * ((unsigned) i >> 10) + 1;
+}
+
+template <typename T>
+void
+f15 (J<K<T>> j)
+{
+#pragma omp parallel for default(none) shared(j, e)
+ for (auto & [k, l, m] : j)
+ if (&k != &e[m].c || &l != &e[m].b || &m != &e[m].a || k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+template <typename T>
+void
+f16 (J<L<T>> j)
+{
+#pragma omp parallel for default(none) shared(j, f)
+ for (auto & [k, l, m] : j)
+ if (&k != &f[k].a || &l != &f[k].b || &m != &f[k].c || l != k * 4 || m != k * 5)
+ abort ();
+ else
+ baz (k);
+}
+
+template <int N>
+void
+f17 (J<K<int>> j)
+{
+#pragma omp parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+template <int N>
+void
+f18 (J<L<int>> j)
+{
+#pragma omp parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (l != k * 4 || m != k * 5)
+ abort ();
+ else
+ baz (k);
+}
+
+#define check(expr) \
+ for (int i = 0; i < 2000; i++) \
+ if (expr) \
+ { \
+ if (results[i] != 1) \
+ abort (); \
+ results[i] = 0; \
+ } \
+ else if (results[i]) \
+ abort ()
+
+int
+main ()
+{
+ for (int i = 0; i < 2000; i++)
+ a[i] = i;
+ for (int i = 0; i < 40; i++)
+ b[i] = i;
+ for (int i = 0; i < 50; i++)
+ c[i] = i;
+ for (int i = 0; i < 1024; i++)
+ d[i] = i;
+ for (int i = 0; i < 1089; i++)
+ {
+ e[i].a = i;
+ e[i].b = 2 * i;
+ e[i].c = 3 * i;
+ }
+ for (int i = 0; i < 1093; i++)
+ {
+ f[i].a = i;
+ f[i].b = 4 * i;
+ f[i].c = 5 * i;
+ }
+ f1 ();
+ check (1);
+ f2 ();
+ check (1);
+ f3 ();
+ check (1);
+ f4 (J<int> (&a[14], &a[1803]));
+ check (i >= 14 && i < 1803);
+ f5 ();
+ check (i >= 0 && i < 1024);
+ f6 (J<K<int>> (&e[19], &e[1029]));
+ check (i >= 19 && i < 1029);
+ f7 (J<L<int>> (&f[15], &f[1091]));
+ check (i >= 15 && i < 1091);
+ f8 (J<K<int>> (&e[27], &e[1037]));
+ check (i >= 27 && i < 1037);
+ f9 (J<L<int>> (&f[1], &f[1012]));
+ check (i >= 1 && i < 1012);
+ f10 <0> ();
+ check (1);
+ f11 <1> ();
+ check (1);
+ f12 <2> ();
+ check (1);
+ f13 (J<int> (&a[24], &a[1703]));
+ check (i >= 24 && i < 1703);
+ f14 <1024> ();
+ check (i >= 0 && i < 1024);
+ f15 (J<K<int>> (&e[39], &e[929]));
+ check (i >= 39 && i < 929);
+ f16 (J<L<int>> (&f[17], &f[1071]));
+ check (i >= 17 && i < 1071);
+ f17 <3> (J<K<int>> (&e[7], &e[1017]));
+ check (i >= 7 && i < 1017);
+ f18 <5> (J<L<int>> (&f[121], &f[1010]));
+ check (i >= 121 && i < 1010);
+}
diff --git a/libgomp/testsuite/libgomp.c++/for-24.C b/libgomp/testsuite/libgomp.c++/for-24.C
new file mode 100644
index 0000000..cb14add
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/for-24.C
@@ -0,0 +1,427 @@
+// { dg-do run }
+// { dg-additional-options "-std=c++17" }
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+extern "C" void abort ();
+
+namespace std {
+ template<typename T> struct tuple_size;
+ template<int, typename> struct tuple_element;
+}
+
+#pragma omp declare target
+template <typename T>
+class I
+{
+public:
+ typedef ptrdiff_t difference_type;
+ I ();
+ ~I ();
+ I (T *);
+ I (const I &);
+ T &operator * ();
+ T *operator -> ();
+ T &operator [] (const difference_type &) const;
+ I &operator = (const I &);
+ I &operator ++ ();
+ I operator ++ (int);
+ I &operator -- ();
+ I operator -- (int);
+ I &operator += (const difference_type &);
+ I &operator -= (const difference_type &);
+ I operator + (const difference_type &) const;
+ I operator - (const difference_type &) const;
+ template <typename S> friend bool operator == (I<S> &, I<S> &);
+ template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator < (I<S> &, I<S> &);
+ template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator <= (I<S> &, I<S> &);
+ template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator > (I<S> &, I<S> &);
+ template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator >= (I<S> &, I<S> &);
+ template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+ template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+ T *p;
+};
+template <typename T> I<T>::I () : p (0) {}
+template <typename T> I<T>::~I () {}
+template <typename T> I<T>::I (T *x) : p (x) {}
+template <typename T> I<T>::I (const I &x) : p (x.p) {}
+template <typename T> T &I<T>::operator * () { return *p; }
+template <typename T> T *I<T>::operator -> () { return p; }
+template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
+template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
+template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
+template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
+template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
+template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
+template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
+template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
+template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
+template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
+template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
+template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
+template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
+template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
+template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
+template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
+template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
+
+template <typename T>
+class J
+{
+public:
+ J(const I<T> &x, const I<T> &y) : b (x), e (y) {}
+ const I<T> &begin ();
+ const I<T> &end ();
+private:
+ I<T> b, e;
+};
+
+template <typename T> const I<T> &J<T>::begin () { return b; }
+template <typename T> const I<T> &J<T>::end () { return e; }
+
+struct K
+{
+ template <int N> int &get () { if (N == 0) return c; else if (N == 1) return b; return a; }
+ int a, b, c;
+};
+
+template <> struct std::tuple_size<K> { static constexpr int value = 3; };
+template <int N> struct std::tuple_element<N, K> { using type = int; };
+
+struct L
+{
+ int a, b, c;
+};
+
+int a[2000];
+long b[40];
+short c[50];
+int d[1024];
+K e[1089];
+L f[1093];
+#pragma omp end declare target
+
+int results[2000];
+
+#pragma omp declare target
+template <typename T>
+void
+baz (I<T> &i)
+{
+ if (*i < 0 || *i >= 2000)
+ abort ();
+ results[*i]++;
+}
+
+void
+baz (int i)
+{
+ if (i < 0 || i >= 2000)
+ abort ();
+ results[i]++;
+}
+
+void
+f1 ()
+{
+#pragma omp distribute parallel for default(none) shared(a)
+ for (auto i : a)
+ baz (i);
+}
+
+void
+f2 ()
+{
+#pragma omp distribute parallel for default(none) shared(a)
+ for (auto &i : a)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+void
+f3 ()
+{
+#pragma omp distribute parallel for collapse(3) default(none) shared(b, c)
+ for (auto &i : b)
+ for (int j = 9; j < 10; j++)
+ for (auto k : c)
+ if (&i != &b[i] || i < 0 || i >= 40 || j != 9 || k < 0 || k >= 50)
+ abort ();
+ else
+ baz (i * 50 + k);
+}
+
+void
+f4 (J<int> j)
+{
+#pragma omp distribute parallel for default(none) shared(j, a)
+ for (auto &i : j)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+void
+f5 ()
+{
+#pragma omp distribute parallel for simd default(none) shared(d, results)
+ for (auto i : d)
+ results[i % 1024] += 2 * ((unsigned) i >> 10) + 1;
+}
+
+void
+f6 (J<K> j)
+{
+#pragma omp distribute parallel for default(none) shared(j, e)
+ for (auto & [k, l, m] : j)
+ if (&k != &e[m].c || &l != &e[m].b || &m != &e[m].a || k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+void
+f7 (J<L> j)
+{
+#pragma omp distribute parallel for default(none) shared(j, f)
+ for (auto & [k, l, m] : j)
+ if (&k != &f[k].a || &l != &f[k].b || &m != &f[k].c || l != k * 4 || m != k * 5)
+ abort ();
+ else
+ baz (k);
+}
+
+void
+f8 (J<K> j)
+{
+#pragma omp distribute parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+void
+f9 (J<L> j)
+{
+#pragma omp distribute parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (l != k * 4 || m != k * 5)
+ abort ();
+ else
+ baz (k);
+}
+
+template <int N>
+void
+f10 ()
+{
+#pragma omp distribute parallel for default(none) shared(a)
+ for (auto i : a)
+ baz (i);
+}
+
+template <int N>
+void
+f11 ()
+{
+#pragma omp distribute parallel for default(none) shared(a)
+ for (auto &i : a)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+template <int N>
+void
+f12 ()
+{
+#pragma omp distribute parallel for collapse(3) default(none) shared(a, b, c)
+ for (auto &i : b)
+ for (I<int> j = I<int> (&a[9]); j < I<int> (&a[10]); j++)
+ for (auto k : c)
+ if (&i != &b[i] || i < 0 || i >= 40 || *j != 9 || k < 0 || k >= 50)
+ abort ();
+ else
+ baz (i * 50 + k);
+}
+
+template <typename T>
+void
+f13 (J<T> j)
+{
+#pragma omp distribute parallel for default(none) shared(j, a)
+ for (auto &i : j)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+template <int N>
+void
+f14 ()
+{
+#pragma omp distribute parallel for simd default(none) shared(d, results)
+ for (auto i : d)
+ results[i % N] += 2 * ((unsigned) i >> 10) + 1;
+}
+
+template <typename T>
+void
+f15 (J<T> j)
+{
+#pragma omp distribute parallel for default(none) shared(j, e)
+ for (auto & [k, l, m] : j)
+ if (&k != &e[m].c || &l != &e[m].b || &m != &e[m].a || k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+template <typename T>
+void
+f16 (J<T> j)
+{
+#pragma omp distribute parallel for default(none) shared(j, f)
+ for (auto & [k, l, m] : j)
+ if (&k != &f[k].a || &l != &f[k].b || &m != &f[k].c || l != k * 4 || m != k * 5)
+ abort ();
+ else
+ baz (k);
+}
+
+template <int N>
+void
+f17 (J<K> j)
+{
+#pragma omp distribute parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+template <int N>
+void
+f18 (J<L> j)
+{
+#pragma omp distribute parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (l != k * 4 || m != k * 5)
+ abort ();
+ else
+ baz (k);
+}
+#pragma omp end declare target
+
+#define check(expr) \
+ for (int i = 0; i < 2000; i++) \
+ if (expr) \
+ { \
+ if (results[i] != 1) \
+ abort (); \
+ results[i] = 0; \
+ } \
+ else if (results[i]) \
+ abort ()
+
+int
+main ()
+{
+ for (int i = 0; i < 2000; i++)
+ a[i] = i;
+ for (int i = 0; i < 40; i++)
+ b[i] = i;
+ for (int i = 0; i < 50; i++)
+ c[i] = i;
+ for (int i = 0; i < 1024; i++)
+ d[i] = i;
+ for (int i = 0; i < 1089; i++)
+ {
+ e[i].a = i;
+ e[i].b = 2 * i;
+ e[i].c = 3 * i;
+ }
+ for (int i = 0; i < 1093; i++)
+ {
+ f[i].a = i;
+ f[i].b = 4 * i;
+ f[i].c = 5 * i;
+ }
+ #pragma omp target update to (a, b, c, d, e, f)
+ #pragma omp target teams map (tofrom: results)
+ f1 ();
+ check (1);
+ #pragma omp target teams map (tofrom: results)
+ f2 ();
+ check (1);
+ #pragma omp target teams map (tofrom: results)
+ f3 ();
+ check (1);
+ #pragma omp target teams map (tofrom: results)
+ f4 (J<int> (&a[14], &a[1803]));
+ check (i >= 14 && i < 1803);
+ #pragma omp target teams map (tofrom: results)
+ f5 ();
+ check (i >= 0 && i < 1024);
+ #pragma omp target teams map (tofrom: results)
+ f6 (J<K> (&e[19], &e[1029]));
+ check (i >= 19 && i < 1029);
+ #pragma omp target teams map (tofrom: results)
+ f7 (J<L> (&f[15], &f[1091]));
+ check (i >= 15 && i < 1091);
+ #pragma omp target teams map (tofrom: results)
+ f8 (J<K> (&e[27], &e[1037]));
+ check (i >= 27 && i < 1037);
+ #pragma omp target teams map (tofrom: results)
+ f9 (J<L> (&f[1], &f[1012]));
+ check (i >= 1 && i < 1012);
+ #pragma omp target teams map (tofrom: results)
+ f10 <0> ();
+ check (1);
+ #pragma omp target teams map (tofrom: results)
+ f11 <1> ();
+ check (1);
+ #pragma omp target teams map (tofrom: results)
+ f12 <2> ();
+ check (1);
+ #pragma omp target teams map (tofrom: results)
+ f13 (J<int> (&a[24], &a[1703]));
+ check (i >= 24 && i < 1703);
+ #pragma omp target teams map (tofrom: results)
+ f14 <1024> ();
+ check (i >= 0 && i < 1024);
+ #pragma omp target teams map (tofrom: results)
+ f15 (J<K> (&e[39], &e[929]));
+ check (i >= 39 && i < 929);
+ #pragma omp target teams map (tofrom: results)
+ f16 (J<L> (&f[17], &f[1071]));
+ check (i >= 17 && i < 1071);
+ #pragma omp target teams map (tofrom: results)
+ f17 <3> (J<K> (&e[7], &e[1017]));
+ check (i >= 7 && i < 1017);
+ #pragma omp target teams map (tofrom: results)
+ f18 <5> (J<L> (&f[121], &f[1010]));
+ check (i >= 121 && i < 1010);
+}
diff --git a/libgomp/testsuite/libgomp.c++/for-25.C b/libgomp/testsuite/libgomp.c++/for-25.C
new file mode 100644
index 0000000..3fecb48
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/for-25.C
@@ -0,0 +1,420 @@
+// { dg-do run }
+// { dg-additional-options "-std=c++17" }
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+extern "C" void abort ();
+
+namespace std {
+ template<typename T> struct tuple_size;
+ template<int, typename> struct tuple_element;
+}
+
+template <typename T>
+class I
+{
+public:
+ typedef ptrdiff_t difference_type;
+ I ();
+ ~I ();
+ I (T *);
+ I (const I &);
+ T &operator * ();
+ T *operator -> ();
+ T &operator [] (const difference_type &) const;
+ I &operator = (const I &);
+ I &operator ++ ();
+ I operator ++ (int);
+ I &operator -- ();
+ I operator -- (int);
+ I &operator += (const difference_type &);
+ I &operator -= (const difference_type &);
+ I operator + (const difference_type &) const;
+ I operator - (const difference_type &) const;
+ template <typename S> friend bool operator == (I<S> &, I<S> &);
+ template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator < (I<S> &, I<S> &);
+ template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator <= (I<S> &, I<S> &);
+ template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator > (I<S> &, I<S> &);
+ template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator >= (I<S> &, I<S> &);
+ template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+ template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+ T *p;
+};
+template <typename T> I<T>::I () : p (0) {}
+template <typename T> I<T>::~I () {}
+template <typename T> I<T>::I (T *x) : p (x) {}
+template <typename T> I<T>::I (const I &x) : p (x.p) {}
+template <typename T> T &I<T>::operator * () { return *p; }
+template <typename T> T *I<T>::operator -> () { return p; }
+template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
+template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
+template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
+template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
+template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
+template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
+template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
+template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
+template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
+template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
+template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
+template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
+template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
+template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
+template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
+template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
+template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
+
+template <typename T>
+class J
+{
+public:
+ J(const I<T> &x, const I<T> &y) : b (x), e (y) {}
+ const I<T> &begin ();
+ const I<T> &end ();
+private:
+ I<T> b, e;
+};
+
+template <typename T> const I<T> &J<T>::begin () { return b; }
+template <typename T> const I<T> &J<T>::end () { return e; }
+
+template <typename T>
+class K
+{
+public:
+ K ();
+ ~K ();
+ template <int N> T &get () { if (N == 0) return c; else if (N == 1) return b; return a; }
+ T a, b, c;
+};
+
+template <typename T> K<T>::K () : a {}, b {}, c {} {}
+template <typename T> K<T>::~K () {}
+template <typename T> struct std::tuple_size<K<T>> { static constexpr int value = 3; };
+template <typename T, int N> struct std::tuple_element<N, K<T>> { using type = T; };
+
+template <typename T>
+class L
+{
+public:
+ L ();
+ ~L ();
+ T a, b, c;
+};
+
+template <typename T> L<T>::L () : a {}, b {}, c {} {}
+template <typename T> L<T>::~L () {}
+
+int a[2000];
+long b[40];
+short c[50];
+int d[1024];
+K<int> e[1089];
+L<int> f[1093];
+int results[2000];
+
+template <typename T>
+void
+baz (I<T> &i)
+{
+ if (*i < 0 || *i >= 2000)
+ abort ();
+ results[*i]++;
+}
+
+void
+baz (int i)
+{
+ if (i < 0 || i >= 2000)
+ abort ();
+ results[i]++;
+}
+
+void
+f1 ()
+{
+#pragma omp taskloop default(none) shared(a)
+ for (auto i : a)
+ baz (i);
+}
+
+void
+f2 ()
+{
+#pragma omp taskloop default(none) shared(a)
+ for (auto &i : a)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+void
+f3 ()
+{
+#pragma omp taskloop collapse(3) default(none) shared(b, c)
+ for (auto &i : b)
+ for (int j = 9; j < 10; j++)
+ for (auto k : c)
+ if (&i != &b[i] || i < 0 || i >= 40 || j != 9 || k < 0 || k >= 50)
+ abort ();
+ else
+ baz (i * 50 + k);
+}
+
+void
+f4 (J<int> j)
+{
+#pragma omp taskloop default(none) shared(j, a)
+ for (auto &i : j)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+void
+f5 ()
+{
+#pragma omp taskloop simd default(none) shared(d, results)
+ for (auto i : d)
+ results[i % 1024] += 2 * ((unsigned) i >> 10) + 1;
+}
+
+void
+f6 (J<K<int>> j)
+{
+#pragma omp taskloop default(none) shared(j, e)
+ for (auto & [k, l, m] : j)
+ if (&k != &e[m].c || &l != &e[m].b || &m != &e[m].a || k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+void
+f7 (J<L<int>> j)
+{
+#pragma omp taskloop default(none) shared(j, f)
+ for (auto & [k, l, m] : j)
+ if (&k != &f[k].a || &l != &f[k].b || &m != &f[k].c || l != k * 4 || m != k * 5)
+ abort ();
+ else
+ baz (k);
+}
+
+void
+f8 (J<K<int>> j)
+{
+#pragma omp taskloop default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+void
+f9 (J<L<int>> j)
+{
+#pragma omp taskloop default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (l != k * 4 || m != k * 5)
+ abort ();
+ else
+ baz (k);
+}
+
+template <int N>
+void
+f10 ()
+{
+#pragma omp taskloop default(none) shared(a)
+ for (auto i : a)
+ baz (i);
+}
+
+template <int N>
+void
+f11 ()
+{
+#pragma omp taskloop default(none) shared(a)
+ for (auto &i : a)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+template <int N>
+void
+f12 ()
+{
+#pragma omp taskloop collapse(3) default(none) shared(a, b, c)
+ for (auto &i : b)
+ for (I<int> j = I<int> (&a[9]); j < I<int> (&a[10]); j++)
+ for (auto k : c)
+ if (&i != &b[i] || i < 0 || i >= 40 || *j != 9 || k < 0 || k >= 50)
+ abort ();
+ else
+ baz (i * 50 + k);
+}
+
+template <typename T>
+void
+f13 (J<T> j)
+{
+#pragma omp taskloop default(none) shared(j, a)
+ for (auto &i : j)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+template <int N>
+void
+f14 ()
+{
+#pragma omp taskloop simd default(none) shared(d, results)
+ for (auto i : d)
+ results[i % N] += 2 * ((unsigned) i >> 10) + 1;
+}
+
+template <typename T>
+void
+f15 (J<K<T>> j)
+{
+#pragma omp taskloop default(none) shared(j, e)
+ for (auto & [k, l, m] : j)
+ if (&k != &e[m].c || &l != &e[m].b || &m != &e[m].a || k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+template <typename T>
+void
+f16 (J<L<T>> j)
+{
+#pragma omp taskloop default(none) shared(j, f)
+ for (auto & [k, l, m] : j)
+ if (&k != &f[k].a || &l != &f[k].b || &m != &f[k].c || l != k * 4 || m != k * 5)
+ abort ();
+ else
+ baz (k);
+}
+
+template <int N>
+void
+f17 (J<K<int>> j)
+{
+#pragma omp taskloop default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+template <int N>
+void
+f18 (J<L<int>> j)
+{
+#pragma omp taskloop default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (l != k * 4 || m != k * 5)
+ abort ();
+ else
+ baz (k);
+}
+
+#define check(expr) \
+ for (int i = 0; i < 2000; i++) \
+ if (expr) \
+ { \
+ if (results[i] != 1) \
+ abort (); \
+ results[i] = 0; \
+ } \
+ else if (results[i]) \
+ abort ()
+
+int
+main ()
+{
+ for (int i = 0; i < 2000; i++)
+ a[i] = i;
+ for (int i = 0; i < 40; i++)
+ b[i] = i;
+ for (int i = 0; i < 50; i++)
+ c[i] = i;
+ for (int i = 0; i < 1024; i++)
+ d[i] = i;
+ for (int i = 0; i < 1089; i++)
+ {
+ e[i].a = i;
+ e[i].b = 2 * i;
+ e[i].c = 3 * i;
+ }
+ for (int i = 0; i < 1093; i++)
+ {
+ f[i].a = i;
+ f[i].b = 4 * i;
+ f[i].c = 5 * i;
+ }
+ #pragma omp parallel
+ #pragma omp single
+ {
+ f1 ();
+ check (1);
+ f2 ();
+ check (1);
+ f3 ();
+ check (1);
+ f4 (J<int> (&a[14], &a[1803]));
+ check (i >= 14 && i < 1803);
+ f5 ();
+ check (i >= 0 && i < 1024);
+ f6 (J<K<int>> (&e[19], &e[1029]));
+ check (i >= 19 && i < 1029);
+ f7 (J<L<int>> (&f[15], &f[1091]));
+ check (i >= 15 && i < 1091);
+ f8 (J<K<int>> (&e[27], &e[1037]));
+ check (i >= 27 && i < 1037);
+ f9 (J<L<int>> (&f[1], &f[1012]));
+ check (i >= 1 && i < 1012);
+ f10 <0> ();
+ check (1);
+ f11 <1> ();
+ check (1);
+ f12 <2> ();
+ check (1);
+ f13 (J<int> (&a[24], &a[1703]));
+ check (i >= 24 && i < 1703);
+ f14 <1024> ();
+ check (i >= 0 && i < 1024);
+ f15 (J<K<int>> (&e[39], &e[929]));
+ check (i >= 39 && i < 929);
+ f16 (J<L<int>> (&f[17], &f[1071]));
+ check (i >= 17 && i < 1071);
+ f17 <3> (J<K<int>> (&e[7], &e[1017]));
+ check (i >= 7 && i < 1017);
+ f18 <5> (J<L<int>> (&f[121], &f[1010]));
+ check (i >= 121 && i < 1010);
+ }
+}
diff --git a/libgomp/testsuite/libgomp.c++/for-26.C b/libgomp/testsuite/libgomp.c++/for-26.C
new file mode 100644
index 0000000..bb7ae11
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/for-26.C
@@ -0,0 +1,422 @@
+// { dg-do run }
+// { dg-additional-options "-std=c++17" }
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+extern "C" void abort ();
+
+namespace std {
+ template<typename T> struct tuple_size;
+ template<int, typename> struct tuple_element;
+}
+
+template <typename T>
+class I
+{
+public:
+ typedef ptrdiff_t difference_type;
+ I ();
+ ~I ();
+ I (T *);
+ I (const I &);
+ T &operator * ();
+ T *operator -> ();
+ T &operator [] (const difference_type &) const;
+ I &operator = (const I &);
+ I &operator ++ ();
+ I operator ++ (int);
+ I &operator -- ();
+ I operator -- (int);
+ I &operator += (const difference_type &);
+ I &operator -= (const difference_type &);
+ I operator + (const difference_type &) const;
+ I operator - (const difference_type &) const;
+ template <typename S> friend bool operator == (I<S> &, I<S> &);
+ template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator < (I<S> &, I<S> &);
+ template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator <= (I<S> &, I<S> &);
+ template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator > (I<S> &, I<S> &);
+ template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator >= (I<S> &, I<S> &);
+ template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+ template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+ T *p;
+};
+template <typename T> I<T>::I () : p (0) {}
+template <typename T> I<T>::~I () {}
+template <typename T> I<T>::I (T *x) : p (x) {}
+template <typename T> I<T>::I (const I &x) : p (x.p) {}
+template <typename T> T &I<T>::operator * () { return *p; }
+template <typename T> T *I<T>::operator -> () { return p; }
+template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
+template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
+template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
+template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
+template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
+template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
+template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
+template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
+template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
+template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
+template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
+template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
+template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
+template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
+template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
+template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
+template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
+
+template <typename T>
+class J
+{
+public:
+ J(const I<T> &x, const I<T> &y) : b (x), e (y) {}
+ const I<T> &begin ();
+ const I<T> &end ();
+private:
+ I<T> b, e;
+};
+
+template <typename T> const I<T> &J<T>::begin () { return b; }
+template <typename T> const I<T> &J<T>::end () { return e; }
+
+struct K
+{
+ template <int N> int &get () { if (N == 0) return c; else if (N == 1) return b; return a; }
+ int a, b, c;
+};
+
+template <> struct std::tuple_size<K> { static constexpr int value = 3; };
+template <int N> struct std::tuple_element<N, K> { using type = int; };
+
+struct L
+{
+ int a, b, c;
+};
+
+int a[2000];
+long b[40];
+short c[50];
+int d[1024];
+K e[1089];
+L f[1093];
+
+int results[2000];
+
+template <typename T>
+void
+baz (I<T> &i)
+{
+ if (*i < 0 || *i >= 2000)
+ abort ();
+ results[*i]++;
+}
+
+void
+baz (int i)
+{
+ if (i < 0 || i >= 2000)
+ abort ();
+ results[i]++;
+}
+
+void
+f1 ()
+{
+#pragma omp distribute parallel for default(none) shared(a)
+ for (auto i : a)
+ baz (i);
+}
+
+void
+f2 ()
+{
+#pragma omp distribute parallel for default(none) shared(a)
+ for (auto &i : a)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+void
+f3 ()
+{
+#pragma omp distribute parallel for collapse(3) default(none) shared(b, c)
+ for (auto &i : b)
+ for (int j = 9; j < 10; j++)
+ for (auto k : c)
+ if (&i != &b[i] || i < 0 || i >= 40 || j != 9 || k < 0 || k >= 50)
+ abort ();
+ else
+ baz (i * 50 + k);
+}
+
+void
+f4 (J<int> j)
+{
+#pragma omp distribute parallel for default(none) shared(j, a)
+ for (auto &i : j)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+void
+f5 ()
+{
+#pragma omp distribute parallel for simd default(none) shared(d, results)
+ for (auto i : d)
+ results[i % 1024] += 2 * ((unsigned) i >> 10) + 1;
+}
+
+void
+f6 (J<K> j)
+{
+#pragma omp distribute parallel for default(none) shared(j, e)
+ for (auto & [k, l, m] : j)
+ if (&k != &e[m].c || &l != &e[m].b || &m != &e[m].a || k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+void
+f7 (J<L> j)
+{
+#pragma omp distribute parallel for default(none) shared(j, f)
+ for (auto & [k, l, m] : j)
+ if (&k != &f[k].a || &l != &f[k].b || &m != &f[k].c || l != k * 4 || m != k * 5)
+ abort ();
+ else
+ baz (k);
+}
+
+void
+f8 (J<K> j)
+{
+#pragma omp distribute parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+void
+f9 (J<L> j)
+{
+#pragma omp distribute parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (l != k * 4 || m != k * 5)
+ abort ();
+ else
+ baz (k);
+}
+
+template <int N>
+void
+f10 ()
+{
+#pragma omp distribute parallel for default(none) shared(a)
+ for (auto i : a)
+ baz (i);
+}
+
+template <int N>
+void
+f11 ()
+{
+#pragma omp distribute parallel for default(none) shared(a)
+ for (auto &i : a)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+template <int N>
+void
+f12 ()
+{
+#pragma omp distribute parallel for collapse(3) default(none) shared(a, b, c)
+ for (auto &i : b)
+ for (I<int> j = I<int> (&a[9]); j < I<int> (&a[10]); j++)
+ for (auto k : c)
+ if (&i != &b[i] || i < 0 || i >= 40 || *j != 9 || k < 0 || k >= 50)
+ abort ();
+ else
+ baz (i * 50 + k);
+}
+
+template <typename T>
+void
+f13 (J<T> j)
+{
+#pragma omp distribute parallel for default(none) shared(j, a)
+ for (auto &i : j)
+ if (&i != &a[i])
+ abort ();
+ else
+ baz (i);
+}
+
+template <int N>
+void
+f14 ()
+{
+#pragma omp distribute parallel for simd default(none) shared(d, results)
+ for (auto i : d)
+ results[i % N] += 2 * ((unsigned) i >> 10) + 1;
+}
+
+template <typename T>
+void
+f15 (J<T> j)
+{
+#pragma omp distribute parallel for default(none) shared(j, e)
+ for (auto & [k, l, m] : j)
+ if (&k != &e[m].c || &l != &e[m].b || &m != &e[m].a || k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+template <typename T>
+void
+f16 (J<T> j)
+{
+#pragma omp distribute parallel for default(none) shared(j, f)
+ for (auto & [k, l, m] : j)
+ if (&k != &f[k].a || &l != &f[k].b || &m != &f[k].c || l != k * 4 || m != k * 5)
+ abort ();
+ else
+ baz (k);
+}
+
+template <int N>
+void
+f17 (J<K> j)
+{
+#pragma omp distribute parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (k != m * 3 || l != m * 2)
+ abort ();
+ else
+ baz (m);
+}
+
+template <int N>
+void
+f18 (J<L> j)
+{
+#pragma omp distribute parallel for default(none) shared(j)
+ for (auto [k, l, m] : j)
+ if (l != k * 4 || m != k * 5)
+ abort ();
+ else
+ baz (k);
+}
+
+#define check(expr) \
+ for (int i = 0; i < 2000; i++) \
+ if (expr) \
+ { \
+ if (results[i] != 1) \
+ abort (); \
+ results[i] = 0; \
+ } \
+ else if (results[i]) \
+ abort ()
+
+int
+main ()
+{
+ for (int i = 0; i < 2000; i++)
+ a[i] = i;
+ for (int i = 0; i < 40; i++)
+ b[i] = i;
+ for (int i = 0; i < 50; i++)
+ c[i] = i;
+ for (int i = 0; i < 1024; i++)
+ d[i] = i;
+ for (int i = 0; i < 1089; i++)
+ {
+ e[i].a = i;
+ e[i].b = 2 * i;
+ e[i].c = 3 * i;
+ }
+ for (int i = 0; i < 1093; i++)
+ {
+ f[i].a = i;
+ f[i].b = 4 * i;
+ f[i].c = 5 * i;
+ }
+ #pragma omp teams
+ f1 ();
+ check (1);
+ #pragma omp teams
+ f2 ();
+ check (1);
+ #pragma omp teams
+ f3 ();
+ check (1);
+ #pragma omp teams
+ f4 (J<int> (&a[14], &a[1803]));
+ check (i >= 14 && i < 1803);
+ #pragma omp teams
+ f5 ();
+ check (i >= 0 && i < 1024);
+ #pragma omp teams
+ f6 (J<K> (&e[19], &e[1029]));
+ check (i >= 19 && i < 1029);
+ #pragma omp teams
+ f7 (J<L> (&f[15], &f[1091]));
+ check (i >= 15 && i < 1091);
+ #pragma omp teams
+ f8 (J<K> (&e[27], &e[1037]));
+ check (i >= 27 && i < 1037);
+ #pragma omp teams
+ f9 (J<L> (&f[1], &f[1012]));
+ check (i >= 1 && i < 1012);
+ #pragma omp teams
+ f10 <0> ();
+ check (1);
+ #pragma omp teams
+ f11 <1> ();
+ check (1);
+ #pragma omp teams
+ f12 <2> ();
+ check (1);
+ #pragma omp teams
+ f13 (J<int> (&a[24], &a[1703]));
+ check (i >= 24 && i < 1703);
+ #pragma omp teams
+ f14 <1024> ();
+ check (i >= 0 && i < 1024);
+ #pragma omp teams
+ f15 (J<K> (&e[39], &e[929]));
+ check (i >= 39 && i < 929);
+ #pragma omp teams
+ f16 (J<L> (&f[17], &f[1071]));
+ check (i >= 17 && i < 1071);
+ #pragma omp teams
+ f17 <3> (J<K> (&e[7], &e[1017]));
+ check (i >= 7 && i < 1017);
+ #pragma omp teams
+ f18 <5> (J<L> (&f[121], &f[1010]));
+ check (i >= 121 && i < 1010);
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-1.C b/libgomp/testsuite/libgomp.c++/task-reduction-1.C
new file mode 100644
index 0000000..b3e228e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-1.C
@@ -0,0 +1,63 @@
+extern "C" void abort ();
+
+int as;
+int &a = as;
+long int bs = 1;
+long int &b = bs;
+
+void
+foo (int &c, long long int &d)
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (*: d) in_reduction (+: c) \
+ in_reduction (+: a) in_reduction (*: b)
+ {
+ a += 7;
+ b *= 2;
+ c += 9;
+ d *= 3;
+ }
+}
+
+int
+main ()
+{
+ int cs = 0;
+ int &c = cs;
+ long long int ds = 1;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ long long int &d = ds;
+ #pragma omp taskgroup task_reduction (+: a, c) task_reduction (*: b, d)
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b, d)
+ {
+ int j;
+ a += 7;
+ b *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b, d)
+ {
+ a += 7;
+ b *= 2;
+ c += 9;
+ d *= 3;
+ foo (c, d);
+ }
+ c += 9;
+ d *= 3;
+ }
+ }
+#define THREEP4 (3LL * 3LL * 3LL * 3LL)
+ if (d != (THREEP4 * THREEP4 * THREEP4 * THREEP4 * THREEP4 * THREEP4
+ * THREEP4))
+ abort ();
+ }
+ if (a != 28 * 7 || b != (1L << 28) || c != 28 * 9)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-10.C b/libgomp/testsuite/libgomp.c++/task-reduction-10.C
new file mode 100644
index 0000000..0eb94c1
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-10.C
@@ -0,0 +1,125 @@
+extern "C" void abort ();
+
+struct S { S (); S (long long int, int); ~S (); static int cnt1, cnt2, cnt3; long long int s; int t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long long int x, int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S as = { 0LL, 7 };
+S &a = as;
+S bs (1LL, 5);
+S &b = bs;
+
+void
+foo (S &c, S &d)
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: c) in_reduction (*: b, d) in_reduction (+: a)
+ {
+ a.s += 7;
+ b.s *= 2;
+ c.s += 9;
+ d.s *= 3;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+}
+
+void
+test ()
+{
+ S cs = { 0LL, 7 };
+ S &c = cs;
+ S ds (1LL, 5);
+ #pragma omp parallel if (0)
+ {
+ S &d = ds;
+ #pragma omp parallel reduction (task, +: a, c) reduction (task, *: b, d)
+ {
+ #pragma omp for
+ for (int i = 0; i < 4; i++)
+ #pragma omp task in_reduction (*: b, d) in_reduction (+: a, c)
+ {
+ int j;
+ a.s += 7;
+ b.s *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a) in_reduction (*: b) \
+ in_reduction (+: c) in_reduction (*: d)
+ {
+ a.s += 7;
+ b.s *= 2;
+ c.s += 9;
+ d.s *= 3;
+ foo (c, d);
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+ c.s += 9;
+ d.s *= 3;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+ }
+#define THREEP7 (3LL * 3LL * 3LL * 3LL * 3LL * 3LL * 3LL)
+ if (d.s != (THREEP7 * THREEP7 * THREEP7 * THREEP7) || d.t != 5)
+ abort ();
+ }
+ if (a.s != 28 * 7 || a.t != 7 || b.s != (1L << 28) || b.t != 5
+ || c.s != 28 * 9 || c.t != 7)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test ();
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-11.C b/libgomp/testsuite/libgomp.c++/task-reduction-11.C
new file mode 100644
index 0000000..542bdd6
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-11.C
@@ -0,0 +1,237 @@
+extern "C" void abort ();
+
+int as[2];
+int (&a)[2] = as;
+long long int bs[7] = { 9, 11, 1, 1, 1, 13, 15 };
+long long int (&b)[7] = bs;
+int es[3] = { 5, 0, 5 };
+int (&e)[3] = es;
+int fs[5] = { 6, 7, 0, 0, 9 };
+int (&f)[5] = fs;
+int gs[4] = { 1, 0, 0, 2 };
+int (&g)[4] = gs;
+int hs[3] = { 0, 1, 4 };
+int (&h)[3] = hs;
+int ks[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+int (&k)[4][2] = ks;
+long long *ss;
+long long *&s = ss;
+long long (*ts)[2];
+long long (*&t)[2] = ts;
+
+template <typename T>
+void
+foo (T &n, T *&c, long long int *&d, T (&m)[3], T *&r, T (&o)[4], T *&p, T (&q)[4][2])
+{
+ T i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ a[0] += 7;
+ a[1] += 17;
+ b[2] *= 2;
+ b[4] *= 2;
+ c[0] += 6;
+ d[1] *= 2;
+ e[1] += 19;
+ f[2] += 21;
+ f[3] += 23;
+ g[1] += 25;
+ g[2] += 27;
+ h[0] += 29;
+ k[1][0] += 31;
+ k[2][1] += 33;
+ m[1] += 19;
+ r[2] += 21;
+ r[3] += 23;
+ o[1] += 25;
+ o[2] += 27;
+ p[0] += 29;
+ q[1][0] += 31;
+ q[2][1] += 33;
+ s[1] *= 2;
+ t[2][0] *= 2;
+ t[3][1] *= 2;
+ }
+}
+
+template <typename T>
+void
+test (T &n)
+{
+ T cs[2] = { 0, 0 };
+ T (&c)[2] = cs;
+ T ps[3] = { 0, 1, 4 };
+ T (&p)[3] = ps;
+ T qs[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+ T (&q)[4][2] = qs;
+ long long sb[4] = { 5, 1, 1, 6 };
+ long long tb[5][2] = { { 9, 10 }, { 11, 12 }, { 1, 1 }, { 1, 1 }, { 13, 14 } };
+ T ms[3] = { 5, 0, 5 };
+ T os[4] = { 1, 0, 0, 2 };
+ s = sb;
+ t = tb;
+ #pragma omp parallel if (0)
+ {
+ long long int ds[] = { 1, 1 };
+ long long int (&d)[2] = ds;
+ T (&m)[3] = ms;
+ T rs[5] = { 6, 7, 0, 0, 9 };
+ T (&r)[5] = rs;
+ T (&o)[4] = os;
+ #pragma omp parallel reduction (task,+: a, c) reduction (task,*: b[2 * n:3 * n], d) \
+ reduction (task,+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ reduction (task,+: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ reduction (task,*: t[2:2][:], s[1:n + 1])
+ {
+ #pragma omp for
+ for (int i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
+ in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
+ in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ T j;
+ a[0] += 2;
+ a[1] += 3;
+ b[2] *= 2;
+ f[3] += 8;
+ g[1] += 9;
+ g[2] += 10;
+ h[0] += 11;
+ k[1][1] += 13;
+ k[2][1] += 15;
+ m[1] += 16;
+ r[2] += 8;
+ s[1] *= 2;
+ t[2][1] *= 2;
+ t[3][1] *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:])
+ {
+ m[1] += 6;
+ r[2] += 7;
+ q[1][0] += 17;
+ q[2][0] += 19;
+ a[0] += 4;
+ a[1] += 5;
+ b[3] *= 2;
+ b[4] *= 2;
+ f[3] += 18;
+ g[1] += 29;
+ g[2] += 18;
+ h[0] += 19;
+ s[2] *= 2;
+ t[2][0] *= 2;
+ t[3][0] *= 2;
+ T *cp = c;
+ long long int *dp = d;
+ T *rp = r;
+ T *pp = p;
+ foo (n, cp, dp, m, rp, o, pp, q);
+ r[3] += 18;
+ o[1] += 29;
+ o[2] += 18;
+ p[0] += 19;
+ c[0] += 4;
+ c[1] += 5;
+ d[0] *= 2;
+ e[1] += 6;
+ f[2] += 7;
+ k[1][0] += 17;
+ k[2][0] += 19;
+ }
+ r[3] += 8;
+ o[1] += 9;
+ o[2] += 10;
+ p[0] += 11;
+ q[1][1] += 13;
+ q[2][1] += 15;
+ b[3] *= 2;
+ c[0] += 4;
+ c[1] += 9;
+ d[0] *= 2;
+ e[1] += 16;
+ f[2] += 8;
+ }
+ }
+ if (d[0] != 1LL << (8 + 4)
+ || d[1] != 1LL << 16
+ || m[0] != 5
+ || m[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2] != 5
+ || r[0] != 6
+ || r[1] != 7
+ || r[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4] != 9
+ || o[0] != 1
+ || o[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3] != 2)
+ abort ();
+ }
+ if (a[0] != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1] != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0] != 9 || b[1] != 11
+ || b[2] != 1LL << (16 + 4)
+ || b[3] != 1LL << (8 + 4)
+ || b[4] != 1LL << (16 + 8)
+ || b[5] != 13 || b[6] != 15
+ || c[0] != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1] != 5 * 8 + 9 * 4
+ || e[0] != 5
+ || e[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2] != 5
+ || f[0] != 6
+ || f[1] != 7
+ || f[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4] != 9
+ || g[0] != 1
+ || g[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3] != 2
+ || h[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1] != 1 || h[2] != 4
+ || k[0][0] != 5 || k[0][1] != 6
+ || k[1][0] != 31 * 16 + 17 * 8
+ || k[1][1] != 13 * 4
+ || k[2][0] != 19 * 8
+ || k[2][1] != 33 * 16 + 15 * 4
+ || k[3][0] != 7 || k[3][1] != 8
+ || p[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1] != 1 || p[2] != 4
+ || q[0][0] != 5 || q[0][1] != 6
+ || q[1][0] != 31 * 16 + 17 * 8
+ || q[1][1] != 13 * 4
+ || q[2][0] != 19 * 8
+ || q[2][1] != 33 * 16 + 15 * 4
+ || q[3][0] != 7 || q[3][1] != 8
+ || sb[0] != 5
+ || sb[1] != 1LL << (16 + 4)
+ || sb[2] != 1LL << 8
+ || sb[3] != 6
+ || tb[0][0] != 9 || tb[0][1] != 10 || tb[1][0] != 11 || tb[1][1] != 12
+ || tb[2][0] != 1LL << (16 + 8)
+ || tb[2][1] != 1LL << 4
+ || tb[3][0] != 1LL << 8
+ || tb[3][1] != 1LL << (16 + 4)
+ || tb[4][0] != 13 || tb[4][1] != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ int n = 1;
+ test (n);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-12.C b/libgomp/testsuite/libgomp.c++/task-reduction-12.C
new file mode 100644
index 0000000..02c1a78
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-12.C
@@ -0,0 +1,321 @@
+extern "C" void abort ();
+
+struct S { S (); S (long int, long int); ~S (); static int cnt1, cnt2, cnt3; long int s, t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long int x, long int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S a[2] = { { 0, 7 }, { 0, 7 } };
+S b[7] = { { 9, 5 }, { 11, 5 }, { 1, 5 }, { 1, 5 }, { 1, 5 }, { 13, 5 }, { 15, 5 } };
+S e[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+S f[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+S g[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+S h[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+S k[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+S *s;
+S (*t)[2];
+
+template <int N>
+void
+foo (int n, S *c, S *d, S m[3], S *r, S o[4], S *p, S q[4][2])
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ a[0].s += 7;
+ a[1].s += 17;
+ b[2].s *= 2;
+ b[4].s *= 2;
+ c[0].s += 6;
+ d[1].s *= 2;
+ e[1].s += 19;
+ f[2].s += 21;
+ f[3].s += 23;
+ g[1].s += 25;
+ g[2].s += 27;
+ h[0].s += 29;
+ k[1][0].s += 31;
+ k[2][1].s += 33;
+ m[1].s += 19;
+ r[2].s += 21;
+ r[3].s += 23;
+ o[1].s += 25;
+ o[2].s += 27;
+ p[0].s += 29;
+ q[1][0].s += 31;
+ q[2][1].s += 33;
+ s[1].s *= 2;
+ t[2][0].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ }
+}
+
+template <int N>
+void
+test (int n)
+{
+ S c[2] = { { 0, 7 }, { 0, 7 } };
+ S p[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+ S q[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+ S ss[4] = { { 5, 5 }, { 1, 5 }, { 1, 5 }, { 6, 5 } };
+ S tt[5][2] = { { { 9, 5 }, { 10, 5 } }, { { 11, 5 }, { 12, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 13, 5 }, { 14, 5 } } };
+ s = ss;
+ t = tt;
+ #pragma omp parallel num_threads (1) if (0)
+ {
+ S d[] = { { 1, 5 }, { 1, 5 } };
+ S m[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+ S r[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+ S o[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+ #pragma omp parallel reduction (task, +: a, c) reduction (task, *: b[2 * n:3 * n], d) \
+ reduction (task, +: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ reduction (task, +: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ reduction (task, *: t[2:2][:], s[1:n + 1])
+ {
+ #pragma omp for
+ for (int i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
+ in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
+ in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ int j;
+ a[0].s += 2;
+ a[1].s += 3;
+ b[2].s *= 2;
+ f[3].s += 8;
+ g[1].s += 9;
+ g[2].s += 10;
+ h[0].s += 11;
+ k[1][1].s += 13;
+ k[2][1].s += 15;
+ m[1].s += 16;
+ r[2].s += 8;
+ s[1].s *= 2;
+ t[2][1].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:])
+ {
+ m[1].s += 6;
+ r[2].s += 7;
+ q[1][0].s += 17;
+ q[2][0].s += 19;
+ a[0].s += 4;
+ a[1].s += 5;
+ b[3].s *= 2;
+ b[4].s *= 2;
+ f[3].s += 18;
+ g[1].s += 29;
+ g[2].s += 18;
+ h[0].s += 19;
+ s[2].s *= 2;
+ t[2][0].s *= 2;
+ t[3][0].s *= 2;
+ foo<N> (n, c, d, m, r, o, p, q);
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ r[3].s += 18;
+ o[1].s += 29;
+ o[2].s += 18;
+ p[0].s += 19;
+ c[0].s += 4;
+ c[1].s += 5;
+ d[0].s *= 2;
+ e[1].s += 6;
+ f[2].s += 7;
+ k[1][0].s += 17;
+ k[2][0].s += 19;
+ }
+ r[3].s += 8;
+ o[1].s += 9;
+ o[2].s += 10;
+ p[0].s += 11;
+ q[1][1].s += 13;
+ q[2][1].s += 15;
+ b[3].s *= 2;
+ c[0].s += 4;
+ c[1].s += 9;
+ d[0].s *= 2;
+ e[1].s += 16;
+ f[2].s += 8;
+ }
+ }
+ if (d[0].s != 1LL << (8 + 4)
+ || d[1].s != 1LL << 16
+ || m[0].s != 5
+ || m[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2].s != 5
+ || r[0].s != 6
+ || r[1].s != 7
+ || r[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4].s != 9
+ || o[0].s != 1
+ || o[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3].s != 2)
+ abort ();
+ if (e[1].t != 7 || h[0].t != 7 || m[1].t != 7 || p[0].t != 7)
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if (a[z].t != 7 || c[z].t != 7 || d[z].t != 5 || f[z + 2].t != 7
+ || g[z + 1].t != 7 || r[z + 2].t != 7 || s[z + 1].t != 5 || o[z + 1].t != 7
+ || k[z + 1][0].t != 7 || k[z + 1][1].t != 7 || q[z + 1][0].t != 7 || q[z + 1][1].t != 7
+ || t[z + 2][0].t != 5 || t[z + 2][1].t != 5)
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5)
+ abort ();
+ }
+ if (a[0].s != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1].s != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0].s != 9 || b[1].s != 11
+ || b[2].s != 1LL << (16 + 4)
+ || b[3].s != 1LL << (8 + 4)
+ || b[4].s != 1LL << (16 + 8)
+ || b[5].s != 13 || b[6].s != 15
+ || c[0].s != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1].s != 5 * 8 + 9 * 4
+ || e[0].s != 5
+ || e[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2].s != 5
+ || f[0].s != 6
+ || f[1].s != 7
+ || f[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4].s != 9
+ || g[0].s != 1
+ || g[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3].s != 2
+ || h[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1].s != 1 || h[2].s != 4
+ || k[0][0].s != 5 || k[0][1].s != 6
+ || k[1][0].s != 31 * 16 + 17 * 8
+ || k[1][1].s != 13 * 4
+ || k[2][0].s != 19 * 8
+ || k[2][1].s != 33 * 16 + 15 * 4
+ || k[3][0].s != 7 || k[3][1].s != 8
+ || p[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1].s != 1 || p[2].s != 4
+ || q[0][0].s != 5 || q[0][1].s != 6
+ || q[1][0].s != 31 * 16 + 17 * 8
+ || q[1][1].s != 13 * 4
+ || q[2][0].s != 19 * 8
+ || q[2][1].s != 33 * 16 + 15 * 4
+ || q[3][0].s != 7 || q[3][1].s != 8
+ || ss[0].s != 5
+ || ss[1].s != 1LL << (16 + 4)
+ || ss[2].s != 1LL << 8
+ || ss[3].s != 6
+ || tt[0][0].s != 9 || tt[0][1].s != 10 || tt[1][0].s != 11 || tt[1][1].s != 12
+ || tt[2][0].s != 1LL << (16 + 8)
+ || tt[2][1].s != 1LL << 4
+ || tt[3][0].s != 1LL << 8
+ || tt[3][1].s != 1LL << (16 + 4)
+ || tt[4][0].s != 13 || tt[4][1].s != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test<0> (1);
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-13.C b/libgomp/testsuite/libgomp.c++/task-reduction-13.C
new file mode 100644
index 0000000..3d0165d
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-13.C
@@ -0,0 +1,342 @@
+extern "C" void abort ();
+
+struct S { S (); S (long int, long int); ~S (); static int cnt1, cnt2, cnt3; long int s, t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long int x, long int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S as[2] = { { 0, 7 }, { 0, 7 } };
+S (&a)[2] = as;
+S bs[7] = { { 9, 5 }, { 11, 5 }, { 1, 5 }, { 1, 5 }, { 1, 5 }, { 13, 5 }, { 15, 5 } };
+S (&b)[7] = bs;
+S es[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+S (&e)[3] = es;
+S fs[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+S (&f)[5] = fs;
+S gs[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+S (&g)[4] = gs;
+S hs[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+S (&h)[3] = hs;
+S ks[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+S (&k)[4][2] = ks;
+S *ss;
+S *&s = ss;
+S (*ts)[2];
+S (*&t)[2] = ts;
+
+template <typename S, typename T>
+void
+foo (T &n, S *&c, S *&d, S (&m)[3], S *&r, S (&o)[4], S *&p, S (&q)[4][2])
+{
+ T i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ a[0].s += 7;
+ a[1].s += 17;
+ b[2].s *= 2;
+ b[4].s *= 2;
+ c[0].s += 6;
+ d[1].s *= 2;
+ e[1].s += 19;
+ f[2].s += 21;
+ f[3].s += 23;
+ g[1].s += 25;
+ g[2].s += 27;
+ h[0].s += 29;
+ k[1][0].s += 31;
+ k[2][1].s += 33;
+ m[1].s += 19;
+ r[2].s += 21;
+ r[3].s += 23;
+ o[1].s += 25;
+ o[2].s += 27;
+ p[0].s += 29;
+ q[1][0].s += 31;
+ q[2][1].s += 33;
+ s[1].s *= 2;
+ t[2][0].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (T z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (T z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ }
+}
+
+template <typename S, typename T>
+void
+test (T &n)
+{
+ S cs[2] = { { 0, 7 }, { 0, 7 } };
+ S (&c)[2] = cs;
+ S ps[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+ S (&p)[3] = ps;
+ S qs[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+ S (&q)[4][2] = qs;
+ S sb[4] = { { 5, 5 }, { 1, 5 }, { 1, 5 }, { 6, 5 } };
+ S tb[5][2] = { { { 9, 5 }, { 10, 5 } }, { { 11, 5 }, { 12, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 13, 5 }, { 14, 5 } } };
+ S ms[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+ S os[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+ s = sb;
+ t = tb;
+ #pragma omp parallel if (0)
+ {
+ S ds[] = { { 1, 5 }, { 1, 5 } };
+ S (&d)[2] = ds;
+ S (&m)[3] = ms;
+ S rs[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+ S (&r)[5] = rs;
+ S (&o)[4] = os;
+ #pragma omp parallel reduction (task, +: a, c) reduction (task, *: b[2 * n:3 * n], d) \
+ reduction (task, +: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ reduction (task, +: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ reduction (task, *: t[2:2][:], s[1:n + 1])
+ {
+ #pragma omp for
+ for (T i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
+ in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
+ in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ T j;
+ a[0].s += 2;
+ a[1].s += 3;
+ b[2].s *= 2;
+ f[3].s += 8;
+ g[1].s += 9;
+ g[2].s += 10;
+ h[0].s += 11;
+ k[1][1].s += 13;
+ k[2][1].s += 15;
+ m[1].s += 16;
+ r[2].s += 8;
+ s[1].s *= 2;
+ t[2][1].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (T z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (T z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:])
+ {
+ m[1].s += 6;
+ r[2].s += 7;
+ q[1][0].s += 17;
+ q[2][0].s += 19;
+ a[0].s += 4;
+ a[1].s += 5;
+ b[3].s *= 2;
+ b[4].s *= 2;
+ f[3].s += 18;
+ g[1].s += 29;
+ g[2].s += 18;
+ h[0].s += 19;
+ s[2].s *= 2;
+ t[2][0].s *= 2;
+ t[3][0].s *= 2;
+ S *cp = c;
+ S *dp = d;
+ S *rp = r;
+ S *pp = p;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (T z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (T z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ foo (n, cp, dp, m, rp, o, pp, q);
+ r[3].s += 18;
+ o[1].s += 29;
+ o[2].s += 18;
+ p[0].s += 19;
+ c[0].s += 4;
+ c[1].s += 5;
+ d[0].s *= 2;
+ e[1].s += 6;
+ f[2].s += 7;
+ k[1][0].s += 17;
+ k[2][0].s += 19;
+ }
+ r[3].s += 8;
+ o[1].s += 9;
+ o[2].s += 10;
+ p[0].s += 11;
+ q[1][1].s += 13;
+ q[2][1].s += 15;
+ b[3].s *= 2;
+ c[0].s += 4;
+ c[1].s += 9;
+ d[0].s *= 2;
+ e[1].s += 16;
+ f[2].s += 8;
+ }
+ }
+ if (d[0].s != 1LL << (8 + 4)
+ || d[1].s != 1LL << 16
+ || m[0].s != 5
+ || m[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2].s != 5
+ || r[0].s != 6
+ || r[1].s != 7
+ || r[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4].s != 9
+ || o[0].s != 1
+ || o[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3].s != 2)
+ abort ();
+ if (e[1].t != 7 || h[0].t != 7 || m[1].t != 7 || p[0].t != 7)
+ abort ();
+ for (T z = 0; z < 2; z++)
+ if (a[z].t != 7 || c[z].t != 7 || d[z].t != 5 || f[z + 2].t != 7
+ || g[z + 1].t != 7 || r[z + 2].t != 7 || s[z + 1].t != 5 || o[z + 1].t != 7
+ || k[z + 1][0].t != 7 || k[z + 1][1].t != 7 || q[z + 1][0].t != 7 || q[z + 1][1].t != 7
+ || t[z + 2][0].t != 5 || t[z + 2][1].t != 5)
+ abort ();
+ for (T z = 0; z < 3; z++)
+ if (b[z + 2].t != 5)
+ abort ();
+ }
+ if (a[0].s != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1].s != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0].s != 9 || b[1].s != 11
+ || b[2].s != 1LL << (16 + 4)
+ || b[3].s != 1LL << (8 + 4)
+ || b[4].s != 1LL << (16 + 8)
+ || b[5].s != 13 || b[6].s != 15
+ || c[0].s != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1].s != 5 * 8 + 9 * 4
+ || e[0].s != 5
+ || e[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2].s != 5
+ || f[0].s != 6
+ || f[1].s != 7
+ || f[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4].s != 9
+ || g[0].s != 1
+ || g[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3].s != 2
+ || h[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1].s != 1 || h[2].s != 4
+ || k[0][0].s != 5 || k[0][1].s != 6
+ || k[1][0].s != 31 * 16 + 17 * 8
+ || k[1][1].s != 13 * 4
+ || k[2][0].s != 19 * 8
+ || k[2][1].s != 33 * 16 + 15 * 4
+ || k[3][0].s != 7 || k[3][1].s != 8
+ || p[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1].s != 1 || p[2].s != 4
+ || q[0][0].s != 5 || q[0][1].s != 6
+ || q[1][0].s != 31 * 16 + 17 * 8
+ || q[1][1].s != 13 * 4
+ || q[2][0].s != 19 * 8
+ || q[2][1].s != 33 * 16 + 15 * 4
+ || q[3][0].s != 7 || q[3][1].s != 8
+ || sb[0].s != 5
+ || sb[1].s != 1LL << (16 + 4)
+ || sb[2].s != 1LL << 8
+ || sb[3].s != 6
+ || tb[0][0].s != 9 || tb[0][1].s != 10 || tb[1][0].s != 11 || tb[1][1].s != 12
+ || tb[2][0].s != 1LL << (16 + 8)
+ || tb[2][1].s != 1LL << 4
+ || tb[3][0].s != 1LL << 8
+ || tb[3][1].s != 1LL << (16 + 4)
+ || tb[4][0].s != 13 || tb[4][1].s != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ int n = 1;
+ test<S, int> (n);
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-14.C b/libgomp/testsuite/libgomp.c++/task-reduction-14.C
new file mode 100644
index 0000000..3f4e79b
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-14.C
@@ -0,0 +1,72 @@
+#include <omp.h>
+#include <stdlib.h>
+
+struct A { A (); ~A (); A (const A &); static int cnt1, cnt2, cnt3; int a; };
+int A::cnt1;
+int A::cnt2;
+int A::cnt3;
+A::A () : a (0)
+{
+ #pragma omp atomic
+ cnt1++;
+}
+A::A (const A &x) : a (x.a)
+{
+ #pragma omp atomic
+ cnt2++;
+}
+A::~A ()
+{
+ #pragma omp atomic
+ cnt3++;
+}
+#pragma omp declare reduction (+: A: omp_out.a += omp_in.a)
+
+void
+foo (int x)
+{
+ A a, b[2];
+ int d = 1;
+ long int e[2] = { 1L, 1L };
+ int c = 0;
+ #pragma omp parallel
+ {
+ if (x && omp_get_thread_num () == 0)
+ {
+ for (int i = 0; i < 10000000; ++i)
+ asm volatile ("");
+ c = 1;
+ #pragma omp cancel parallel
+ }
+ #pragma omp for reduction (task, +: a, b) reduction (task, *: d, e)
+ for (int i = 0; i < 64; i++)
+ #pragma omp task in_reduction (+: a, b) in_reduction (*: d, e)
+ {
+ a.a++;
+ b[0].a += 2;
+ b[1].a += 3;
+ d *= ((i & 7) == 0) + 1;
+ e[0] *= ((i & 7) == 3) + 1;
+ e[1] *= ((i & 3) == 2) + 1;
+ }
+ if (x && omp_get_cancellation ())
+ abort ();
+ }
+ if (!c)
+ {
+ if (a.a != 64 || b[0].a != 128 || b[1].a != 192)
+ abort ();
+ if (d != 256 || e[0] != 256L || e[1] != 65536L)
+ abort ();
+ }
+}
+
+int
+main ()
+{
+ int c1 = A::cnt1, c2 = A::cnt2, c3 = A::cnt3;
+ volatile int zero = 0;
+ foo (zero);
+ if (A::cnt1 + A::cnt2 - c1 - c2 != A::cnt3 - c3)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-15.C b/libgomp/testsuite/libgomp.c++/task-reduction-15.C
new file mode 100644
index 0000000..8a01e6b
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-15.C
@@ -0,0 +1,75 @@
+extern "C" void abort ();
+
+int as;
+int &a = as;
+long int bs = 1;
+long int &b = bs;
+
+template <typename T, typename U>
+void
+foo (T &c, U &d)
+{
+ T i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (*: d) in_reduction (+: c) \
+ in_reduction (+: a) in_reduction (*: b)
+ {
+ a += 7;
+ b *= 2;
+ c += 9;
+ d *= 3;
+ }
+}
+
+template <typename T, typename U>
+void
+bar ()
+{
+ T cs = 0;
+ T &c = cs;
+ U ds = 1;
+ #pragma omp parallel if (0)
+ {
+ U &d = ds;
+ #pragma omp parallel
+ {
+ T i;
+ #pragma omp for reduction (task, +: a, c) reduction (task, *: b, d)
+ for (i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b, d)
+ {
+ T j;
+ a += 7;
+ b *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b, d)
+ {
+ a += 7;
+ b *= 2;
+ c += 9;
+ d *= 3;
+ foo (c, d);
+ }
+ c += 9;
+ d *= 3;
+ }
+#define THREEP4 (3LL * 3LL * 3LL * 3LL)
+ if (d != (THREEP4 * THREEP4 * THREEP4 * THREEP4 * THREEP4 * THREEP4
+ * THREEP4))
+ abort ();
+ if (a != 28 * 7 || b != (1L << 28) || c != 28 * 9)
+ abort ();
+ }
+ }
+ if (a != 28 * 7 || b != (1L << 28) || c != 28 * 9)
+ abort ();
+ if (ds != (THREEP4 * THREEP4 * THREEP4 * THREEP4 * THREEP4 * THREEP4
+ * THREEP4))
+ abort ();
+}
+
+int
+main ()
+{
+ bar<int, long long int> ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-16.C b/libgomp/testsuite/libgomp.c++/task-reduction-16.C
new file mode 100644
index 0000000..5835edc
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-16.C
@@ -0,0 +1,130 @@
+extern "C" void abort ();
+
+struct S { S (); S (long long int, int); ~S (); static int cnt1, cnt2, cnt3; long long int s; int t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long long int x, int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S as = { 0LL, 7 };
+S &a = as;
+S bs (1LL, 5);
+S &b = bs;
+
+void
+foo (S &c, S &d)
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: c) in_reduction (*: b, d) in_reduction (+: a)
+ {
+ a.s += 7;
+ b.s *= 2;
+ c.s += 9;
+ d.s *= 3;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+}
+
+void
+test ()
+{
+ S cs = { 0LL, 7 };
+ S &c = cs;
+ S ds (1LL, 5);
+ #pragma omp parallel if (0)
+ {
+ S &d = ds;
+ #pragma omp parallel shared (a, b, c, d)
+ {
+ #pragma omp for schedule (static, 1) reduction (task, +: a, c) reduction (task, *: b, d)
+ for (int i = 0; i < 4; i++)
+ #pragma omp task in_reduction (*: b, d) in_reduction (+: a, c)
+ {
+ int j;
+ a.s += 7;
+ b.s *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a) in_reduction (*: b) \
+ in_reduction (+: c) in_reduction (*: d)
+ {
+ a.s += 7;
+ b.s *= 2;
+ c.s += 9;
+ d.s *= 3;
+ foo (c, d);
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+ c.s += 9;
+ d.s *= 3;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+#define THREEP7 (3LL * 3LL * 3LL * 3LL * 3LL * 3LL * 3LL)
+ if (d.s != (THREEP7 * THREEP7 * THREEP7 * THREEP7) || d.t != 5)
+ abort ();
+ if (a.s != 28 * 7 || a.t != 7 || b.s != (1L << 28) || b.t != 5
+ || c.s != 28 * 9 || c.t != 7)
+ abort ();
+ }
+ }
+ if (a.s != 28 * 7 || a.t != 7 || b.s != (1L << 28) || b.t != 5
+ || c.s != 28 * 9 || c.t != 7)
+ abort ();
+ if (ds.s != (THREEP7 * THREEP7 * THREEP7 * THREEP7) || ds.t != 5)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test ();
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-17.C b/libgomp/testsuite/libgomp.c++/task-reduction-17.C
new file mode 100644
index 0000000..c00c8e4
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-17.C
@@ -0,0 +1,300 @@
+extern "C" void abort ();
+
+int as[2];
+int (&a)[2] = as;
+long long int bs[7] = { 9, 11, 1, 1, 1, 13, 15 };
+long long int (&b)[7] = bs;
+int es[3] = { 5, 0, 5 };
+int (&e)[3] = es;
+int fs[5] = { 6, 7, 0, 0, 9 };
+int (&f)[5] = fs;
+int gs[4] = { 1, 0, 0, 2 };
+int (&g)[4] = gs;
+int hs[3] = { 0, 1, 4 };
+int (&h)[3] = hs;
+int ks[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+int (&k)[4][2] = ks;
+long long *ss;
+long long *&s = ss;
+long long (*ts)[2];
+long long (*&t)[2] = ts;
+
+template <typename T>
+void
+foo (T &n, T *&c, long long int *&d, T (&m)[3], T *&r, T (&o)[4], T *&p, T (&q)[4][2])
+{
+ T i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ a[0] += 7;
+ a[1] += 17;
+ b[2] *= 2;
+ b[4] *= 2;
+ c[0] += 6;
+ d[1] *= 2;
+ e[1] += 19;
+ f[2] += 21;
+ f[3] += 23;
+ g[1] += 25;
+ g[2] += 27;
+ h[0] += 29;
+ k[1][0] += 31;
+ k[2][1] += 33;
+ m[1] += 19;
+ r[2] += 21;
+ r[3] += 23;
+ o[1] += 25;
+ o[2] += 27;
+ p[0] += 29;
+ q[1][0] += 31;
+ q[2][1] += 33;
+ s[1] *= 2;
+ t[2][0] *= 2;
+ t[3][1] *= 2;
+ }
+}
+
+template <typename T, typename I>
+void
+test (T &n, I x, I y)
+{
+ T cs[2] = { 0, 0 };
+ T (&c)[2] = cs;
+ T ps[3] = { 0, 1, 4 };
+ T (&p)[3] = ps;
+ T qs[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+ T (&q)[4][2] = qs;
+ long long sb[4] = { 5, 1, 1, 6 };
+ long long tb[5][2] = { { 9, 10 }, { 11, 12 }, { 1, 1 }, { 1, 1 }, { 13, 14 } };
+ T ms[3] = { 5, 0, 5 };
+ T os[4] = { 1, 0, 0, 2 };
+ s = sb;
+ t = tb;
+ #pragma omp parallel if (0)
+ {
+ long long int ds[] = { 1, 1 };
+ long long int (&d)[2] = ds;
+ T (&m)[3] = ms;
+ T rs[5] = { 6, 7, 0, 0, 9 };
+ T (&r)[5] = rs;
+ T (&o)[4] = os;
+ #pragma omp parallel
+ {
+ #pragma omp for reduction (task,+: a, c) reduction (task,*: b[2 * n:3 * n], d) \
+ reduction (task,+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ reduction (task,+: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ reduction (task,*: t[2:2][:], s[1:n + 1]) schedule (dynamic)
+ for (I i = x; i != y; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
+ in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
+ in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ T j;
+ a[0] += 2;
+ a[1] += 3;
+ b[2] *= 2;
+ f[3] += 8;
+ g[1] += 9;
+ g[2] += 10;
+ h[0] += 11;
+ k[1][1] += 13;
+ k[2][1] += 15;
+ m[1] += 16;
+ r[2] += 8;
+ s[1] *= 2;
+ t[2][1] *= 2;
+ t[3][1] *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:])
+ {
+ m[1] += 6;
+ r[2] += 7;
+ q[1][0] += 17;
+ q[2][0] += 19;
+ a[0] += 4;
+ a[1] += 5;
+ b[3] *= 2;
+ b[4] *= 2;
+ f[3] += 18;
+ g[1] += 29;
+ g[2] += 18;
+ h[0] += 19;
+ s[2] *= 2;
+ t[2][0] *= 2;
+ t[3][0] *= 2;
+ T *cp = c;
+ long long int *dp = d;
+ T *rp = r;
+ T *pp = p;
+ foo (n, cp, dp, m, rp, o, pp, q);
+ r[3] += 18;
+ o[1] += 29;
+ o[2] += 18;
+ p[0] += 19;
+ c[0] += 4;
+ c[1] += 5;
+ d[0] *= 2;
+ e[1] += 6;
+ f[2] += 7;
+ k[1][0] += 17;
+ k[2][0] += 19;
+ }
+ r[3] += 8;
+ o[1] += 9;
+ o[2] += 10;
+ p[0] += 11;
+ q[1][1] += 13;
+ q[2][1] += 15;
+ b[3] *= 2;
+ c[0] += 4;
+ c[1] += 9;
+ d[0] *= 2;
+ e[1] += 16;
+ f[2] += 8;
+ }
+ if (d[0] != 1LL << (8 + 4)
+ || d[1] != 1LL << 16
+ || m[0] != 5
+ || m[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2] != 5
+ || r[0] != 6
+ || r[1] != 7
+ || r[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4] != 9
+ || o[0] != 1
+ || o[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3] != 2)
+ abort ();
+ if (a[0] != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1] != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0] != 9 || b[1] != 11
+ || b[2] != 1LL << (16 + 4)
+ || b[3] != 1LL << (8 + 4)
+ || b[4] != 1LL << (16 + 8)
+ || b[5] != 13 || b[6] != 15
+ || c[0] != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1] != 5 * 8 + 9 * 4
+ || e[0] != 5
+ || e[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2] != 5
+ || f[0] != 6
+ || f[1] != 7
+ || f[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4] != 9
+ || g[0] != 1
+ || g[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3] != 2
+ || h[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1] != 1 || h[2] != 4
+ || k[0][0] != 5 || k[0][1] != 6
+ || k[1][0] != 31 * 16 + 17 * 8
+ || k[1][1] != 13 * 4
+ || k[2][0] != 19 * 8
+ || k[2][1] != 33 * 16 + 15 * 4
+ || k[3][0] != 7 || k[3][1] != 8
+ || p[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1] != 1 || p[2] != 4
+ || q[0][0] != 5 || q[0][1] != 6
+ || q[1][0] != 31 * 16 + 17 * 8
+ || q[1][1] != 13 * 4
+ || q[2][0] != 19 * 8
+ || q[2][1] != 33 * 16 + 15 * 4
+ || q[3][0] != 7 || q[3][1] != 8
+ || sb[0] != 5
+ || sb[1] != 1LL << (16 + 4)
+ || sb[2] != 1LL << 8
+ || sb[3] != 6
+ || tb[0][0] != 9 || tb[0][1] != 10 || tb[1][0] != 11 || tb[1][1] != 12
+ || tb[2][0] != 1LL << (16 + 8)
+ || tb[2][1] != 1LL << 4
+ || tb[3][0] != 1LL << 8
+ || tb[3][1] != 1LL << (16 + 4)
+ || tb[4][0] != 13 || tb[4][1] != 14)
+ abort ();
+ }
+ if (d[0] != 1LL << (8 + 4)
+ || d[1] != 1LL << 16
+ || m[0] != 5
+ || m[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2] != 5
+ || r[0] != 6
+ || r[1] != 7
+ || r[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4] != 9
+ || o[0] != 1
+ || o[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3] != 2)
+ abort ();
+ }
+ if (a[0] != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1] != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0] != 9 || b[1] != 11
+ || b[2] != 1LL << (16 + 4)
+ || b[3] != 1LL << (8 + 4)
+ || b[4] != 1LL << (16 + 8)
+ || b[5] != 13 || b[6] != 15
+ || c[0] != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1] != 5 * 8 + 9 * 4
+ || e[0] != 5
+ || e[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2] != 5
+ || f[0] != 6
+ || f[1] != 7
+ || f[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4] != 9
+ || g[0] != 1
+ || g[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3] != 2
+ || h[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1] != 1 || h[2] != 4
+ || k[0][0] != 5 || k[0][1] != 6
+ || k[1][0] != 31 * 16 + 17 * 8
+ || k[1][1] != 13 * 4
+ || k[2][0] != 19 * 8
+ || k[2][1] != 33 * 16 + 15 * 4
+ || k[3][0] != 7 || k[3][1] != 8
+ || p[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1] != 1 || p[2] != 4
+ || q[0][0] != 5 || q[0][1] != 6
+ || q[1][0] != 31 * 16 + 17 * 8
+ || q[1][1] != 13 * 4
+ || q[2][0] != 19 * 8
+ || q[2][1] != 33 * 16 + 15 * 4
+ || q[3][0] != 7 || q[3][1] != 8
+ || sb[0] != 5
+ || sb[1] != 1LL << (16 + 4)
+ || sb[2] != 1LL << 8
+ || sb[3] != 6
+ || tb[0][0] != 9 || tb[0][1] != 10 || tb[1][0] != 11 || tb[1][1] != 12
+ || tb[2][0] != 1LL << (16 + 8)
+ || tb[2][1] != 1LL << 4
+ || tb[3][0] != 1LL << 8
+ || tb[3][1] != 1LL << (16 + 4)
+ || tb[4][0] != 13 || tb[4][1] != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ int n = 1;
+ test (n, 0ULL, 4ULL);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-18.C b/libgomp/testsuite/libgomp.c++/task-reduction-18.C
new file mode 100644
index 0000000..99c0e37
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-18.C
@@ -0,0 +1,325 @@
+extern "C" void abort ();
+
+struct S { S (); S (long int, long int); ~S (); static int cnt1, cnt2, cnt3; long int s, t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long int x, long int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S a[2] = { { 0, 7 }, { 0, 7 } };
+S b[7] = { { 9, 5 }, { 11, 5 }, { 1, 5 }, { 1, 5 }, { 1, 5 }, { 13, 5 }, { 15, 5 } };
+S e[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+S f[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+S g[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+S h[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+S k[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+S *s;
+S (*t)[2];
+
+template <int N>
+void
+foo (int n, S *c, S *d, S m[3], S *r, S o[4], S *p, S q[4][2])
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ a[0].s += 7;
+ a[1].s += 17;
+ b[2].s *= 2;
+ b[4].s *= 2;
+ c[0].s += 6;
+ d[1].s *= 2;
+ e[1].s += 19;
+ f[2].s += 21;
+ f[3].s += 23;
+ g[1].s += 25;
+ g[2].s += 27;
+ h[0].s += 29;
+ k[1][0].s += 31;
+ k[2][1].s += 33;
+ m[1].s += 19;
+ r[2].s += 21;
+ r[3].s += 23;
+ o[1].s += 25;
+ o[2].s += 27;
+ p[0].s += 29;
+ q[1][0].s += 31;
+ q[2][1].s += 33;
+ s[1].s *= 2;
+ t[2][0].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ }
+}
+
+template <int N>
+void
+test (int n)
+{
+ S c[2] = { { 0, 7 }, { 0, 7 } };
+ S p[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+ S q[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+ S ss[4] = { { 5, 5 }, { 1, 5 }, { 1, 5 }, { 6, 5 } };
+ S tt[5][2] = { { { 9, 5 }, { 10, 5 } }, { { 11, 5 }, { 12, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 13, 5 }, { 14, 5 } } };
+ s = ss;
+ t = tt;
+ #pragma omp parallel num_threads (1) if (0)
+ {
+ S d[] = { { 1, 5 }, { 1, 5 } };
+ S m[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+ S r[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+ S o[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+ volatile unsigned long long x = 0;
+ volatile unsigned long long y = 4;
+ volatile unsigned long long z = 1;
+ #pragma omp parallel
+ {
+ #pragma omp for reduction (task, +: a, c) reduction (task, *: b[2 * n:3 * n], d) \
+ reduction (task, +: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ reduction (task, +: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ reduction (task, *: t[2:2][:], s[1:n + 1]) \
+ schedule (nonmonotonic: guided, 1)
+ for (unsigned long long i = x; i < y; i += z)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
+ in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
+ in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ int j;
+ a[0].s += 2;
+ a[1].s += 3;
+ b[2].s *= 2;
+ f[3].s += 8;
+ g[1].s += 9;
+ g[2].s += 10;
+ h[0].s += 11;
+ k[1][1].s += 13;
+ k[2][1].s += 15;
+ m[1].s += 16;
+ r[2].s += 8;
+ s[1].s *= 2;
+ t[2][1].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:])
+ {
+ m[1].s += 6;
+ r[2].s += 7;
+ q[1][0].s += 17;
+ q[2][0].s += 19;
+ a[0].s += 4;
+ a[1].s += 5;
+ b[3].s *= 2;
+ b[4].s *= 2;
+ f[3].s += 18;
+ g[1].s += 29;
+ g[2].s += 18;
+ h[0].s += 19;
+ s[2].s *= 2;
+ t[2][0].s *= 2;
+ t[3][0].s *= 2;
+ foo<N> (n, c, d, m, r, o, p, q);
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ r[3].s += 18;
+ o[1].s += 29;
+ o[2].s += 18;
+ p[0].s += 19;
+ c[0].s += 4;
+ c[1].s += 5;
+ d[0].s *= 2;
+ e[1].s += 6;
+ f[2].s += 7;
+ k[1][0].s += 17;
+ k[2][0].s += 19;
+ }
+ r[3].s += 8;
+ o[1].s += 9;
+ o[2].s += 10;
+ p[0].s += 11;
+ q[1][1].s += 13;
+ q[2][1].s += 15;
+ b[3].s *= 2;
+ c[0].s += 4;
+ c[1].s += 9;
+ d[0].s *= 2;
+ e[1].s += 16;
+ f[2].s += 8;
+ }
+ if (a[0].s != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1].s != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0].s != 9 || b[1].s != 11
+ || b[2].s != 1LL << (16 + 4)
+ || b[3].s != 1LL << (8 + 4)
+ || b[4].s != 1LL << (16 + 8)
+ || b[5].s != 13 || b[6].s != 15
+ || c[0].s != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1].s != 5 * 8 + 9 * 4
+ || e[0].s != 5
+ || e[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2].s != 5
+ || f[0].s != 6
+ || f[1].s != 7
+ || f[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4].s != 9
+ || g[0].s != 1
+ || g[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3].s != 2
+ || h[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1].s != 1 || h[2].s != 4
+ || k[0][0].s != 5 || k[0][1].s != 6
+ || k[1][0].s != 31 * 16 + 17 * 8
+ || k[1][1].s != 13 * 4
+ || k[2][0].s != 19 * 8
+ || k[2][1].s != 33 * 16 + 15 * 4
+ || k[3][0].s != 7 || k[3][1].s != 8
+ || p[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1].s != 1 || p[2].s != 4
+ || q[0][0].s != 5 || q[0][1].s != 6
+ || q[1][0].s != 31 * 16 + 17 * 8
+ || q[1][1].s != 13 * 4
+ || q[2][0].s != 19 * 8
+ || q[2][1].s != 33 * 16 + 15 * 4
+ || q[3][0].s != 7 || q[3][1].s != 8
+ || ss[0].s != 5
+ || ss[1].s != 1LL << (16 + 4)
+ || ss[2].s != 1LL << 8
+ || ss[3].s != 6
+ || tt[0][0].s != 9 || tt[0][1].s != 10 || tt[1][0].s != 11 || tt[1][1].s != 12
+ || tt[2][0].s != 1LL << (16 + 8)
+ || tt[2][1].s != 1LL << 4
+ || tt[3][0].s != 1LL << 8
+ || tt[3][1].s != 1LL << (16 + 4)
+ || tt[4][0].s != 13 || tt[4][1].s != 14)
+ abort ();
+ }
+ if (d[0].s != 1LL << (8 + 4)
+ || d[1].s != 1LL << 16
+ || m[0].s != 5
+ || m[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2].s != 5
+ || r[0].s != 6
+ || r[1].s != 7
+ || r[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4].s != 9
+ || o[0].s != 1
+ || o[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3].s != 2)
+ abort ();
+ if (e[1].t != 7 || h[0].t != 7 || m[1].t != 7 || p[0].t != 7)
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if (a[z].t != 7 || c[z].t != 7 || d[z].t != 5 || f[z + 2].t != 7
+ || g[z + 1].t != 7 || r[z + 2].t != 7 || s[z + 1].t != 5 || o[z + 1].t != 7
+ || k[z + 1][0].t != 7 || k[z + 1][1].t != 7 || q[z + 1][0].t != 7 || q[z + 1][1].t != 7
+ || t[z + 2][0].t != 5 || t[z + 2][1].t != 5)
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5)
+ abort ();
+ }
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test<0> (1);
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-19.C b/libgomp/testsuite/libgomp.c++/task-reduction-19.C
new file mode 100644
index 0000000..15945c5
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-19.C
@@ -0,0 +1,343 @@
+extern "C" void abort ();
+
+struct S { S (); S (long int, long int); ~S (); static int cnt1, cnt2, cnt3; long int s, t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long int x, long int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S as[2] = { { 0, 7 }, { 0, 7 } };
+S (&a)[2] = as;
+S bs[7] = { { 9, 5 }, { 11, 5 }, { 1, 5 }, { 1, 5 }, { 1, 5 }, { 13, 5 }, { 15, 5 } };
+S (&b)[7] = bs;
+S es[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+S (&e)[3] = es;
+S fs[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+S (&f)[5] = fs;
+S gs[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+S (&g)[4] = gs;
+S hs[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+S (&h)[3] = hs;
+S ks[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+S (&k)[4][2] = ks;
+S *ss;
+S *&s = ss;
+S (*ts)[2];
+S (*&t)[2] = ts;
+
+template <typename S, typename T>
+void
+foo (T &n, S *&c, S *&d, S (&m)[3], S *&r, S (&o)[4], S *&p, S (&q)[4][2])
+{
+ T i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ a[0].s += 7;
+ a[1].s += 17;
+ b[2].s *= 2;
+ b[4].s *= 2;
+ c[0].s += 6;
+ d[1].s *= 2;
+ e[1].s += 19;
+ f[2].s += 21;
+ f[3].s += 23;
+ g[1].s += 25;
+ g[2].s += 27;
+ h[0].s += 29;
+ k[1][0].s += 31;
+ k[2][1].s += 33;
+ m[1].s += 19;
+ r[2].s += 21;
+ r[3].s += 23;
+ o[1].s += 25;
+ o[2].s += 27;
+ p[0].s += 29;
+ q[1][0].s += 31;
+ q[2][1].s += 33;
+ s[1].s *= 2;
+ t[2][0].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (T z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (T z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ }
+}
+
+template <typename S, typename T>
+void
+test (T &n)
+{
+ S cs[2] = { { 0, 7 }, { 0, 7 } };
+ S (&c)[2] = cs;
+ S ps[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+ S (&p)[3] = ps;
+ S qs[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+ S (&q)[4][2] = qs;
+ S sb[4] = { { 5, 5 }, { 1, 5 }, { 1, 5 }, { 6, 5 } };
+ S tb[5][2] = { { { 9, 5 }, { 10, 5 } }, { { 11, 5 }, { 12, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 13, 5 }, { 14, 5 } } };
+ S ms[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+ S os[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+ s = sb;
+ t = tb;
+ #pragma omp parallel if (0)
+ {
+ S ds[] = { { 1, 5 }, { 1, 5 } };
+ S (&d)[2] = ds;
+ S (&m)[3] = ms;
+ S rs[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+ S (&r)[5] = rs;
+ S (&o)[4] = os;
+ #pragma omp parallel
+ {
+ #pragma omp for reduction (task, +: a, c) reduction (task, *: b[2 * n:3 * n], d) \
+ reduction (task, +: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ reduction (task, +: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ reduction (task, *: t[2:2][:], s[1:n + 1]) \
+ schedule (monotonic: runtime)
+ for (T i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
+ in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
+ in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ T j;
+ a[0].s += 2;
+ a[1].s += 3;
+ b[2].s *= 2;
+ f[3].s += 8;
+ g[1].s += 9;
+ g[2].s += 10;
+ h[0].s += 11;
+ k[1][1].s += 13;
+ k[2][1].s += 15;
+ m[1].s += 16;
+ r[2].s += 8;
+ s[1].s *= 2;
+ t[2][1].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (T z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (T z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:])
+ {
+ m[1].s += 6;
+ r[2].s += 7;
+ q[1][0].s += 17;
+ q[2][0].s += 19;
+ a[0].s += 4;
+ a[1].s += 5;
+ b[3].s *= 2;
+ b[4].s *= 2;
+ f[3].s += 18;
+ g[1].s += 29;
+ g[2].s += 18;
+ h[0].s += 19;
+ s[2].s *= 2;
+ t[2][0].s *= 2;
+ t[3][0].s *= 2;
+ S *cp = c;
+ S *dp = d;
+ S *rp = r;
+ S *pp = p;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (T z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (T z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ foo (n, cp, dp, m, rp, o, pp, q);
+ r[3].s += 18;
+ o[1].s += 29;
+ o[2].s += 18;
+ p[0].s += 19;
+ c[0].s += 4;
+ c[1].s += 5;
+ d[0].s *= 2;
+ e[1].s += 6;
+ f[2].s += 7;
+ k[1][0].s += 17;
+ k[2][0].s += 19;
+ }
+ r[3].s += 8;
+ o[1].s += 9;
+ o[2].s += 10;
+ p[0].s += 11;
+ q[1][1].s += 13;
+ q[2][1].s += 15;
+ b[3].s *= 2;
+ c[0].s += 4;
+ c[1].s += 9;
+ d[0].s *= 2;
+ e[1].s += 16;
+ f[2].s += 8;
+ }
+ if (a[0].s != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1].s != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0].s != 9 || b[1].s != 11
+ || b[2].s != 1LL << (16 + 4)
+ || b[3].s != 1LL << (8 + 4)
+ || b[4].s != 1LL << (16 + 8)
+ || b[5].s != 13 || b[6].s != 15
+ || c[0].s != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1].s != 5 * 8 + 9 * 4
+ || e[0].s != 5
+ || e[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2].s != 5
+ || f[0].s != 6
+ || f[1].s != 7
+ || f[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4].s != 9
+ || g[0].s != 1
+ || g[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3].s != 2
+ || h[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1].s != 1 || h[2].s != 4
+ || k[0][0].s != 5 || k[0][1].s != 6
+ || k[1][0].s != 31 * 16 + 17 * 8
+ || k[1][1].s != 13 * 4
+ || k[2][0].s != 19 * 8
+ || k[2][1].s != 33 * 16 + 15 * 4
+ || k[3][0].s != 7 || k[3][1].s != 8
+ || p[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1].s != 1 || p[2].s != 4
+ || q[0][0].s != 5 || q[0][1].s != 6
+ || q[1][0].s != 31 * 16 + 17 * 8
+ || q[1][1].s != 13 * 4
+ || q[2][0].s != 19 * 8
+ || q[2][1].s != 33 * 16 + 15 * 4
+ || q[3][0].s != 7 || q[3][1].s != 8
+ || sb[0].s != 5
+ || sb[1].s != 1LL << (16 + 4)
+ || sb[2].s != 1LL << 8
+ || sb[3].s != 6
+ || tb[0][0].s != 9 || tb[0][1].s != 10 || tb[1][0].s != 11 || tb[1][1].s != 12
+ || tb[2][0].s != 1LL << (16 + 8)
+ || tb[2][1].s != 1LL << 4
+ || tb[3][0].s != 1LL << 8
+ || tb[3][1].s != 1LL << (16 + 4)
+ || tb[4][0].s != 13 || tb[4][1].s != 14)
+ abort ();
+ if (d[0].s != 1LL << (8 + 4)
+ || d[1].s != 1LL << 16
+ || m[0].s != 5
+ || m[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2].s != 5
+ || r[0].s != 6
+ || r[1].s != 7
+ || r[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4].s != 9
+ || o[0].s != 1
+ || o[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3].s != 2)
+ abort ();
+ if (e[1].t != 7 || h[0].t != 7 || m[1].t != 7 || p[0].t != 7)
+ abort ();
+ for (T z = 0; z < 2; z++)
+ if (a[z].t != 7 || c[z].t != 7 || d[z].t != 5 || f[z + 2].t != 7
+ || g[z + 1].t != 7 || r[z + 2].t != 7 || s[z + 1].t != 5 || o[z + 1].t != 7
+ || k[z + 1][0].t != 7 || k[z + 1][1].t != 7 || q[z + 1][0].t != 7 || q[z + 1][1].t != 7
+ || t[z + 2][0].t != 5 || t[z + 2][1].t != 5)
+ abort ();
+ for (T z = 0; z < 3; z++)
+ if (b[z + 2].t != 5)
+ abort ();
+ }
+ }
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ int n = 1;
+ test<S, int> (n);
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-2.C b/libgomp/testsuite/libgomp.c++/task-reduction-2.C
new file mode 100644
index 0000000..75d2ee3
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-2.C
@@ -0,0 +1,119 @@
+extern "C" void abort ();
+
+struct S { S (); S (long int, long int); ~S (); static int cnt1, cnt2, cnt3; long int s, t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long int x, long int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S a = { 0, 7 };
+S b (1, 5);
+
+void
+foo ()
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (*: b) in_reduction (+: a)
+ {
+ a.s += 7;
+ b.s *= 2;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9))
+ abort ();
+ }
+}
+
+void
+test ()
+{
+ S c = { 0, 7 };
+ #pragma omp parallel
+ #pragma omp single
+ {
+ S d (1, 5);
+ #pragma omp taskgroup task_reduction (+: a, c) task_reduction (*: b, d)
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ #pragma omp task in_reduction (*: b, d) in_reduction (+: a, c)
+ {
+ int j;
+ a.s += 7;
+ b.s *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a) in_reduction (*: b) \
+ in_reduction (+: c) in_reduction (*: d)
+ {
+ a.s += 7;
+ b.s *= 2;
+ c.s += 9;
+ d.s *= 3;
+ foo ();
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+ c.s += 9;
+ d.s *= 3;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+ }
+#define THREEP4 (3L * 3L * 3L * 3L)
+ if (d.s != (THREEP4 * THREEP4 * THREEP4) || d.t != 5)
+ abort ();
+ }
+ if (a.s != 28 * 7 || a.t != 7 || b.s != (1L << 28) || b.t != 5
+ || c.s != 12 * 9 || c.t != 7)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test ();
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-3.C b/libgomp/testsuite/libgomp.c++/task-reduction-3.C
new file mode 100644
index 0000000..a6eccf6
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-3.C
@@ -0,0 +1,126 @@
+extern "C" void abort ();
+
+struct S { S (); S (long long int, int); ~S (); static int cnt1, cnt2, cnt3; long long int s; int t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long long int x, int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S as = { 0LL, 7 };
+S &a = as;
+S bs (1LL, 5);
+S &b = bs;
+
+void
+foo (S &c, S &d)
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: c) in_reduction (*: b, d) in_reduction (+: a)
+ {
+ a.s += 7;
+ b.s *= 2;
+ c.s += 9;
+ d.s *= 3;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+}
+
+void
+test ()
+{
+ S cs = { 0LL, 7 };
+ S &c = cs;
+ S ds (1LL, 5);
+ #pragma omp parallel
+ #pragma omp single
+ {
+ S &d = ds;
+ #pragma omp taskgroup task_reduction (+: a, c) task_reduction (*: b, d)
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ #pragma omp task in_reduction (*: b, d) in_reduction (+: a, c)
+ {
+ int j;
+ a.s += 7;
+ b.s *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a) in_reduction (*: b) \
+ in_reduction (+: c) in_reduction (*: d)
+ {
+ a.s += 7;
+ b.s *= 2;
+ c.s += 9;
+ d.s *= 3;
+ foo (c, d);
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+ c.s += 9;
+ d.s *= 3;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+ }
+#define THREEP7 (3LL * 3LL * 3LL * 3LL * 3LL * 3LL * 3LL)
+ if (d.s != (THREEP7 * THREEP7 * THREEP7 * THREEP7) || d.t != 5)
+ abort ();
+ }
+ if (a.s != 28 * 7 || a.t != 7 || b.s != (1L << 28) || b.t != 5
+ || c.s != 28 * 9 || c.t != 7)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test ();
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-4.C b/libgomp/testsuite/libgomp.c++/task-reduction-4.C
new file mode 100644
index 0000000..1d4da79
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-4.C
@@ -0,0 +1,238 @@
+extern "C" void abort ();
+
+int as[2];
+int (&a)[2] = as;
+long long int bs[7] = { 9, 11, 1, 1, 1, 13, 15 };
+long long int (&b)[7] = bs;
+int es[3] = { 5, 0, 5 };
+int (&e)[3] = es;
+int fs[5] = { 6, 7, 0, 0, 9 };
+int (&f)[5] = fs;
+int gs[4] = { 1, 0, 0, 2 };
+int (&g)[4] = gs;
+int hs[3] = { 0, 1, 4 };
+int (&h)[3] = hs;
+int ks[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+int (&k)[4][2] = ks;
+long long *ss;
+long long *&s = ss;
+long long (*ts)[2];
+long long (*&t)[2] = ts;
+
+template <typename T>
+void
+foo (T &n, T *&c, long long int *&d, T (&m)[3], T *&r, T (&o)[4], T *&p, T (&q)[4][2])
+{
+ T i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ a[0] += 7;
+ a[1] += 17;
+ b[2] *= 2;
+ b[4] *= 2;
+ c[0] += 6;
+ d[1] *= 2;
+ e[1] += 19;
+ f[2] += 21;
+ f[3] += 23;
+ g[1] += 25;
+ g[2] += 27;
+ h[0] += 29;
+ k[1][0] += 31;
+ k[2][1] += 33;
+ m[1] += 19;
+ r[2] += 21;
+ r[3] += 23;
+ o[1] += 25;
+ o[2] += 27;
+ p[0] += 29;
+ q[1][0] += 31;
+ q[2][1] += 33;
+ s[1] *= 2;
+ t[2][0] *= 2;
+ t[3][1] *= 2;
+ }
+}
+
+template <typename T>
+void
+test (T &n)
+{
+ T cs[2] = { 0, 0 };
+ T (&c)[2] = cs;
+ T ps[3] = { 0, 1, 4 };
+ T (&p)[3] = ps;
+ T qs[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+ T (&q)[4][2] = qs;
+ long long sb[4] = { 5, 1, 1, 6 };
+ long long tb[5][2] = { { 9, 10 }, { 11, 12 }, { 1, 1 }, { 1, 1 }, { 13, 14 } };
+ T ms[3] = { 5, 0, 5 };
+ T os[4] = { 1, 0, 0, 2 };
+ s = sb;
+ t = tb;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ long long int ds[] = { 1, 1 };
+ long long int (&d)[2] = ds;
+ T (&m)[3] = ms;
+ T rs[5] = { 6, 7, 0, 0, 9 };
+ T (&r)[5] = rs;
+ T (&o)[4] = os;
+ #pragma omp taskgroup task_reduction (+: a, c) task_reduction (*: b[2 * n:3 * n], d) \
+ task_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ task_reduction (+: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ task_reduction (*: t[2:2][:], s[1:n + 1])
+ {
+ T i;
+ for (i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
+ in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
+ in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ T j;
+ a[0] += 2;
+ a[1] += 3;
+ b[2] *= 2;
+ f[3] += 8;
+ g[1] += 9;
+ g[2] += 10;
+ h[0] += 11;
+ k[1][1] += 13;
+ k[2][1] += 15;
+ m[1] += 16;
+ r[2] += 8;
+ s[1] *= 2;
+ t[2][1] *= 2;
+ t[3][1] *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:])
+ {
+ m[1] += 6;
+ r[2] += 7;
+ q[1][0] += 17;
+ q[2][0] += 19;
+ a[0] += 4;
+ a[1] += 5;
+ b[3] *= 2;
+ b[4] *= 2;
+ f[3] += 18;
+ g[1] += 29;
+ g[2] += 18;
+ h[0] += 19;
+ s[2] *= 2;
+ t[2][0] *= 2;
+ t[3][0] *= 2;
+ T *cp = c;
+ long long int *dp = d;
+ T *rp = r;
+ T *pp = p;
+ foo (n, cp, dp, m, rp, o, pp, q);
+ r[3] += 18;
+ o[1] += 29;
+ o[2] += 18;
+ p[0] += 19;
+ c[0] += 4;
+ c[1] += 5;
+ d[0] *= 2;
+ e[1] += 6;
+ f[2] += 7;
+ k[1][0] += 17;
+ k[2][0] += 19;
+ }
+ r[3] += 8;
+ o[1] += 9;
+ o[2] += 10;
+ p[0] += 11;
+ q[1][1] += 13;
+ q[2][1] += 15;
+ b[3] *= 2;
+ c[0] += 4;
+ c[1] += 9;
+ d[0] *= 2;
+ e[1] += 16;
+ f[2] += 8;
+ }
+ }
+ if (d[0] != 1LL << (8 + 4)
+ || d[1] != 1LL << 16
+ || m[0] != 5
+ || m[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2] != 5
+ || r[0] != 6
+ || r[1] != 7
+ || r[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4] != 9
+ || o[0] != 1
+ || o[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3] != 2)
+ abort ();
+ }
+ if (a[0] != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1] != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0] != 9 || b[1] != 11
+ || b[2] != 1LL << (16 + 4)
+ || b[3] != 1LL << (8 + 4)
+ || b[4] != 1LL << (16 + 8)
+ || b[5] != 13 || b[6] != 15
+ || c[0] != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1] != 5 * 8 + 9 * 4
+ || e[0] != 5
+ || e[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2] != 5
+ || f[0] != 6
+ || f[1] != 7
+ || f[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4] != 9
+ || g[0] != 1
+ || g[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3] != 2
+ || h[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1] != 1 || h[2] != 4
+ || k[0][0] != 5 || k[0][1] != 6
+ || k[1][0] != 31 * 16 + 17 * 8
+ || k[1][1] != 13 * 4
+ || k[2][0] != 19 * 8
+ || k[2][1] != 33 * 16 + 15 * 4
+ || k[3][0] != 7 || k[3][1] != 8
+ || p[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1] != 1 || p[2] != 4
+ || q[0][0] != 5 || q[0][1] != 6
+ || q[1][0] != 31 * 16 + 17 * 8
+ || q[1][1] != 13 * 4
+ || q[2][0] != 19 * 8
+ || q[2][1] != 33 * 16 + 15 * 4
+ || q[3][0] != 7 || q[3][1] != 8
+ || sb[0] != 5
+ || sb[1] != 1LL << (16 + 4)
+ || sb[2] != 1LL << 8
+ || sb[3] != 6
+ || tb[0][0] != 9 || tb[0][1] != 10 || tb[1][0] != 11 || tb[1][1] != 12
+ || tb[2][0] != 1LL << (16 + 8)
+ || tb[2][1] != 1LL << 4
+ || tb[3][0] != 1LL << 8
+ || tb[3][1] != 1LL << (16 + 4)
+ || tb[4][0] != 13 || tb[4][1] != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ int n = 1;
+ test (n);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-5.C b/libgomp/testsuite/libgomp.c++/task-reduction-5.C
new file mode 100644
index 0000000..59583f1
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-5.C
@@ -0,0 +1,320 @@
+extern "C" void abort ();
+
+struct S { S (); S (long int, long int); ~S (); static int cnt1, cnt2, cnt3; long int s, t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long int x, long int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S a[2] = { { 0, 7 }, { 0, 7 } };
+S b[7] = { { 9, 5 }, { 11, 5 }, { 1, 5 }, { 1, 5 }, { 1, 5 }, { 13, 5 }, { 15, 5 } };
+S e[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+S f[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+S g[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+S h[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+S k[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+S *s;
+S (*t)[2];
+
+void
+foo (int n, S *c, S *d, S m[3], S *r, S o[4], S *p, S q[4][2])
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ a[0].s += 7;
+ a[1].s += 17;
+ b[2].s *= 2;
+ b[4].s *= 2;
+ c[0].s += 6;
+ d[1].s *= 2;
+ e[1].s += 19;
+ f[2].s += 21;
+ f[3].s += 23;
+ g[1].s += 25;
+ g[2].s += 27;
+ h[0].s += 29;
+ k[1][0].s += 31;
+ k[2][1].s += 33;
+ m[1].s += 19;
+ r[2].s += 21;
+ r[3].s += 23;
+ o[1].s += 25;
+ o[2].s += 27;
+ p[0].s += 29;
+ q[1][0].s += 31;
+ q[2][1].s += 33;
+ s[1].s *= 2;
+ t[2][0].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ }
+}
+
+void
+test (int n)
+{
+ S c[2] = { { 0, 7 }, { 0, 7 } };
+ S p[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+ S q[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+ S ss[4] = { { 5, 5 }, { 1, 5 }, { 1, 5 }, { 6, 5 } };
+ S tt[5][2] = { { { 9, 5 }, { 10, 5 } }, { { 11, 5 }, { 12, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 13, 5 }, { 14, 5 } } };
+ s = ss;
+ t = tt;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ S d[] = { { 1, 5 }, { 1, 5 } };
+ S m[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+ S r[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+ S o[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+ #pragma omp taskgroup task_reduction (+: a, c) task_reduction (*: b[2 * n:3 * n], d) \
+ task_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ task_reduction (+: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ task_reduction (*: t[2:2][:], s[1:n + 1])
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
+ in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
+ in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ int j;
+ a[0].s += 2;
+ a[1].s += 3;
+ b[2].s *= 2;
+ f[3].s += 8;
+ g[1].s += 9;
+ g[2].s += 10;
+ h[0].s += 11;
+ k[1][1].s += 13;
+ k[2][1].s += 15;
+ m[1].s += 16;
+ r[2].s += 8;
+ s[1].s *= 2;
+ t[2][1].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:])
+ {
+ m[1].s += 6;
+ r[2].s += 7;
+ q[1][0].s += 17;
+ q[2][0].s += 19;
+ a[0].s += 4;
+ a[1].s += 5;
+ b[3].s *= 2;
+ b[4].s *= 2;
+ f[3].s += 18;
+ g[1].s += 29;
+ g[2].s += 18;
+ h[0].s += 19;
+ s[2].s *= 2;
+ t[2][0].s *= 2;
+ t[3][0].s *= 2;
+ foo (n, c, d, m, r, o, p, q);
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ r[3].s += 18;
+ o[1].s += 29;
+ o[2].s += 18;
+ p[0].s += 19;
+ c[0].s += 4;
+ c[1].s += 5;
+ d[0].s *= 2;
+ e[1].s += 6;
+ f[2].s += 7;
+ k[1][0].s += 17;
+ k[2][0].s += 19;
+ }
+ r[3].s += 8;
+ o[1].s += 9;
+ o[2].s += 10;
+ p[0].s += 11;
+ q[1][1].s += 13;
+ q[2][1].s += 15;
+ b[3].s *= 2;
+ c[0].s += 4;
+ c[1].s += 9;
+ d[0].s *= 2;
+ e[1].s += 16;
+ f[2].s += 8;
+ }
+ }
+ if (d[0].s != 1LL << (8 + 4)
+ || d[1].s != 1LL << 16
+ || m[0].s != 5
+ || m[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2].s != 5
+ || r[0].s != 6
+ || r[1].s != 7
+ || r[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4].s != 9
+ || o[0].s != 1
+ || o[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3].s != 2)
+ abort ();
+ if (e[1].t != 7 || h[0].t != 7 || m[1].t != 7 || p[0].t != 7)
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if (a[z].t != 7 || c[z].t != 7 || d[z].t != 5 || f[z + 2].t != 7
+ || g[z + 1].t != 7 || r[z + 2].t != 7 || s[z + 1].t != 5 || o[z + 1].t != 7
+ || k[z + 1][0].t != 7 || k[z + 1][1].t != 7 || q[z + 1][0].t != 7 || q[z + 1][1].t != 7
+ || t[z + 2][0].t != 5 || t[z + 2][1].t != 5)
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5)
+ abort ();
+ }
+ if (a[0].s != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1].s != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0].s != 9 || b[1].s != 11
+ || b[2].s != 1LL << (16 + 4)
+ || b[3].s != 1LL << (8 + 4)
+ || b[4].s != 1LL << (16 + 8)
+ || b[5].s != 13 || b[6].s != 15
+ || c[0].s != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1].s != 5 * 8 + 9 * 4
+ || e[0].s != 5
+ || e[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2].s != 5
+ || f[0].s != 6
+ || f[1].s != 7
+ || f[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4].s != 9
+ || g[0].s != 1
+ || g[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3].s != 2
+ || h[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1].s != 1 || h[2].s != 4
+ || k[0][0].s != 5 || k[0][1].s != 6
+ || k[1][0].s != 31 * 16 + 17 * 8
+ || k[1][1].s != 13 * 4
+ || k[2][0].s != 19 * 8
+ || k[2][1].s != 33 * 16 + 15 * 4
+ || k[3][0].s != 7 || k[3][1].s != 8
+ || p[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1].s != 1 || p[2].s != 4
+ || q[0][0].s != 5 || q[0][1].s != 6
+ || q[1][0].s != 31 * 16 + 17 * 8
+ || q[1][1].s != 13 * 4
+ || q[2][0].s != 19 * 8
+ || q[2][1].s != 33 * 16 + 15 * 4
+ || q[3][0].s != 7 || q[3][1].s != 8
+ || ss[0].s != 5
+ || ss[1].s != 1LL << (16 + 4)
+ || ss[2].s != 1LL << 8
+ || ss[3].s != 6
+ || tt[0][0].s != 9 || tt[0][1].s != 10 || tt[1][0].s != 11 || tt[1][1].s != 12
+ || tt[2][0].s != 1LL << (16 + 8)
+ || tt[2][1].s != 1LL << 4
+ || tt[3][0].s != 1LL << 8
+ || tt[3][1].s != 1LL << (16 + 4)
+ || tt[4][0].s != 13 || tt[4][1].s != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test (1);
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-6.C b/libgomp/testsuite/libgomp.c++/task-reduction-6.C
new file mode 100644
index 0000000..d7f69da
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-6.C
@@ -0,0 +1,341 @@
+extern "C" void abort ();
+
+struct S { S (); S (long int, long int); ~S (); static int cnt1, cnt2, cnt3; long int s, t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long int x, long int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S as[2] = { { 0, 7 }, { 0, 7 } };
+S (&a)[2] = as;
+S bs[7] = { { 9, 5 }, { 11, 5 }, { 1, 5 }, { 1, 5 }, { 1, 5 }, { 13, 5 }, { 15, 5 } };
+S (&b)[7] = bs;
+S es[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+S (&e)[3] = es;
+S fs[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+S (&f)[5] = fs;
+S gs[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+S (&g)[4] = gs;
+S hs[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+S (&h)[3] = hs;
+S ks[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+S (&k)[4][2] = ks;
+S *ss;
+S *&s = ss;
+S (*ts)[2];
+S (*&t)[2] = ts;
+
+void
+foo (int &n, S *&c, S *&d, S (&m)[3], S *&r, S (&o)[4], S *&p, S (&q)[4][2])
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ a[0].s += 7;
+ a[1].s += 17;
+ b[2].s *= 2;
+ b[4].s *= 2;
+ c[0].s += 6;
+ d[1].s *= 2;
+ e[1].s += 19;
+ f[2].s += 21;
+ f[3].s += 23;
+ g[1].s += 25;
+ g[2].s += 27;
+ h[0].s += 29;
+ k[1][0].s += 31;
+ k[2][1].s += 33;
+ m[1].s += 19;
+ r[2].s += 21;
+ r[3].s += 23;
+ o[1].s += 25;
+ o[2].s += 27;
+ p[0].s += 29;
+ q[1][0].s += 31;
+ q[2][1].s += 33;
+ s[1].s *= 2;
+ t[2][0].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ }
+}
+
+void
+test (int &n)
+{
+ S cs[2] = { { 0, 7 }, { 0, 7 } };
+ S (&c)[2] = cs;
+ S ps[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+ S (&p)[3] = ps;
+ S qs[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+ S (&q)[4][2] = qs;
+ S sb[4] = { { 5, 5 }, { 1, 5 }, { 1, 5 }, { 6, 5 } };
+ S tb[5][2] = { { { 9, 5 }, { 10, 5 } }, { { 11, 5 }, { 12, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 13, 5 }, { 14, 5 } } };
+ S ms[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+ S os[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+ s = sb;
+ t = tb;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ S ds[] = { { 1, 5 }, { 1, 5 } };
+ S (&d)[2] = ds;
+ S (&m)[3] = ms;
+ S rs[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+ S (&r)[5] = rs;
+ S (&o)[4] = os;
+ #pragma omp taskgroup task_reduction (+: a, c) task_reduction (*: b[2 * n:3 * n], d) \
+ task_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ task_reduction (+: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ task_reduction (*: t[2:2][:], s[1:n + 1])
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
+ in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
+ in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ int j;
+ a[0].s += 2;
+ a[1].s += 3;
+ b[2].s *= 2;
+ f[3].s += 8;
+ g[1].s += 9;
+ g[2].s += 10;
+ h[0].s += 11;
+ k[1][1].s += 13;
+ k[2][1].s += 15;
+ m[1].s += 16;
+ r[2].s += 8;
+ s[1].s *= 2;
+ t[2][1].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:])
+ {
+ m[1].s += 6;
+ r[2].s += 7;
+ q[1][0].s += 17;
+ q[2][0].s += 19;
+ a[0].s += 4;
+ a[1].s += 5;
+ b[3].s *= 2;
+ b[4].s *= 2;
+ f[3].s += 18;
+ g[1].s += 29;
+ g[2].s += 18;
+ h[0].s += 19;
+ s[2].s *= 2;
+ t[2][0].s *= 2;
+ t[3][0].s *= 2;
+ S *cp = c;
+ S *dp = d;
+ S *rp = r;
+ S *pp = p;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ foo (n, cp, dp, m, rp, o, pp, q);
+ r[3].s += 18;
+ o[1].s += 29;
+ o[2].s += 18;
+ p[0].s += 19;
+ c[0].s += 4;
+ c[1].s += 5;
+ d[0].s *= 2;
+ e[1].s += 6;
+ f[2].s += 7;
+ k[1][0].s += 17;
+ k[2][0].s += 19;
+ }
+ r[3].s += 8;
+ o[1].s += 9;
+ o[2].s += 10;
+ p[0].s += 11;
+ q[1][1].s += 13;
+ q[2][1].s += 15;
+ b[3].s *= 2;
+ c[0].s += 4;
+ c[1].s += 9;
+ d[0].s *= 2;
+ e[1].s += 16;
+ f[2].s += 8;
+ }
+ }
+ if (d[0].s != 1LL << (8 + 4)
+ || d[1].s != 1LL << 16
+ || m[0].s != 5
+ || m[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2].s != 5
+ || r[0].s != 6
+ || r[1].s != 7
+ || r[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4].s != 9
+ || o[0].s != 1
+ || o[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3].s != 2)
+ abort ();
+ if (e[1].t != 7 || h[0].t != 7 || m[1].t != 7 || p[0].t != 7)
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if (a[z].t != 7 || c[z].t != 7 || d[z].t != 5 || f[z + 2].t != 7
+ || g[z + 1].t != 7 || r[z + 2].t != 7 || s[z + 1].t != 5 || o[z + 1].t != 7
+ || k[z + 1][0].t != 7 || k[z + 1][1].t != 7 || q[z + 1][0].t != 7 || q[z + 1][1].t != 7
+ || t[z + 2][0].t != 5 || t[z + 2][1].t != 5)
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5)
+ abort ();
+ }
+ if (a[0].s != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1].s != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0].s != 9 || b[1].s != 11
+ || b[2].s != 1LL << (16 + 4)
+ || b[3].s != 1LL << (8 + 4)
+ || b[4].s != 1LL << (16 + 8)
+ || b[5].s != 13 || b[6].s != 15
+ || c[0].s != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1].s != 5 * 8 + 9 * 4
+ || e[0].s != 5
+ || e[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2].s != 5
+ || f[0].s != 6
+ || f[1].s != 7
+ || f[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4].s != 9
+ || g[0].s != 1
+ || g[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3].s != 2
+ || h[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1].s != 1 || h[2].s != 4
+ || k[0][0].s != 5 || k[0][1].s != 6
+ || k[1][0].s != 31 * 16 + 17 * 8
+ || k[1][1].s != 13 * 4
+ || k[2][0].s != 19 * 8
+ || k[2][1].s != 33 * 16 + 15 * 4
+ || k[3][0].s != 7 || k[3][1].s != 8
+ || p[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1].s != 1 || p[2].s != 4
+ || q[0][0].s != 5 || q[0][1].s != 6
+ || q[1][0].s != 31 * 16 + 17 * 8
+ || q[1][1].s != 13 * 4
+ || q[2][0].s != 19 * 8
+ || q[2][1].s != 33 * 16 + 15 * 4
+ || q[3][0].s != 7 || q[3][1].s != 8
+ || sb[0].s != 5
+ || sb[1].s != 1LL << (16 + 4)
+ || sb[2].s != 1LL << 8
+ || sb[3].s != 6
+ || tb[0][0].s != 9 || tb[0][1].s != 10 || tb[1][0].s != 11 || tb[1][1].s != 12
+ || tb[2][0].s != 1LL << (16 + 8)
+ || tb[2][1].s != 1LL << 4
+ || tb[3][0].s != 1LL << 8
+ || tb[3][1].s != 1LL << (16 + 4)
+ || tb[4][0].s != 13 || tb[4][1].s != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ int n = 1;
+ test (n);
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-7.C b/libgomp/testsuite/libgomp.c++/task-reduction-7.C
new file mode 100644
index 0000000..2a4d82e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-7.C
@@ -0,0 +1,145 @@
+typedef __SIZE_TYPE__ size_t;
+extern "C" void abort ();
+
+void
+bar (int *a, int *b, int *c, int (*d)[2], int (*e)[4], int *f, int *g, size_t n)
+{
+ #pragma omp task in_reduction (*: a[:n], b[3:n], c[n:n], d[0][:n], e[0][1:n], f[:n], g[1:n])
+ {
+ a[0] *= 12;
+ a[1] *= 13;
+ b[3] *= 14;
+ b[4] *= 15;
+ c[n] *= 16;
+ c[n + 1] *= 17;
+ d[0][0] *= 18;
+ d[0][1] *= 19;
+ e[0][1] *= 20;
+ e[0][2] *= 21;
+ f[0] *= 22;
+ f[1] *= 23;
+ g[1] *= 24;
+ g[2] *= 25;
+ }
+}
+
+void
+foo (size_t n, void *x, void *y)
+{
+ int a[n], b[n + 3], c[2 * n];
+ int (*d)[n] = (int (*)[n]) x;
+ int (*e)[n * 2] = (int (*)[n * 2]) y;
+ int fb[n], gb[n * 2];
+ int (&f)[n] = fb;
+ int (&g)[n * 2] = gb;
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ a[i] = 1;
+ b[i + 3] = 1;
+ c[i + n] = 1;
+ d[0][i] = 1;
+ e[0][i + 1] = 1;
+ f[i] = 1;
+ g[i + 1] = 1;
+ }
+ #pragma omp taskgroup task_reduction (*: a, b[3:n], c[n:n], d[0][:n], e[0][1:n], f, g[1:n])
+ {
+ bar (a, b, c, (int (*)[2]) d, (int (*)[4]) e, &f[0], &g[0], n);
+ #pragma omp task in_reduction (*: a, b[3:n], c[n:n], d[0][:n], e[0][1:n], f, g[1:n])
+ {
+ a[0] *= 2;
+ a[1] *= 3;
+ b[3] *= 4;
+ b[4] *= 5;
+ c[n] *= 6;
+ c[n + 1] *= 7;
+ d[0][0] *= 8;
+ d[0][1] *= 9;
+ e[0][1] *= 10;
+ e[0][2] *= 11;
+ f[0] *= 12;
+ f[1] *= 13;
+ g[1] *= 14;
+ g[2] *= 15;
+ }
+ n = 0;
+ }
+ if (a[0] != 24 || a[1] != 39 || b[3] != 56 || b[4] != 75)
+ abort ();
+ if (c[2] != 96 || c[3] != 119 || d[0][0] != 144 || d[0][1] != 171)
+ abort ();
+ if (e[0][1] != 200 || e[0][2] != 231 || f[0] != 264 || f[1] != 299)
+ abort ();
+ if (g[1] != 336 || g[2] != 375)
+ abort ();
+}
+
+void
+baz (size_t n, void *x, void *y)
+{
+ int a[n], b[n + 3], c[2 * n];
+ int (*d)[n] = (int (*)[n]) x;
+ int (*e)[n * 2] = (int (*)[n * 2]) y;
+ int fb[n], gb[n * 2];
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ a[i] = 1;
+ b[i + 3] = 1;
+ c[i + n] = 1;
+ d[0][i] = 1;
+ e[0][i + 1] = 1;
+ fb[i] = 1;
+ gb[i + 1] = 1;
+ }
+ #pragma omp parallel num_threads(2)
+ #pragma omp master
+ {
+ int (&f)[n] = fb;
+ int (&g)[n * 2] = gb;
+ #pragma omp taskgroup task_reduction (*: a, b[3:n], c[n:n], d[0][:n], e[0][1:n], f, g[1:n])
+ {
+ bar (a, b, c, (int (*)[2]) d, (int (*)[4]) e, &f[0], &g[0], n);
+ #pragma omp task in_reduction (*: a, b[3:n], c[n:n], d[0][:n], e[0][1:n], f, g[1:n])
+ {
+ a[0] *= 2;
+ a[1] *= 3;
+ b[3] *= 4;
+ b[4] *= 5;
+ c[n] *= 6;
+ c[n + 1] *= 7;
+ d[0][0] *= 8;
+ d[0][1] *= 9;
+ e[0][1] *= 10;
+ e[0][2] *= 11;
+ f[0] *= 12;
+ f[1] *= 13;
+ g[1] *= 14;
+ g[2] *= 15;
+ }
+ n = 0;
+ }
+ }
+ if (a[0] != 24 || a[1] != 39 || b[3] != 56 || b[4] != 75)
+ abort ();
+ if (c[2] != 96 || c[3] != 119 || d[0][0] != 144 || d[0][1] != 171)
+ abort ();
+ if (e[0][1] != 200 || e[0][2] != 231 || fb[0] != 264 || fb[1] != 299)
+ abort ();
+ if (gb[1] != 336 || gb[2] != 375)
+ abort ();
+}
+
+int
+main ()
+{
+ int d[2], e[4];
+ volatile int two;
+ two = 2;
+ #pragma omp parallel num_threads (2)
+ #pragma omp master
+ foo (two, (void *) d, (void *) e);
+ baz (two, (void *) d, (void *) e);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-8.C b/libgomp/testsuite/libgomp.c++/task-reduction-8.C
new file mode 100644
index 0000000..26737a3
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-8.C
@@ -0,0 +1,70 @@
+extern "C" void abort ();
+
+int as;
+int &a = as;
+long int bs = 1;
+long int &b = bs;
+
+template <typename T, typename U>
+void
+foo (T &c, U &d)
+{
+ T i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (*: d) in_reduction (+: c) \
+ in_reduction (+: a) in_reduction (*: b)
+ {
+ a += 7;
+ b *= 2;
+ c += 9;
+ d *= 3;
+ }
+}
+
+template <typename T, typename U>
+void
+bar ()
+{
+ T cs = 0;
+ T &c = cs;
+ U ds = 1;
+ #pragma omp parallel if (0)
+ {
+ U &d = ds;
+ #pragma omp parallel reduction (task, +: a, c) reduction (task, *: b, d)
+ {
+ T i;
+ #pragma omp for
+ for (i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b, d)
+ {
+ T j;
+ a += 7;
+ b *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b, d)
+ {
+ a += 7;
+ b *= 2;
+ c += 9;
+ d *= 3;
+ foo (c, d);
+ }
+ c += 9;
+ d *= 3;
+ }
+ }
+#define THREEP4 (3LL * 3LL * 3LL * 3LL)
+ if (d != (THREEP4 * THREEP4 * THREEP4 * THREEP4 * THREEP4 * THREEP4
+ * THREEP4))
+ abort ();
+ }
+ if (a != 28 * 7 || b != (1L << 28) || c != 28 * 9)
+ abort ();
+}
+
+int
+main ()
+{
+ bar<int, long long int> ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/task-reduction-9.C b/libgomp/testsuite/libgomp.c++/task-reduction-9.C
new file mode 100644
index 0000000..068a7bb
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/task-reduction-9.C
@@ -0,0 +1,128 @@
+#include <omp.h>
+#include <stdlib.h>
+
+struct S { S (); S (long int, long int); ~S (); static int cnt1, cnt2, cnt3; long int s, t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long int x, long int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S a = { 0, 7 };
+S b (1, 5);
+
+void
+foo ()
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (*: b) in_reduction (+: a)
+ {
+ a.s += 7;
+ b.s *= 2;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9))
+ abort ();
+ }
+}
+
+void
+test ()
+{
+ S c = { 0, 7 };
+ int t;
+ #pragma omp parallel num_threads (1)
+ {
+ S d (1, 5);
+ int r = 0;
+ #pragma omp parallel reduction (task, +: a, c) reduction (task, *: b, d) \
+ reduction (+: r)
+ {
+ int i;
+ #pragma omp master
+ t = omp_get_num_threads ();
+ r++;
+ a.s += 3;
+ c.s += 4;
+ #pragma omp for
+ for (i = 0; i < 4; i++)
+ #pragma omp task in_reduction (*: b, d) in_reduction (+: a, c)
+ {
+ int j;
+ a.s += 7;
+ b.s *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a) in_reduction (*: b) \
+ in_reduction (+: c) in_reduction (*: d)
+ {
+ a.s += 7;
+ b.s *= 2;
+ c.s += 9;
+ d.s *= 3;
+ foo ();
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+ c.s += 9;
+ d.s *= 3;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+ }
+#define THREEP4 (3L * 3L * 3L * 3L)
+ if (d.s != (THREEP4 * THREEP4 * THREEP4) || d.t != 5 || r != t)
+ abort ();
+ }
+ if (a.s != 28 * 7 + 3 * t || a.t != 7 || b.s != (1L << 28) || b.t != 5
+ || c.s != 12 * 9 + 4 * t || c.t != 7)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test ();
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/taskloop-reduction-1.C b/libgomp/testsuite/libgomp.c++/taskloop-reduction-1.C
new file mode 100644
index 0000000..f7fb9ca
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/taskloop-reduction-1.C
@@ -0,0 +1,153 @@
+extern "C" void abort ();
+
+struct S { S (); S (unsigned long long int, int); ~S (); static int cnt1, cnt2, cnt3; unsigned long long int s; int t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (unsigned long long int x, int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+rbar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+rbaz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) \
+ initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : rbaz (&omp_out, &omp_in)) \
+ initializer (rbar (&omp_priv, &omp_orig))
+
+S gs = { 0, 7 };
+S &g = gs;
+S hs (1, 5);
+S &h = hs;
+
+int
+foo (int *a, int &b)
+{
+ int xs = 0;
+ int &x = xs;
+ #pragma omp taskloop reduction (+:x) in_reduction (+:b)
+ for (int i = 0; i < 64; i++)
+ {
+ x += a[i];
+ b += a[i] * 2;
+ }
+ return x;
+}
+
+unsigned long long int
+bar (int *a, unsigned long long int &b)
+{
+ unsigned long long int xs = 1;
+ unsigned long long int &x = xs;
+ #pragma omp taskloop reduction (*:x) in_reduction (*:b)
+ for (int i = 0; i < 64; i++)
+ {
+ #pragma omp task in_reduction (*:x)
+ x *= a[i];
+ #pragma omp task in_reduction (*:b)
+ b *= (3 - a[i]);
+ }
+ return x;
+}
+
+void
+baz (int i, int *a, int *c)
+{
+ #pragma omp task in_reduction (*:h) in_reduction (+:g)
+ {
+ g.s += 7 * a[i];
+ h.s *= (3 - c[i]);
+ if ((g.t != 7 && g.t != 3) || (h.t != 5 && h.t != 9))
+ abort ();
+ }
+}
+
+void
+test ()
+{
+ int i, j, a[64], b = 0, c[64];
+ unsigned long long int d = 1, e;
+ S ms (0, 7);
+ for (i = 0; i < 64; i++)
+ {
+ a[i] = 2 * i;
+ c[i] = 1 + ((i % 3) != 1);
+ }
+ #pragma omp parallel
+ #pragma omp master
+ {
+ S ns = { 1, 5 };
+ S &m = ms;
+ S &n = ns;
+ #pragma omp taskgroup task_reduction (+:b)
+ j = foo (a, b);
+ #pragma omp taskgroup task_reduction (*:d)
+ e = bar (c, d);
+ #pragma omp taskloop reduction (+: g, m) reduction (*: h, n)
+ for (i = 0; i < 64; ++i)
+ {
+ g.s += 3 * a[i];
+ h.s *= (3 - c[i]);
+ m.s += 4 * a[i];
+ n.s *= c[i];
+ if ((g.t != 7 && g.t != 3) || (h.t != 5 && h.t != 9)
+ || (m.t != 7 && m.t != 3) || (n.t != 5 && n.t != 9))
+ abort ();
+ baz (i, a, c);
+ }
+ if (n.s != (1ULL << 43) || n.t != 5)
+ abort ();
+ }
+ if (j != 63 * 64 || b != 63 * 64 * 2)
+ abort ();
+ if (e != (1ULL << 43) || d != (1ULL << 21))
+ abort ();
+ if (g.s != 63 * 64 * 10 || g.t != 7)
+ abort ();
+ if (h.s != (1ULL << 42) || h.t != 5)
+ abort ();
+ if (ms.s != 63 * 64 * 4 || ms.t != 7)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test ();
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/taskloop-reduction-2.C b/libgomp/testsuite/libgomp.c++/taskloop-reduction-2.C
new file mode 100644
index 0000000..f1de5da
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/taskloop-reduction-2.C
@@ -0,0 +1,253 @@
+extern "C" void abort ();
+
+int as[2];
+int (&a)[2] = as;
+long long int bs[7] = { 9, 11, 1, 1, 1, 13, 15 };
+long long int (&b)[7] = bs;
+int es[3] = { 5, 0, 5 };
+int (&e)[3] = es;
+int fs[5] = { 6, 7, 0, 0, 9 };
+int (&f)[5] = fs;
+int gs[4] = { 1, 0, 0, 2 };
+int (&g)[4] = gs;
+int hs[3] = { 0, 1, 4 };
+int (&h)[3] = hs;
+int ks[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+int (&k)[4][2] = ks;
+long long *ss;
+long long *&s = ss;
+long long (*ts)[2];
+long long (*&t)[2] = ts;
+struct U { U (); ~U () {}; U (const U &); int u[4]; };
+
+U::U
+()
+{
+ u[0] = 0; u[1] = 1; u[2] = 2; u[3] = 3;
+}
+
+U::U
+(const U &r)
+{
+ u[0] = r.u[0]; u[1] = r.u[1]; u[2] = r.u[2]; u[3] = r.u[3];
+}
+
+void
+foo (int &n, int *&c, long long int *&d, int (&m)[3], int *&r, int (&o)[4], int *&p, int (&q)[4][2])
+{
+ int i;
+ U u;
+ u.u[2] = 8;
+ #pragma omp taskloop in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:]) firstprivate (u) nogroup
+ for (i = 0; i < 2; i++)
+ {
+ a[0] += 7;
+ a[1] += 17;
+ b[2] *= 2;
+ b[4] *= 2;
+ c[0] += 6;
+ d[1] *= 2;
+ e[1] += 19;
+ f[2] += 21;
+ f[3] += 23;
+ g[1] += 25;
+ g[2] += 27;
+ h[0] += 29;
+ k[1][0] += 31;
+ k[2][1] += 33;
+ m[1] += 19;
+ r[2] += 21;
+ r[3] += 23;
+ o[1] += 25;
+ o[2] += 27;
+ p[0] += 29;
+ q[1][0] += 31;
+ q[2][1] += 33;
+ s[1] *= 2;
+ t[2][0] *= 2;
+ t[3][1] *= 2;
+ if (u.u[2] != 8)
+ abort ();
+ }
+}
+
+void
+test (int &n)
+{
+ int cs[2] = { 0, 0 };
+ int (&c)[2] = cs;
+ int ps[3] = { 0, 1, 4 };
+ int (&p)[3] = ps;
+ int qs[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+ int (&q)[4][2] = qs;
+ long long sb[4] = { 5, 1, 1, 6 };
+ long long tb[5][2] = { { 9, 10 }, { 11, 12 }, { 1, 1 }, { 1, 1 }, { 13, 14 } };
+ int ms[3] = { 5, 0, 5 };
+ int os[4] = { 1, 0, 0, 2 };
+ s = sb;
+ t = tb;
+ U u;
+ u.u[2] = 10;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ long long int ds[] = { 1, 1 };
+ long long int (&d)[2] = ds;
+ int (&m)[3] = ms;
+ int rs[5] = { 6, 7, 0, 0, 9 };
+ int (&r)[5] = rs;
+ int (&o)[4] = os;
+ int i;
+ #pragma omp taskloop reduction (+: a, c) reduction (*: b[2 * n:3 * n], d) \
+ reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ reduction (+: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ reduction (*: t[2:2][:], s[1:n + 1]) firstprivate (u)
+ for (i = 0; i < 4; i++)
+ {
+ int j;
+ a[0] += 2;
+ a[1] += 3;
+ b[2] *= 2;
+ f[3] += 8;
+ g[1] += 9;
+ g[2] += 10;
+ h[0] += 11;
+ k[1][1] += 13;
+ k[2][1] += 15;
+ m[1] += 16;
+ r[2] += 8;
+ s[1] *= 2;
+ t[2][1] *= 2;
+ t[3][1] *= 2;
+ if (u.u[2] != 10)
+ abort ();
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:]) firstprivate (u)
+ {
+ m[1] += 6;
+ r[2] += 7;
+ q[1][0] += 17;
+ q[2][0] += 19;
+ a[0] += 4;
+ a[1] += 5;
+ b[3] *= 2;
+ b[4] *= 2;
+ f[3] += 18;
+ g[1] += 29;
+ g[2] += 18;
+ h[0] += 19;
+ s[2] *= 2;
+ t[2][0] *= 2;
+ t[3][0] *= 2;
+ int *cp = c;
+ long long int *dp = d;
+ int *rp = r;
+ int *pp = p;
+ foo (n, cp, dp, m, rp, o, pp, q);
+ if (u.u[2] != 10)
+ abort ();
+ r[3] += 18;
+ o[1] += 29;
+ o[2] += 18;
+ p[0] += 19;
+ c[0] += 4;
+ c[1] += 5;
+ d[0] *= 2;
+ e[1] += 6;
+ f[2] += 7;
+ k[1][0] += 17;
+ k[2][0] += 19;
+ }
+ r[3] += 8;
+ o[1] += 9;
+ o[2] += 10;
+ p[0] += 11;
+ q[1][1] += 13;
+ q[2][1] += 15;
+ b[3] *= 2;
+ c[0] += 4;
+ c[1] += 9;
+ d[0] *= 2;
+ e[1] += 16;
+ f[2] += 8;
+ }
+ if (d[0] != 1LL << (8 + 4)
+ || d[1] != 1LL << 16
+ || m[0] != 5
+ || m[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2] != 5
+ || r[0] != 6
+ || r[1] != 7
+ || r[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4] != 9
+ || o[0] != 1
+ || o[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3] != 2)
+ abort ();
+ }
+ if (a[0] != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1] != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0] != 9 || b[1] != 11
+ || b[2] != 1LL << (16 + 4)
+ || b[3] != 1LL << (8 + 4)
+ || b[4] != 1LL << (16 + 8)
+ || b[5] != 13 || b[6] != 15
+ || c[0] != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1] != 5 * 8 + 9 * 4
+ || e[0] != 5
+ || e[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2] != 5
+ || f[0] != 6
+ || f[1] != 7
+ || f[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4] != 9
+ || g[0] != 1
+ || g[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3] != 2
+ || h[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1] != 1 || h[2] != 4
+ || k[0][0] != 5 || k[0][1] != 6
+ || k[1][0] != 31 * 16 + 17 * 8
+ || k[1][1] != 13 * 4
+ || k[2][0] != 19 * 8
+ || k[2][1] != 33 * 16 + 15 * 4
+ || k[3][0] != 7 || k[3][1] != 8
+ || p[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1] != 1 || p[2] != 4
+ || q[0][0] != 5 || q[0][1] != 6
+ || q[1][0] != 31 * 16 + 17 * 8
+ || q[1][1] != 13 * 4
+ || q[2][0] != 19 * 8
+ || q[2][1] != 33 * 16 + 15 * 4
+ || q[3][0] != 7 || q[3][1] != 8
+ || sb[0] != 5
+ || sb[1] != 1LL << (16 + 4)
+ || sb[2] != 1LL << 8
+ || sb[3] != 6
+ || tb[0][0] != 9 || tb[0][1] != 10 || tb[1][0] != 11 || tb[1][1] != 12
+ || tb[2][0] != 1LL << (16 + 8)
+ || tb[2][1] != 1LL << 4
+ || tb[3][0] != 1LL << 8
+ || tb[3][1] != 1LL << (16 + 4)
+ || tb[4][0] != 13 || tb[4][1] != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ int n = 1;
+ test (n);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/taskloop-reduction-3.C b/libgomp/testsuite/libgomp.c++/taskloop-reduction-3.C
new file mode 100644
index 0000000..0588e47
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/taskloop-reduction-3.C
@@ -0,0 +1,314 @@
+extern "C" void abort ();
+
+struct S { S (); S (long int, long int); ~S (); static int cnt1, cnt2, cnt3; long int s, t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long int x, long int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S a[2] = { { 0, 7 }, { 0, 7 } };
+S b[7] = { { 9, 5 }, { 11, 5 }, { 1, 5 }, { 1, 5 }, { 1, 5 }, { 13, 5 }, { 15, 5 } };
+S e[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+S f[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+S g[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+S h[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+S k[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+S *s;
+S (*t)[2];
+
+void
+foo (int n, S *c, S *d, S m[3], S *r, S o[4], S *p, S q[4][2])
+{
+ int i;
+ #pragma omp taskloop in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:]) nogroup
+ for (i = 0; i < 2; i++)
+ {
+ a[0].s += 7;
+ a[1].s += 17;
+ b[2].s *= 2;
+ b[4].s *= 2;
+ c[0].s += 6;
+ d[1].s *= 2;
+ e[1].s += 19;
+ f[2].s += 21;
+ f[3].s += 23;
+ g[1].s += 25;
+ g[2].s += 27;
+ h[0].s += 29;
+ k[1][0].s += 31;
+ k[2][1].s += 33;
+ m[1].s += 19;
+ r[2].s += 21;
+ r[3].s += 23;
+ o[1].s += 25;
+ o[2].s += 27;
+ p[0].s += 29;
+ q[1][0].s += 31;
+ q[2][1].s += 33;
+ s[1].s *= 2;
+ t[2][0].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ }
+}
+
+void
+test (int n)
+{
+ S c[2] = { { 0, 7 }, { 0, 7 } };
+ S p[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+ S q[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+ S ss[4] = { { 5, 5 }, { 1, 5 }, { 1, 5 }, { 6, 5 } };
+ S tt[5][2] = { { { 9, 5 }, { 10, 5 } }, { { 11, 5 }, { 12, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 13, 5 }, { 14, 5 } } };
+ s = ss;
+ t = tt;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ S d[] = { { 1, 5 }, { 1, 5 } };
+ S m[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+ S r[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+ S o[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+ int i;
+ #pragma omp taskloop reduction (+: a, c) reduction (*: b[2 * n:3 * n], d) \
+ reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ reduction (+: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ reduction (*: t[2:2][:], s[1:n + 1])
+ for (i = 0; i < 4; i++)
+ {
+ int j;
+ a[0].s += 2;
+ a[1].s += 3;
+ b[2].s *= 2;
+ f[3].s += 8;
+ g[1].s += 9;
+ g[2].s += 10;
+ h[0].s += 11;
+ k[1][1].s += 13;
+ k[2][1].s += 15;
+ m[1].s += 16;
+ r[2].s += 8;
+ s[1].s *= 2;
+ t[2][1].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ #pragma omp taskloop in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:]) nogroup
+ for (j = 0; j < 2; j++)
+ {
+ m[1].s += 6;
+ r[2].s += 7;
+ q[1][0].s += 17;
+ q[2][0].s += 19;
+ a[0].s += 4;
+ a[1].s += 5;
+ b[3].s *= 2;
+ b[4].s *= 2;
+ f[3].s += 18;
+ g[1].s += 29;
+ g[2].s += 18;
+ h[0].s += 19;
+ s[2].s *= 2;
+ t[2][0].s *= 2;
+ t[3][0].s *= 2;
+ foo (n, c, d, m, r, o, p, q);
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ r[3].s += 18;
+ o[1].s += 29;
+ o[2].s += 18;
+ p[0].s += 19;
+ c[0].s += 4;
+ c[1].s += 5;
+ d[0].s *= 2;
+ e[1].s += 6;
+ f[2].s += 7;
+ k[1][0].s += 17;
+ k[2][0].s += 19;
+ }
+ r[3].s += 8;
+ o[1].s += 9;
+ o[2].s += 10;
+ p[0].s += 11;
+ q[1][1].s += 13;
+ q[2][1].s += 15;
+ b[3].s *= 2;
+ c[0].s += 4;
+ c[1].s += 9;
+ d[0].s *= 2;
+ e[1].s += 16;
+ f[2].s += 8;
+ }
+ if (d[0].s != 1LL << (8 + 4)
+ || d[1].s != 1LL << 16
+ || m[0].s != 5
+ || m[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2].s != 5
+ || r[0].s != 6
+ || r[1].s != 7
+ || r[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4].s != 9
+ || o[0].s != 1
+ || o[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3].s != 2)
+ abort ();
+ if (e[1].t != 7 || h[0].t != 7 || m[1].t != 7 || p[0].t != 7)
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if (a[z].t != 7 || c[z].t != 7 || d[z].t != 5 || f[z + 2].t != 7
+ || g[z + 1].t != 7 || r[z + 2].t != 7 || s[z + 1].t != 5 || o[z + 1].t != 7
+ || k[z + 1][0].t != 7 || k[z + 1][1].t != 7 || q[z + 1][0].t != 7 || q[z + 1][1].t != 7
+ || t[z + 2][0].t != 5 || t[z + 2][1].t != 5)
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5)
+ abort ();
+ }
+ if (a[0].s != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1].s != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0].s != 9 || b[1].s != 11
+ || b[2].s != 1LL << (16 + 4)
+ || b[3].s != 1LL << (8 + 4)
+ || b[4].s != 1LL << (16 + 8)
+ || b[5].s != 13 || b[6].s != 15
+ || c[0].s != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1].s != 5 * 8 + 9 * 4
+ || e[0].s != 5
+ || e[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2].s != 5
+ || f[0].s != 6
+ || f[1].s != 7
+ || f[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4].s != 9
+ || g[0].s != 1
+ || g[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3].s != 2
+ || h[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1].s != 1 || h[2].s != 4
+ || k[0][0].s != 5 || k[0][1].s != 6
+ || k[1][0].s != 31 * 16 + 17 * 8
+ || k[1][1].s != 13 * 4
+ || k[2][0].s != 19 * 8
+ || k[2][1].s != 33 * 16 + 15 * 4
+ || k[3][0].s != 7 || k[3][1].s != 8
+ || p[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1].s != 1 || p[2].s != 4
+ || q[0][0].s != 5 || q[0][1].s != 6
+ || q[1][0].s != 31 * 16 + 17 * 8
+ || q[1][1].s != 13 * 4
+ || q[2][0].s != 19 * 8
+ || q[2][1].s != 33 * 16 + 15 * 4
+ || q[3][0].s != 7 || q[3][1].s != 8
+ || ss[0].s != 5
+ || ss[1].s != 1LL << (16 + 4)
+ || ss[2].s != 1LL << 8
+ || ss[3].s != 6
+ || tt[0][0].s != 9 || tt[0][1].s != 10 || tt[1][0].s != 11 || tt[1][1].s != 12
+ || tt[2][0].s != 1LL << (16 + 8)
+ || tt[2][1].s != 1LL << 4
+ || tt[3][0].s != 1LL << 8
+ || tt[3][1].s != 1LL << (16 + 4)
+ || tt[4][0].s != 13 || tt[4][1].s != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test (1);
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/taskloop-reduction-4.C b/libgomp/testsuite/libgomp.c++/taskloop-reduction-4.C
new file mode 100644
index 0000000..41c7040
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/taskloop-reduction-4.C
@@ -0,0 +1,315 @@
+extern "C" void abort ();
+
+struct S { S (); S (long int, long int); ~S (); static int cnt1, cnt2, cnt3; long int s, t; };
+
+int S::cnt1;
+int S::cnt2;
+int S::cnt3;
+
+S::S ()
+{
+ #pragma omp atomic
+ cnt1++;
+}
+
+S::S (long int x, long int y) : s (x), t (y)
+{
+ #pragma omp atomic update
+ ++cnt2;
+}
+
+S::~S ()
+{
+ #pragma omp atomic
+ cnt3 = cnt3 + 1;
+ if (t < 3 || t > 9 || (t & 1) == 0)
+ abort ();
+}
+
+void
+bar (S *p, S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (S *o, S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
+#pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+S a[2] = { { 0, 7 }, { 0, 7 } };
+S b[7] = { { 9, 5 }, { 11, 5 }, { 1, 5 }, { 1, 5 }, { 1, 5 }, { 13, 5 }, { 15, 5 } };
+S e[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+S f[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+S g[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+S h[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+S k[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+S *s;
+S (*t)[2];
+
+template <int N>
+void
+foo (int n, S *c, S *d, S m[3], S *r, S o[4], S *p, S q[4][2])
+{
+ int i;
+ #pragma omp taskloop in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ reduction (default, +: o[n:n*2], m[1], p[0]) in_reduction (+: k[1:2][:], f[2:2]) \
+ reduction (+: q[1:2][:], r[2:2]) in_reduction (+: g[n:n*2], e[1], h[0]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ for (i = 0; i < 2; i++)
+ {
+ a[0].s += 7;
+ a[1].s += 17;
+ b[2].s *= 2;
+ b[4].s *= 2;
+ c[0].s += 6;
+ d[1].s *= 2;
+ e[1].s += 19;
+ f[2].s += 21;
+ f[3].s += 23;
+ g[1].s += 25;
+ g[2].s += 27;
+ h[0].s += 29;
+ k[1][0].s += 31;
+ k[2][1].s += 33;
+ m[1].s += 19;
+ r[2].s += 21;
+ r[3].s += 23;
+ o[1].s += 25;
+ o[2].s += 27;
+ p[0].s += 29;
+ q[1][0].s += 31;
+ q[2][1].s += 33;
+ s[1].s *= 2;
+ t[2][0].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ }
+}
+
+template <typename T>
+void
+test (int n)
+{
+ T c[2] = { { 0, 7 }, { 0, 7 } };
+ T p[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
+ T q[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
+ T ss[4] = { { 5, 5 }, { 1, 5 }, { 1, 5 }, { 6, 5 } };
+ T tt[5][2] = { { { 9, 5 }, { 10, 5 } }, { { 11, 5 }, { 12, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 13, 5 }, { 14, 5 } } };
+ s = ss;
+ t = tt;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ T d[] = { { 1, 5 }, { 1, 5 } };
+ T m[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
+ T r[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
+ T o[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
+ int i;
+ #pragma omp taskloop reduction (+: a, c) reduction (default, *: b[2 * n:3 * n], d) \
+ reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ reduction (+: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ reduction (*: t[2:2][:], s[1:n + 1])
+ for (i = 0; i < 4; i++)
+ {
+ int j;
+ a[0].s += 2;
+ a[1].s += 3;
+ b[2].s *= 2;
+ f[3].s += 8;
+ g[1].s += 9;
+ g[2].s += 10;
+ h[0].s += 11;
+ k[1][1].s += 13;
+ k[2][1].s += 15;
+ m[1].s += 16;
+ r[2].s += 8;
+ s[1].s *= 2;
+ t[2][1].s *= 2;
+ t[3][1].s *= 2;
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ #pragma omp taskloop in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:]) nogroup
+ for (j = 0; j < 2; j++)
+ {
+ m[1].s += 6;
+ r[2].s += 7;
+ q[1][0].s += 17;
+ q[2][0].s += 19;
+ a[0].s += 4;
+ a[1].s += 5;
+ b[3].s *= 2;
+ b[4].s *= 2;
+ f[3].s += 18;
+ g[1].s += 29;
+ g[2].s += 18;
+ h[0].s += 19;
+ s[2].s *= 2;
+ t[2][0].s *= 2;
+ t[3][0].s *= 2;
+ foo<0> (n, c, d, m, r, o, p, q);
+ if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
+ || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
+ || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
+ || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
+ || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
+ || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
+ || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
+ || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5 && b[z + 2].t != 9)
+ abort ();
+ r[3].s += 18;
+ o[1].s += 29;
+ o[2].s += 18;
+ p[0].s += 19;
+ c[0].s += 4;
+ c[1].s += 5;
+ d[0].s *= 2;
+ e[1].s += 6;
+ f[2].s += 7;
+ k[1][0].s += 17;
+ k[2][0].s += 19;
+ }
+ r[3].s += 8;
+ o[1].s += 9;
+ o[2].s += 10;
+ p[0].s += 11;
+ q[1][1].s += 13;
+ q[2][1].s += 15;
+ b[3].s *= 2;
+ c[0].s += 4;
+ c[1].s += 9;
+ d[0].s *= 2;
+ e[1].s += 16;
+ f[2].s += 8;
+ }
+ if (d[0].s != 1LL << (8 + 4)
+ || d[1].s != 1LL << 16
+ || m[0].s != 5
+ || m[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2].s != 5
+ || r[0].s != 6
+ || r[1].s != 7
+ || r[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4].s != 9
+ || o[0].s != 1
+ || o[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3].s != 2)
+ abort ();
+ if (e[1].t != 7 || h[0].t != 7 || m[1].t != 7 || p[0].t != 7)
+ abort ();
+ for (int z = 0; z < 2; z++)
+ if (a[z].t != 7 || c[z].t != 7 || d[z].t != 5 || f[z + 2].t != 7
+ || g[z + 1].t != 7 || r[z + 2].t != 7 || s[z + 1].t != 5 || o[z + 1].t != 7
+ || k[z + 1][0].t != 7 || k[z + 1][1].t != 7 || q[z + 1][0].t != 7 || q[z + 1][1].t != 7
+ || t[z + 2][0].t != 5 || t[z + 2][1].t != 5)
+ abort ();
+ for (int z = 0; z < 3; z++)
+ if (b[z + 2].t != 5)
+ abort ();
+ }
+ if (a[0].s != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1].s != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0].s != 9 || b[1].s != 11
+ || b[2].s != 1LL << (16 + 4)
+ || b[3].s != 1LL << (8 + 4)
+ || b[4].s != 1LL << (16 + 8)
+ || b[5].s != 13 || b[6].s != 15
+ || c[0].s != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1].s != 5 * 8 + 9 * 4
+ || e[0].s != 5
+ || e[1].s != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2].s != 5
+ || f[0].s != 6
+ || f[1].s != 7
+ || f[2].s != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3].s != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4].s != 9
+ || g[0].s != 1
+ || g[1].s != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2].s != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3].s != 2
+ || h[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1].s != 1 || h[2].s != 4
+ || k[0][0].s != 5 || k[0][1].s != 6
+ || k[1][0].s != 31 * 16 + 17 * 8
+ || k[1][1].s != 13 * 4
+ || k[2][0].s != 19 * 8
+ || k[2][1].s != 33 * 16 + 15 * 4
+ || k[3][0].s != 7 || k[3][1].s != 8
+ || p[0].s != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1].s != 1 || p[2].s != 4
+ || q[0][0].s != 5 || q[0][1].s != 6
+ || q[1][0].s != 31 * 16 + 17 * 8
+ || q[1][1].s != 13 * 4
+ || q[2][0].s != 19 * 8
+ || q[2][1].s != 33 * 16 + 15 * 4
+ || q[3][0].s != 7 || q[3][1].s != 8
+ || ss[0].s != 5
+ || ss[1].s != 1LL << (16 + 4)
+ || ss[2].s != 1LL << 8
+ || ss[3].s != 6
+ || tt[0][0].s != 9 || tt[0][1].s != 10 || tt[1][0].s != 11 || tt[1][1].s != 12
+ || tt[2][0].s != 1LL << (16 + 8)
+ || tt[2][1].s != 1LL << 4
+ || tt[3][0].s != 1LL << 8
+ || tt[3][1].s != 1LL << (16 + 4)
+ || tt[4][0].s != 13 || tt[4][1].s != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
+ test<S> (1);
+ if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/cancel-parallel-1.c b/libgomp/testsuite/libgomp.c-c++-common/cancel-parallel-1.c
new file mode 100644
index 0000000..77395e2
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/cancel-parallel-1.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-set-target-env-var OMP_CANCELLATION "true" } */
+
+#include <stdlib.h>
+#include <omp.h>
+
+int
+main ()
+{
+ int a[64];
+ #pragma omp parallel
+ {
+ #pragma omp barrier
+ if (omp_get_thread_num () == 0)
+ {
+ #pragma omp cancel parallel
+ }
+ #pragma omp for
+ for (int i = 0; i < 64; i++)
+ a[i] = i;
+ if (omp_get_cancellation ())
+ abort ();
+ }
+ #pragma omp parallel
+ {
+ #pragma omp barrier
+ if (omp_get_thread_num () == 0)
+ {
+ #pragma omp cancel parallel
+ }
+ #pragma omp taskgroup
+ {
+ #pragma omp for
+ for (int i = 0; i < 64; i++)
+ #pragma omp task
+ a[i] += i;
+ if (omp_get_cancellation ())
+ abort ();
+ }
+ }
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/cancel-taskgroup-3.c b/libgomp/testsuite/libgomp.c-c++-common/cancel-taskgroup-3.c
new file mode 100644
index 0000000..b9af835
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/cancel-taskgroup-3.c
@@ -0,0 +1,68 @@
+/* { dg-do run } */
+/* { dg-set-target-env-var OMP_CANCELLATION "true" } */
+
+#include <stdlib.h>
+#include <omp.h>
+
+int
+main ()
+{
+ int a = 0, i;
+ #pragma omp parallel
+ #pragma omp taskgroup
+ {
+ #pragma omp task
+ {
+ #pragma omp cancel taskgroup
+ if (omp_get_cancellation ())
+ abort ();
+ }
+ #pragma omp taskwait
+ #pragma omp for reduction (task, +: a)
+ for (i = 0; i < 64; ++i)
+ {
+ a++;
+ #pragma omp task in_reduction (+: a)
+ {
+ volatile int zero = 0;
+ a += zero;
+ if (omp_get_cancellation ())
+ abort ();
+ }
+ }
+ if (a != 64)
+ abort ();
+ #pragma omp task
+ {
+ if (omp_get_cancellation ())
+ abort ();
+ }
+ }
+ a = 0;
+ #pragma omp parallel
+ #pragma omp taskgroup
+ {
+ #pragma omp taskwait
+ #pragma omp for reduction (task, +: a)
+ for (i = 0; i < 64; ++i)
+ {
+ a++;
+ #pragma omp task in_reduction (+: a)
+ {
+ volatile int zero = 0;
+ a += zero;
+ #pragma omp cancel taskgroup
+ if (omp_get_cancellation ())
+ abort ();
+ }
+ }
+ if (a != 64)
+ abort ();
+ #pragma omp task
+ {
+ if (omp_get_cancellation ())
+ abort ();
+ }
+ }
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/depend-iterator-1.c b/libgomp/testsuite/libgomp.c-c++-common/depend-iterator-1.c
new file mode 100644
index 0000000..03cded4
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/depend-iterator-1.c
@@ -0,0 +1,115 @@
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+int arr[64], arr2[64], arr3[64];
+
+int *
+foo (int x, int y, long z)
+{
+ int v;
+ switch (x)
+ {
+ case 1:
+ if (z != 0 || y < 0 || y >= 64)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = arr2[y];
+ arr2[y]++;
+ }
+ if (v != 0) abort ();
+ return &arr[y];
+ case 2:
+ if (y < 0 || y > 60 || (y & 3) || z < 0 || z >= 4)
+ abort ();
+ #pragma omp atomic
+ arr2[y + z] = arr2[y + z] + 4;
+ return &arr[y + z];
+ case 3:
+ if (z < 0 || z > 60 || (z & 3) || y < 0 || y >= 4)
+ abort ();
+ #pragma omp atomic
+ arr2[y + z] = arr2[y + z] + 16;
+ return &arr[y + z];
+ case 4:
+ if (y != 0 || z > 64 || z <= 0)
+ abort ();
+ #pragma omp atomic
+ arr2[z - 1] = arr2[z - 1] + 64;
+ return &arr[z - 1];
+ case 5:
+ if ((y & 3) != 0 || y < 64 || y >= 96
+ || (z & 127) != 0 || z < 512 || z >= 1024)
+ abort ();
+ y = (y - 64) + (z - 512) / 128;
+ #pragma omp atomic
+ arr2[y] = arr2[y] + 256;
+ return &arr[y];
+ case 6:
+ if ((y & 3) != 0 || y <= 64 || y > 96
+ || (z & 127) != 1 || z <= 513 || z > 1025)
+ abort ();
+ y = (y - 68) + (z - 641) / 128;
+ #pragma omp atomic
+ arr2[y] = arr2[y] + 1024;
+ return &arr[y];
+ default:
+ abort ();
+ }
+}
+
+volatile int beg, end, step, step2;
+volatile unsigned int begu, endu;
+
+int
+main ()
+{
+ int m;
+ beg = 60;
+ end = -4;
+ step = -4;
+ step2 = 4;
+ begu = -64U;
+ endu = -32U;
+ #pragma omp parallel
+ #pragma omp master
+ {
+ int i;
+ for (i = 0; i < 64; i++)
+ #pragma omp task depend (iterator (j=i:i+1) , out : foo (1, j, 0)[0])
+ arr[i] = i;
+ #pragma omp task depend (iterator (int k=beg:end:step,long int l=0:4:1) , inout : \
+ foo (2, k, l)[0], foo (3, l, k)[0]) private (i)
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i)
+ abort ();
+ else
+ arr[i] = arr[i] + 1;
+ #pragma omp task depend (iterator (int *p=&arr3[64]:&arr3[0]:-1) , inout : \
+ foo (4, 0, p - &arr3[0])[0]) depend (in : beg)
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i + 1)
+ abort ();
+ else
+ arr[i] = arr[i] + 2;
+ #pragma omp task depend (iterator (unsigned n=begu:endu:step2, unsigned int o = 512: 1024U: (unsigned char) 128), inout : \
+ foo (5, n + 128, o)[0])
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i + 3)
+ abort ();
+ else
+ arr[i] = arr[i] + 4;
+ #pragma omp task depend (iterator (int unsigned p=endu:begu:step,unsigned q= 1025U:513U:(signed char) -128), in : \
+ foo (6, p + 128, q)[0])
+ for (i = 0; i < 64; i++)
+ if (arr[i] != i + 7)
+ abort ();
+ else
+ arr[i] = arr[i] + 8;
+ }
+ for (m = 0; m < 64; m++)
+ if (arr[m] != m + 15 || arr2[m] != (m < 32 ? 1365 : 85))
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/depend-iterator-2.c b/libgomp/testsuite/libgomp.c-c++-common/depend-iterator-2.c
new file mode 100644
index 0000000..d9cbfdc
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/depend-iterator-2.c
@@ -0,0 +1,63 @@
+volatile int v;
+
+__attribute__((noipa)) void
+foo (int *p, int i)
+{
+ #pragma omp task depend (out: p[0])
+ v++;
+ #pragma omp task depend (in: p[0])
+ v++;
+ #pragma omp task depend (inout: p[0])
+ v++;
+ #pragma omp task depend (mutexinoutset: p[0])
+ v++;
+ #pragma omp task depend (out: p[0]) depend (in: p[1])
+ v++;
+ #pragma omp task depend (in: p[0]) depend (inout: p[1])
+ v++;
+ #pragma omp task depend (inout: p[0]) depend (mutexinoutset: p[1])
+ v++;
+ #pragma omp task depend (mutexinoutset: p[0]) depend (out: p[1])
+ v++;
+ #pragma omp task depend (iterator (j=0:2) , out : p[j])
+ v++;
+ #pragma omp task depend (iterator (j=0:2) , in : p[j])
+ v++;
+ #pragma omp task depend (iterator (j=0:2) , inout : p[j])
+ v++;
+ #pragma omp task depend (iterator (j=0:2) , mutexinoutset : p[j])
+ v++;
+ #pragma omp task depend (iterator (j=0:2) , out : p[j]) depend (iterator (j=0:2) , in : p[j + 2])
+ v++;
+ #pragma omp task depend (iterator (j=0:2) , in : p[j]) depend (iterator (j=0:2) , inout : p[j + 2])
+ v++;
+ #pragma omp task depend (iterator (j=0:2) , inout : p[j]) depend (iterator (j=0:2) , mutexinoutset : p[j + 2])
+ v++;
+ #pragma omp task depend (iterator (j=0:2) , mutexinoutset : p[j]) depend (iterator (j=0:2) , out : p[j + 2])
+ v++;
+ #pragma omp task depend (iterator (j=0:i) , out : p[j])
+ v++;
+ #pragma omp task depend (iterator (j=0:i) , in : p[j])
+ v++;
+ #pragma omp task depend (iterator (j=0:i) , inout : p[j])
+ v++;
+ #pragma omp task depend (iterator (j=0:i) , mutexinoutset : p[j])
+ v++;
+ #pragma omp task depend (iterator (j=0:i) , out : p[j]) depend (iterator (j=0:i) , in : p[j + 2])
+ v++;
+ #pragma omp task depend (iterator (j=0:i) , in : p[j]) depend (iterator (j=0:i) , inout : p[j + 2])
+ v++;
+ #pragma omp task depend (iterator (j=0:i) , inout : p[j]) depend (iterator (j=0:i) , mutexinoutset : p[j + 2])
+ v++;
+ #pragma omp task depend (iterator (j=0:i) , mutexinoutset : p[j]) depend (iterator (j=0:i) , out : p[j + 2])
+ v++;
+}
+
+int
+main ()
+{
+ int p[4];
+ foo (p, 2);
+ foo (p, -1);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/depend-mutexinout-1.c b/libgomp/testsuite/libgomp.c-c++-common/depend-mutexinout-1.c
new file mode 100644
index 0000000..86322ed
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/depend-mutexinout-1.c
@@ -0,0 +1,28 @@
+int
+main ()
+{
+ int a, b, c, d;
+ #pragma omp parallel num_threads (6)
+ #pragma omp single
+ {
+ #pragma omp task depend(out: c)
+ c = 1;
+ #pragma omp task depend(out: a)
+ a = 2;
+ #pragma omp task depend(out: b)
+ b = 3;
+ /* The above 3 tasks can be scheduled in any order. */
+ #pragma omp task depend(in: a) depend(mutexinoutset: c)
+ c += a;
+ #pragma omp task depend(in: b) depend(mutexinoutset: c)
+ c += b;
+ /* The above 2 tasks are mutually exclusive and need to wait
+ for the first and second or first and third tasks respectively. */
+ #pragma omp task depend(in: c)
+ d = c;
+ /* The above task needs to wait for the mutexinoutset tasks. */
+ }
+ if (d != 6)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/depend-mutexinout-2.c b/libgomp/testsuite/libgomp.c-c++-common/depend-mutexinout-2.c
new file mode 100644
index 0000000..ed92063
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/depend-mutexinout-2.c
@@ -0,0 +1,59 @@
+int
+main ()
+{
+ int a, b, c = 0;
+ #pragma omp parallel num_threads(2)
+ {
+ #pragma omp barrier
+ #pragma omp single
+ {
+ #pragma omp task depend(out: a)
+ {
+ int i;
+ a = 0;
+ for (i = 0; i < 524288; ++i)
+ {
+ asm volatile ("" : "+g" (a));
+ a++;
+ }
+ }
+ #pragma omp task depend(out: b)
+ {
+ int i;
+ b = 0;
+ for (i = 0; i < 64; ++i)
+ {
+ asm volatile ("" : "+g" (b));
+ b++;
+ }
+ }
+ #pragma omp task depend(in: a) depend(mutexinoutset: c)
+ {
+ int i;
+ int d = c;
+ for (i = 0; i < 524288 + 64 - a; ++i)
+ {
+ asm volatile ("" : "+g" (d) : "g" (&a) : "memory");
+ d++;
+ }
+ asm volatile ("" : "+g" (d), "+g" (c));
+ c = d;
+ }
+ #pragma omp task depend(in: b) depend(mutexinoutset: c)
+ {
+ int i;
+ int d = c;
+ for (i = 0; i < 524288 + 64 - b; ++i)
+ {
+ asm volatile ("" : "+g" (d) : "g" (&b) : "memory");
+ d++;
+ }
+ asm volatile ("" : "+g" (d), "+g" (c));
+ c = d;
+ }
+ }
+ }
+ if (c != 524288 + 64)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/depobj-1.c b/libgomp/testsuite/libgomp.c-c++-common/depobj-1.c
new file mode 100644
index 0000000..a07a0c8
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/depobj-1.c
@@ -0,0 +1,99 @@
+#include <stdlib.h>
+#include <omp.h>
+
+void
+dep (void)
+{
+ int x = 1;
+ omp_depend_t d1, d2;
+ #pragma omp depobj (d1) depend(in: x)
+ #pragma omp depobj (d2) depend(in: x)
+ #pragma omp depobj (d2) update(out)
+ #pragma omp parallel
+ #pragma omp single
+ {
+ #pragma omp task shared (x) depend(depobj: d2)
+ x = 2;
+ #pragma omp task shared (x) depend(depobj: d1)
+ if (x != 2)
+ abort ();
+ }
+ #pragma omp depobj (d2) destroy
+ #pragma omp depobj (d1) destroy
+}
+
+void
+dep2 (void)
+{
+ #pragma omp parallel
+ #pragma omp single
+ {
+ int x = 1;
+ omp_depend_t d1, d2;
+ #pragma omp depobj (d1) depend(out: x)
+ #pragma omp depobj (*&d2) depend (in:x)
+ #pragma omp depobj(d2)update(in)
+ #pragma omp task shared (x) depend(depobj:d1)
+ x = 2;
+ #pragma omp task shared (x) depend(depobj : d2)
+ if (x != 2)
+ abort ();
+ #pragma omp taskwait
+ #pragma omp depobj(d1)destroy
+ #pragma omp depobj((&d2)[0]) destroy
+ }
+}
+
+void
+dep3 (void)
+{
+ omp_depend_t d[2];
+ #pragma omp parallel
+ {
+ int x = 1;
+ #pragma omp single
+ {
+ #pragma omp depobj(d[0]) depend(out:x)
+ #pragma omp depobj(d[1]) depend(in: x)
+ #pragma omp task shared (x) depend(depobj: *d)
+ x = 2;
+ #pragma omp task shared (x) depend(depobj: *(d + 1))
+ if (x != 2)
+ abort ();
+ }
+ }
+ #pragma omp depobj(d[0]) destroy
+ #pragma omp depobj(d[1]) destroy
+}
+
+int xx;
+omp_depend_t dd1, dd2;
+
+void
+antidep (void)
+{
+ xx = 1;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ #pragma omp task shared(xx) depend(depobj:dd2)
+ if (xx != 1)
+ abort ();
+ #pragma omp task shared(xx) depend(depobj:dd1)
+ xx = 2;
+ }
+}
+
+int
+main ()
+{
+ dep ();
+ dep2 ();
+ dep3 ();
+ #pragma omp depobj (dd1) depend (inout: xx)
+ #pragma omp depobj (dd2) depend (in : xx)
+ antidep ();
+ #pragma omp depobj (dd2) destroy
+ #pragma omp depobj (dd1) destroy
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/display-affinity-1.c b/libgomp/testsuite/libgomp.c-c++-common/display-affinity-1.c
new file mode 100644
index 0000000..a67bb37
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/display-affinity-1.c
@@ -0,0 +1,91 @@
+/* { dg-set-target-env-var OMP_PROC_BIND "spread,close" } */
+/* { dg-set-target-env-var OMP_PLACES "cores" } */
+/* { dg-set-target-env-var OMP_NUM_THREADS "4" } */
+/* { dg-set-target-env-var OMP_AFFINITY_FORMAT "hello" } */
+
+#include <omp.h>
+#include <string.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+#define FMT "L:%0.5L%%%n>%32H<!%.33{host}!%.6P_%i_%0.18i_%0.7{ancestor_tnum} %18A"
+ char buf[] = FMT, hostname[256], buf2[512 + 32], *q;
+ size_t l, l2, l3;
+ char *r = getenv ("OMP_AFFINITY_FORMAT");
+ if (r && strcmp (r, "hello") == 0)
+ {
+ if (omp_get_affinity_format (NULL, 0) != 5)
+ abort ();
+ if (omp_get_affinity_format (buf2, 3) != 5
+ || strcmp (buf2, "he") != 0)
+ abort ();
+ if (omp_get_affinity_format (buf2, 6) != 5
+ || strcmp (buf2, "hello") != 0)
+ abort ();
+ }
+ omp_set_affinity_format (buf);
+ memset (buf, '^', sizeof (buf));
+ if (omp_get_affinity_format (NULL, 0) != sizeof (buf) - 1)
+ abort ();
+ if (omp_get_affinity_format (buf, 3) != sizeof (buf) - 1
+ || buf[0] != FMT[0] || buf[1] != FMT[1] || buf[2] != '\0')
+ abort ();
+ memset (buf, ' ', sizeof (buf));
+ if (omp_get_affinity_format (buf, sizeof (buf) - 1) != sizeof (buf) - 1
+ || strncmp (buf, FMT, sizeof (buf) - 2) != 0
+ || buf[sizeof (buf) - 2] != '\0')
+ abort ();
+ memset (buf, '-', sizeof (buf));
+ if (omp_get_affinity_format (buf, sizeof (buf)) != sizeof (buf) - 1
+ || strcmp (buf, FMT) != 0)
+ abort ();
+ memset (buf, '0', sizeof (buf));
+ omp_display_affinity (NULL);
+ omp_display_affinity ("");
+ omp_display_affinity ("%%%0.9N");
+ omp_set_affinity_format ("%{host}");
+ l = omp_capture_affinity (hostname, sizeof hostname, NULL);
+ if (l < sizeof (hostname))
+ {
+ if (strlen (hostname) != l)
+ abort ();
+ l2 = omp_capture_affinity (NULL, 0,
+ "%0.5{nesting_level}%%%32{host}|||%.33H"
+ "%0.7a%3N!%N!");
+ if (l2 != (5 + 1 + (l > 32 ? l : 32) + 3 + (l > 33 ? l : 33)
+ + 7 + 3 + 1 + 1 + 1))
+ abort ();
+ omp_set_affinity_format ("%.5L%%%32H|||%.33{host}%0.7{ancestor_tnum}"
+ "%3{num_threads}!%{num_threads}!");
+ l3 = omp_capture_affinity (buf2, sizeof buf2, "");
+ if (l3 != l2)
+ abort ();
+ if (memcmp (buf2, " 0%", 5 + 1) != 0)
+ abort ();
+ q = buf2 + 6;
+ if (memcmp (q, hostname, l) != 0)
+ abort ();
+ q += l;
+ if (l < 32)
+ for (l3 = 32 - l; l3; l3--)
+ if (*q++ != ' ')
+ abort ();
+ if (memcmp (q, "|||", 3) != 0)
+ abort ();
+ q += 3;
+ if (l < 33)
+ for (l3 = 33 - l; l3; l3--)
+ if (*q++ != ' ')
+ abort ();
+ if (memcmp (q, hostname, l) != 0)
+ abort ();
+ q += l;
+ if (strcmp (q, "-0000011 !1!") != 0)
+ abort ();
+ }
+ #pragma omp parallel num_threads (4) proc_bind(spread)
+ omp_display_affinity ("%0.2a!%n!%.4L!%N;%.2t;%0.2T;%{team_num};%{num_teams};%A");
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/for-10.c b/libgomp/testsuite/libgomp.c-c++-common/for-10.c
new file mode 100644
index 0000000..2b339a5
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/for-10.c
@@ -0,0 +1,4 @@
+/* { dg-additional-options "-std=gnu99" {target c } } */
+
+#define CONDNE
+#include "for-4.c"
diff --git a/libgomp/testsuite/libgomp.c-c++-common/for-11.c b/libgomp/testsuite/libgomp.c-c++-common/for-11.c
new file mode 100644
index 0000000..e46b4dd
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/for-11.c
@@ -0,0 +1,4 @@
+/* { dg-additional-options "-std=gnu99" {target c } } */
+
+#define CONDNE
+#include "for-5.c"
diff --git a/libgomp/testsuite/libgomp.c-c++-common/for-12.c b/libgomp/testsuite/libgomp.c-c++-common/for-12.c
new file mode 100644
index 0000000..e28ba93
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/for-12.c
@@ -0,0 +1,4 @@
+/* { dg-additional-options "-std=gnu99" {target c } } */
+
+#define CONDNE
+#include "for-6.c"
diff --git a/libgomp/testsuite/libgomp.c-c++-common/for-13.c b/libgomp/testsuite/libgomp.c-c++-common/for-13.c
new file mode 100644
index 0000000..a476727
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/for-13.c
@@ -0,0 +1,99 @@
+unsigned short a[256];
+
+__attribute__((noinline, noclone)) void
+bar (void *x, unsigned short z)
+{
+ unsigned short *y = (unsigned short *) x;
+ if (y < &a[5] || y > &a[222] || y == &a[124])
+ __builtin_abort ();
+ *y += z;
+}
+
+__attribute__((noinline, noclone)) void
+foo (void *qx, void *rx, void *sx, int n)
+{
+ unsigned short (*q)[n], (*r)[n], (*s)[n], (*p)[n];
+ q = (typeof (q)) qx;
+ r = (typeof (r)) rx;
+ s = (typeof (s)) sx;
+ #pragma omp for
+ for (p = q; p != r; p++)
+ bar (p, 1);
+ #pragma omp for
+ for (p = s; p != r; p--)
+ bar (p, 2);
+ #pragma omp for
+ for (p = q; p != r; p = p + 1)
+ bar (p, 4);
+ #pragma omp for
+ for (p = s; p != r; p = p - 1)
+ bar (p, 8);
+ #pragma omp for
+ for (p = q; p != r; p = 1 + p)
+ bar (p, 16);
+ #pragma omp for
+ for (p = s; p != r; p = -1 + p)
+ bar (p, 32);
+ #pragma omp for
+ for (p = q; p != r; p += 1)
+ bar (p, 64);
+ #pragma omp for
+ for (p = s; p != r; p -= 1)
+ bar (p, 128);
+}
+
+__attribute__((noinline, noclone)) void
+baz (void *qx, void *rx, void *sx, int n)
+{
+ unsigned short (*q)[n], (*r)[n], (*s)[n], (*p)[n];
+ q = (typeof (q)) qx;
+ r = (typeof (r)) rx;
+ s = (typeof (s)) sx;
+ #pragma omp for
+ for (p = q; p < r; p++)
+ bar (p, 256);
+ #pragma omp for
+ for (p = s; p > r; p--)
+ bar (p, 512);
+ #pragma omp for
+ for (p = q; p < r; p = p + 1)
+ bar (p, 1024);
+ #pragma omp for
+ for (p = s; p > r; p = p - 1)
+ bar (p, 2048);
+ #pragma omp for
+ for (p = q; p < r; p = 1 + p)
+ bar (p, 4096);
+ #pragma omp for
+ for (p = s; p > r; p = -1 + p)
+ bar (p, 8192);
+ #pragma omp for
+ for (p = q; p < r; p += 1)
+ bar (p, 16384);
+ #pragma omp for
+ for (p = s; p > r; p -= 1)
+ bar (p, 32768U);
+}
+
+int
+main ()
+{
+ int i;
+ volatile int j = 7;
+#pragma omp parallel
+ {
+ foo (&a[5 + (j - 7)], &a[124 + (j - 7)], &a[222 + (j - 7)], j);
+ baz (&a[5 + (j - 7)], &a[124 + (j - 7)], &a[222 + (j - 7)], j);
+ }
+ for (i = 0; i < 256; i++)
+ if (i < 5 || i > 222 || i == 124 || ((i - 5) % 7) != 0)
+ {
+ if (a[i])
+ __builtin_abort ();
+ }
+ else if (i < 124 && a[i] != 1 + 4 + 16 + 64 + 256 + 1024 + 4096 + 16384)
+ __builtin_abort ();
+ else if (i > 124 && a[i] != 2 + 8 + 32 + 128 + 512 + 2048 + 8192 + 32768U)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/for-14.c b/libgomp/testsuite/libgomp.c-c++-common/for-14.c
new file mode 100644
index 0000000..56440ab7
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/for-14.c
@@ -0,0 +1,110 @@
+/* { dg-additional-options "-std=gnu99" { target c } } */
+
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort ();
+
+#define M(x, y, z) O(x, y, z)
+#define O(x, y, z) x ## _ ## y ## _ ## z
+
+#define F distribute
+#define G d
+#define S
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F distribute
+#define G d_ds128
+#define S dist_schedule(static, 128)
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F distribute simd
+#define G ds
+#define S
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F distribute simd
+#define G ds_ds128
+#define S dist_schedule(static, 128)
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F distribute parallel for
+#define G dpf
+#include "for-1.h"
+#undef F
+#undef G
+
+#define F distribute parallel for dist_schedule(static, 128)
+#define G dpf_ds128
+#include "for-1.h"
+#undef F
+#undef G
+
+#define F distribute parallel for simd
+#define G dpfs
+#include "for-1.h"
+#undef F
+#undef G
+
+#define F distribute parallel for simd dist_schedule(static, 128)
+#define G dpfs_ds128
+#include "for-1.h"
+#undef F
+#undef G
+
+int
+main ()
+{
+ int err = 0;
+ #pragma omp teams reduction(|:err)
+ {
+ err |= test_d_normal ();
+ err |= test_d_ds128_normal ();
+ err |= test_ds_normal ();
+ err |= test_ds_ds128_normal ();
+ err |= test_dpf_static ();
+ err |= test_dpf_static32 ();
+ err |= test_dpf_auto ();
+ err |= test_dpf_guided32 ();
+ err |= test_dpf_runtime ();
+ err |= test_dpf_ds128_static ();
+ err |= test_dpf_ds128_static32 ();
+ err |= test_dpf_ds128_auto ();
+ err |= test_dpf_ds128_guided32 ();
+ err |= test_dpf_ds128_runtime ();
+ err |= test_dpfs_static ();
+ err |= test_dpfs_static32 ();
+ err |= test_dpfs_auto ();
+ err |= test_dpfs_guided32 ();
+ err |= test_dpfs_runtime ();
+ err |= test_dpfs_ds128_static ();
+ err |= test_dpfs_ds128_static32 ();
+ err |= test_dpfs_ds128_auto ();
+ err |= test_dpfs_ds128_guided32 ();
+ err |= test_dpfs_ds128_runtime ();
+ }
+ if (err)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/for-15.c b/libgomp/testsuite/libgomp.c-c++-common/for-15.c
new file mode 100644
index 0000000..512b972
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/for-15.c
@@ -0,0 +1,115 @@
+/* { dg-additional-options "-std=gnu99" { target c } } */
+
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort ();
+
+#define M(x, y, z) O(x, y, z)
+#define O(x, y, z) x ## _ ## y ## _ ## z
+
+#define F for
+#define G f
+#define S
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F teams distribute
+#define G td
+#define S
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F teams distribute
+#define G td_ds128
+#define S dist_schedule(static, 128)
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F teams distribute simd
+#define G tds
+#define S
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F teams distribute simd
+#define G tds_ds128
+#define S dist_schedule(static, 128)
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F teams distribute parallel for
+#define G tdpf
+#include "for-1.h"
+#undef F
+#undef G
+
+#define F teams distribute parallel for dist_schedule(static, 128)
+#define G tdpf_ds128
+#include "for-1.h"
+#undef F
+#undef G
+
+#define F teams distribute parallel for simd
+#define G tdpfs
+#include "for-1.h"
+#undef F
+#undef G
+
+#define F teams distribute parallel for simd dist_schedule(static, 128)
+#define G tdpfs_ds128
+#include "for-1.h"
+#undef F
+#undef G
+
+int
+main ()
+{
+ if (test_td_normal ()
+ || test_td_ds128_normal ()
+ || test_tds_normal ()
+ || test_tds_ds128_normal ()
+ || test_tdpf_static ()
+ || test_tdpf_static32 ()
+ || test_tdpf_auto ()
+ || test_tdpf_guided32 ()
+ || test_tdpf_runtime ()
+ || test_tdpf_ds128_static ()
+ || test_tdpf_ds128_static32 ()
+ || test_tdpf_ds128_auto ()
+ || test_tdpf_ds128_guided32 ()
+ || test_tdpf_ds128_runtime ()
+ || test_tdpfs_static ()
+ || test_tdpfs_static32 ()
+ || test_tdpfs_auto ()
+ || test_tdpfs_guided32 ()
+ || test_tdpfs_runtime ()
+ || test_tdpfs_ds128_static ()
+ || test_tdpfs_ds128_static32 ()
+ || test_tdpfs_ds128_auto ()
+ || test_tdpfs_ds128_guided32 ()
+ || test_tdpfs_ds128_runtime ())
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/for-2.h b/libgomp/testsuite/libgomp.c-c++-common/for-2.h
index 0bd116c..91a604a 100644
--- a/libgomp/testsuite/libgomp.c-c++-common/for-2.h
+++ b/libgomp/testsuite/libgomp.c-c++-common/for-2.h
@@ -21,6 +21,7 @@ noreturn (void)
#define OMPFROM(v) do {} while (0)
#endif
+#ifndef CONDNE
__attribute__((noinline, noclone)) void
N(f0) (void)
{
@@ -311,3 +312,292 @@ N(test) (void)
return 1;
return 0;
}
+
+#else
+
+__attribute__((noinline, noclone)) void
+N(f20) (void)
+{
+ int i;
+ OMPTGT
+#pragma omp F S
+ for (i = 0; i != 1500; i++)
+ a[i] += 2;
+}
+
+__attribute__((noinline, noclone)) void
+N(f21) (void)
+{
+ OMPTGT
+#pragma omp F S
+ for (unsigned int i = __INT_MAX__; i < 1500U + __INT_MAX__; i += 2 - 1)
+ a[(i - __INT_MAX__)] -= 2;
+}
+
+__attribute__((noinline, noclone)) void
+N(f22) (void)
+{
+ unsigned long long i;
+ OMPTGT
+#pragma omp F S
+ for (i = __LONG_LONG_MAX__ + 1500ULL - 27;
+ i != __LONG_LONG_MAX__ - 27ULL; i -= 3 - 2)
+ a[i + 26LL - __LONG_LONG_MAX__] -= 4;
+}
+
+__attribute__((noinline, noclone)) void
+N(f23) (long long n1, long long n2)
+{
+ OMPTGT
+#pragma omp F S
+ for (long long i = n1 + 23; i != n2 - 25; --i)
+ a[i + 48] += 7;
+}
+
+__attribute__((noinline, noclone)) void
+N(f24) (void)
+{
+ unsigned int i;
+ OMPTGT
+#pragma omp F S
+ for (i = 30; i != 30; i += 1)
+ a[i] += 10;
+}
+
+__attribute__((noinline, noclone)) void
+N(f25) (int n11, int n12, int n21, int n22, int n31, int n32,
+ int s2)
+{
+ SC int v1, v2, v3;
+ OMPTGT
+#pragma omp F S collapse(3)
+ for (v1 = n11; v1 != n12; v1 += 17 - 19 + 3)
+ for (v2 = n21; v2 < n22; v2 += s2)
+ for (v3 = n31; v3 != n32; ++v3)
+ b[v1][v2][v3] += 2.5;
+}
+
+__attribute__((noinline, noclone)) void
+N(f26) (int n11, int n12, int n21, int n22, long long n31, long long n32,
+ int s2)
+{
+ SC int v1, v2;
+ SC long long v3;
+ OMPTGT
+#pragma omp F S collapse(3)
+ for (v1 = n11; v1 != n12; v1 += -1)
+ for (v2 = n21; v2 > n22; v2 += s2)
+ for (v3 = n31; v3 != n32; v3 --)
+ b[v1][v2 / 2][v3] -= 4.5;
+}
+
+__attribute__((noinline, noclone)) void
+N(f27) (void)
+{
+ SC unsigned int v1, v3;
+ SC unsigned long long v2;
+ OMPTGT
+#pragma omp F S collapse(3)
+ for (v1 = 0; v1 < 20; v1 += 2)
+ for (v2 = __LONG_LONG_MAX__ + 11ULL;
+ v2 != __LONG_LONG_MAX__ - 4ULL; -- v2)
+ for (v3 = 10; v3 != 0; v3--)
+ b[v1 >> 1][v2 - __LONG_LONG_MAX__ + 3][v3 - 1] += 5.5;
+}
+
+__attribute__((noinline, noclone)) void
+N(f28) (void)
+{
+ SC long long v1, v2, v3;
+ OMPTGT
+#pragma omp F S collapse(3)
+ for (v1 = 0; v1 != 20; v1 -= 17 - 18)
+ for (v2 = 30; v2 < 20; v2++)
+ for (v3 = 10; v3 < 0; v3--)
+ b[v1][v2][v3] += 5.5;
+}
+
+__attribute__((noinline, noclone)) void
+N(f29) (void)
+{
+ int i;
+ OMPTGT
+#pragma omp F S
+ for (i = 20; i != 20; i++)
+ {
+ a[i] += 2;
+ noreturn ();
+ a[i] -= 4;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+N(f30) (void)
+{
+ SC int i;
+ OMPTGT
+#pragma omp F S collapse(3)
+ for (i = 0; i != 10; i++)
+ for (int j = 10; j < 8; j++)
+ for (long k = -10; k != 10; k++)
+ {
+ b[i][j][k] += 4;
+ noreturn ();
+ b[i][j][k] -= 8;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+N(f31) (int n)
+{
+ int i;
+ OMPTGT
+#pragma omp F S
+ for (i = 20; i != n; i++)
+ {
+ a[i] += 8;
+ noreturn ();
+ a[i] -= 16;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+N(f32) (int n)
+{
+ SC int i;
+ OMPTGT
+#pragma omp F S collapse(3)
+ for (i = 0; i != 10; i++)
+ for (int j = n; j != 12; j++)
+ for (long k = -10; k != 10; k++)
+ {
+ b[i][j][k] += 16;
+ noreturn ();
+ b[i][j][k] -= 32;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+N(f33) (void)
+{
+ int *i;
+ OMPTGT
+#pragma omp F S
+ for (i = a; i != &a[1500]; i++)
+ i[0] += 2;
+}
+
+__attribute__((noinline, noclone)) void
+N(f34) (void)
+{
+ SC float *i;
+ OMPTGT
+#pragma omp F S collapse(3)
+ for (i = &b[0][0][0]; i != &b[0][0][10]; i++)
+ for (float *j = &b[0][15][0]; j > &b[0][0][0]; j -= 10)
+ for (float *k = &b[0][0][10]; k != &b[0][0][0]; --k)
+ b[i - &b[0][0][0]][(j - &b[0][0][0]) / 10 - 1][(k - &b[0][0][0]) - 1]
+ -= 3.5;
+}
+
+__attribute__((noinline, noclone)) int
+N(test) (void)
+{
+ int i, j, k;
+ for (i = 0; i < 1500; i++)
+ a[i] = i - 25;
+ OMPTO (a);
+ N(f20) ();
+ OMPFROM (a);
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 23)
+ return 1;
+ N(f21) ();
+ OMPFROM (a);
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 25)
+ return 1;
+ N(f22) ();
+ OMPFROM (a);
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 29)
+ return 1;
+ N(f23) (1500LL - 1 - 23 - 48, -1LL + 25 - 48);
+ OMPFROM (a);
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 22)
+ return 1;
+ N(f24) ();
+ OMPFROM (a);
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 22)
+ return 1;
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ b[i][j][k] = i - 2.5 + 1.5 * j - 1.5 * k;
+ OMPTO (b);
+ N(f25) (0, 10, 0, 15, 0, 10, 1);
+ OMPFROM (b);
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ if (b[i][j][k] != i + 1.5 * j - 1.5 * k)
+ return 1;
+ N(f25) (0, 10, 30, 15, 0, 10, 5);
+ OMPFROM (b);
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ if (b[i][j][k] != i + 1.5 * j - 1.5 * k)
+ return 1;
+ N(f26) (9, -1, 29, 0, 9, -1, -2);
+ OMPFROM (b);
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ if (b[i][j][k] != i - 4.5 + 1.5 * j - 1.5 * k)
+ return 1;
+ N(f27) ();
+ OMPFROM (b);
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ if (b[i][j][k] != i + 1.0 + 1.5 * j - 1.5 * k)
+ return 1;
+ N(f28) ();
+ OMPFROM (b);
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ if (b[i][j][k] != i + 1.0 + 1.5 * j - 1.5 * k)
+ return 1;
+ N(f29) ();
+ N(f30) ();
+ N(f31) (20);
+ N(f32) (12);
+ OMPFROM (a);
+ OMPFROM (b);
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 22)
+ return 1;
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ if (b[i][j][k] != i + 1.0 + 1.5 * j - 1.5 * k)
+ return 1;
+ N(f33) ();
+ N(f34) ();
+ OMPFROM (a);
+ OMPFROM (b);
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 20)
+ return 1;
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ if (b[i][j][k] != i - 2.5 + 1.5 * j - 1.5 * k)
+ return 1;
+ return 0;
+}
+#endif
diff --git a/libgomp/testsuite/libgomp.c-c++-common/for-7.c b/libgomp/testsuite/libgomp.c-c++-common/for-7.c
new file mode 100644
index 0000000..43461bb
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/for-7.c
@@ -0,0 +1,4 @@
+/* { dg-additional-options "-std=gnu99" {target c } } */
+
+#define CONDNE
+#include "for-1.c"
diff --git a/libgomp/testsuite/libgomp.c-c++-common/for-8.c b/libgomp/testsuite/libgomp.c-c++-common/for-8.c
new file mode 100644
index 0000000..ed6bf71
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/for-8.c
@@ -0,0 +1,4 @@
+/* { dg-additional-options "-std=gnu99" {target c } } */
+
+#define CONDNE
+#include "for-2.c"
diff --git a/libgomp/testsuite/libgomp.c-c++-common/for-9.c b/libgomp/testsuite/libgomp.c-c++-common/for-9.c
new file mode 100644
index 0000000..dfd674f
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/for-9.c
@@ -0,0 +1,4 @@
+/* { dg-additional-options "-std=gnu99" {target c } } */
+
+#define CONDNE
+#include "for-3.c"
diff --git a/libgomp/testsuite/libgomp.c-c++-common/master-combined-1.c b/libgomp/testsuite/libgomp.c-c++-common/master-combined-1.c
new file mode 100644
index 0000000..3e6da09
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/master-combined-1.c
@@ -0,0 +1,66 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-std=c99" { target c } } */
+/* { dg-additional-options "-msse2" { target sse2_runtime } } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+
+#include <omp.h>
+#include <stdlib.h>
+
+#define N 64
+
+int
+main ()
+{
+ int p, *q, i, l;
+ int a[N];
+ q = a;
+ #pragma omp parallel master num_threads(4) private (p) shared(a)
+ {
+ int i;
+ p = omp_get_thread_num ();
+ if (p != 0)
+ abort ();
+ #pragma omp taskloop nogroup
+ for (i = 0; i < N; ++i)
+ {
+ if (omp_get_thread_num () >= 4)
+ abort ();
+ a[i] = i;
+ }
+ }
+ #pragma omp parallel num_threads(4)
+ {
+ #pragma omp master taskloop lastprivate (i, l) firstprivate (q)
+ for (i = 0; i != N; i = i + 1)
+ l = q[i];
+ }
+ if (i != N || l != N - 1)
+ abort ();
+ #pragma omp parallel master taskloop num_threads(4) \
+ lastprivate (i, l) firstprivate (q)
+ for (i = 0; i < N - 5; i += 2)
+ if (q[i] != i)
+ abort ();
+ else
+ l = q[i];
+ if (i != N - 4 || l != N - 6)
+ abort ();
+ #pragma omp parallel master taskloop simd num_threads(4)
+ for (i = 0; i < N; i++)
+ a[i] = 2 * a[i];
+ if (i != N)
+ abort ();
+ #pragma omp parallel num_threads(4)
+ {
+ int j;
+ #pragma omp master taskloop simd collapse(2)
+ for (i = 0; i < 2; i += 2)
+ for (j = 0; j < N; j++)
+ a[j] = a[j] + 1;
+ }
+ for (i = 0; i < N; i++)
+ if (a[i] != 2 * i + 1)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/pause-1.c b/libgomp/testsuite/libgomp.c-c++-common/pause-1.c
new file mode 100644
index 0000000..5367a7283
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/pause-1.c
@@ -0,0 +1,23 @@
+#include <omp.h>
+#include <stdlib.h>
+
+int a[64];
+
+int
+main ()
+{
+ int i;
+ #pragma omp parallel for
+ for (i = 0; i < 64; i++)
+ a[i] = i;
+ omp_pause_resource (omp_pause_soft, omp_get_initial_device ());
+ #pragma omp parallel for
+ for (i = 0; i < 64; i++)
+ a[i] += i;
+ omp_pause_resource_all (omp_pause_hard);
+ #pragma omp parallel for
+ for (i = 0; i < 64; i++)
+ if (a[i] != 2 * i)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/pause-2.c b/libgomp/testsuite/libgomp.c-c++-common/pause-2.c
new file mode 100644
index 0000000..e4781cd
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/pause-2.c
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* { dg-require-effective-target tls_runtime } */
+
+#include <omp.h>
+#include <stdlib.h>
+
+int t = 128;
+#pragma omp threadprivate (t)
+
+int
+main ()
+{
+ #pragma omp parallel
+ t = omp_get_thread_num () + 256;
+ #pragma omp parallel
+ if (t != omp_get_thread_num () + 256)
+ abort ();
+ omp_pause_resource (omp_pause_soft, omp_get_initial_device ());
+ /* This goes beyond what is required by the standard, we actually
+ check if the threads other than the initial one have been destroyed. */
+ #pragma omp parallel
+ {
+ if (omp_get_thread_num () != 0 && t != 128)
+ abort ();
+ t = omp_get_thread_num () + 384;
+ }
+ #pragma omp parallel
+ if (t != omp_get_thread_num () + 384)
+ abort ();
+ omp_pause_resource_all (omp_pause_hard);
+ #pragma omp parallel
+ {
+ if (omp_get_thread_num () != 0 && t != 128)
+ abort ();
+ t = omp_get_thread_num () + 512;
+ }
+ #pragma omp parallel
+ if (t != omp_get_thread_num () + 512)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/pr66199-10.c b/libgomp/testsuite/libgomp.c-c++-common/pr66199-10.c
new file mode 100644
index 0000000..301fa6c
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/pr66199-10.c
@@ -0,0 +1,60 @@
+/* PR middle-end/66199 */
+/* { dg-do run } */
+
+int u[1024], v[1024], w[1024];
+
+__attribute__((noinline, noclone)) long
+f1 (long a, long b)
+{
+ long d;
+ #pragma omp teams distribute parallel for simd default(none) firstprivate (a, b) shared(u, v, w)
+ for (d = a; d < b; d++)
+ u[d] = v[d] + w[d];
+ return d;
+}
+
+__attribute__((noinline, noclone)) long
+f2 (long a, long b, long c)
+{
+ long d, e;
+ #pragma omp teams distribute parallel for simd default(none) firstprivate (a, b, c) shared(u, v, w) linear(d) lastprivate(e)
+ for (d = a; d < b; d++)
+ {
+ u[d] = v[d] + w[d];
+ e = c + d * 5;
+ }
+ return d + e;
+}
+
+__attribute__((noinline, noclone)) long
+f3 (long a1, long b1, long a2, long b2)
+{
+ long d1, d2;
+ #pragma omp teams distribute parallel for simd default(none) firstprivate (a1, b1, a2, b2) shared(u, v, w) lastprivate(d1, d2) collapse(2)
+ for (d1 = a1; d1 < b1; d1++)
+ for (d2 = a2; d2 < b2; d2++)
+ u[d1 * 32 + d2] = v[d1 * 32 + d2] + w[d1 * 32 + d2];
+ return d1 + d2;
+}
+
+__attribute__((noinline, noclone)) long
+f4 (long a1, long b1, long a2, long b2)
+{
+ long d1, d2;
+ #pragma omp teams distribute parallel for simd default(none) firstprivate (a1, b1, a2, b2) shared(u, v, w) collapse(2)
+ for (d1 = a1; d1 < b1; d1++)
+ for (d2 = a2; d2 < b2; d2++)
+ u[d1 * 32 + d2] = v[d1 * 32 + d2] + w[d1 * 32 + d2];
+ return d1 + d2;
+}
+
+int
+main ()
+{
+ if (f1 (0, 1024) != 1024
+ || f2 (0, 1024, 17) != 1024 + (17 + 5 * 1023)
+ || f3 (0, 32, 0, 32) != 64
+ || f4 (0, 32, 0, 32) != 64)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/pr66199-11.c b/libgomp/testsuite/libgomp.c-c++-common/pr66199-11.c
new file mode 100644
index 0000000..bcb596e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/pr66199-11.c
@@ -0,0 +1,38 @@
+/* PR middle-end/66199 */
+/* { dg-do run } */
+/* { dg-options "-O2" { target c } } */
+
+int u[1024], v[1024], w[1024];
+
+__attribute__((noinline, noclone)) long
+f2 (long a, long b, long c)
+{
+ long d, e;
+ #pragma omp teams distribute parallel for default(none) firstprivate (a, b, c) shared(u, v, w) lastprivate(d, e)
+ for (d = a; d < b; d++)
+ {
+ u[d] = v[d] + w[d];
+ e = c + d * 5;
+ }
+ return d + e;
+}
+
+__attribute__((noinline, noclone)) long
+f3 (long a1, long b1, long a2, long b2)
+{
+ long d1, d2;
+ #pragma omp teams distribute parallel for default(none) firstprivate (a1, b1, a2, b2) shared(u, v, w) lastprivate(d1, d2) collapse(2)
+ for (d1 = a1; d1 < b1; d1++)
+ for (d2 = a2; d2 < b2; d2++)
+ u[d1 * 32 + d2] = v[d1 * 32 + d2] + w[d1 * 32 + d2];
+ return d1 + d2;
+}
+
+int
+main ()
+{
+ if (f2 (0, 1024, 17) != 1024 + (17 + 5 * 1023)
+ || f3 (0, 32, 0, 32) != 64)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/pr66199-12.c b/libgomp/testsuite/libgomp.c-c++-common/pr66199-12.c
new file mode 100644
index 0000000..78eb12a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/pr66199-12.c
@@ -0,0 +1,60 @@
+/* PR middle-end/66199 */
+/* { dg-do run } */
+
+int u[1024], v[1024], w[1024];
+
+__attribute__((noinline, noclone)) long
+f1 (long a, long b)
+{
+ long d;
+ #pragma omp teams distribute simd default(none) firstprivate (a, b) shared(u, v, w)
+ for (d = a; d < b; d++)
+ u[d] = v[d] + w[d];
+ return d;
+}
+
+__attribute__((noinline, noclone)) long
+f2 (long a, long b, long c)
+{
+ long d, e;
+ #pragma omp teams distribute simd default(none) firstprivate (a, b, c) shared(u, v, w) linear(d) lastprivate(e)
+ for (d = a; d < b; d++)
+ {
+ u[d] = v[d] + w[d];
+ e = c + d * 5;
+ }
+ return d + e;
+}
+
+__attribute__((noinline, noclone)) long
+f3 (long a1, long b1, long a2, long b2)
+{
+ long d1, d2;
+ #pragma omp teams distribute simd default(none) firstprivate (a1, b1, a2, b2) shared(u, v, w) lastprivate(d1, d2) collapse(2)
+ for (d1 = a1; d1 < b1; d1++)
+ for (d2 = a2; d2 < b2; d2++)
+ u[d1 * 32 + d2] = v[d1 * 32 + d2] + w[d1 * 32 + d2];
+ return d1 + d2;
+}
+
+__attribute__((noinline, noclone)) long
+f4 (long a1, long b1, long a2, long b2)
+{
+ long d1, d2;
+ #pragma omp teams distribute simd default(none) firstprivate (a1, b1, a2, b2) shared(u, v, w) collapse(2)
+ for (d1 = a1; d1 < b1; d1++)
+ for (d2 = a2; d2 < b2; d2++)
+ u[d1 * 32 + d2] = v[d1 * 32 + d2] + w[d1 * 32 + d2];
+ return d1 + d2;
+}
+
+int
+main ()
+{
+ if (f1 (0, 1024) != 1024
+ || f2 (0, 1024, 17) != 1024 + (17 + 5 * 1023)
+ || f3 (0, 32, 0, 32) != 64
+ || f4 (0, 32, 0, 32) != 64)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/pr66199-13.c b/libgomp/testsuite/libgomp.c-c++-common/pr66199-13.c
new file mode 100644
index 0000000..2f41a38
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/pr66199-13.c
@@ -0,0 +1,64 @@
+/* PR middle-end/66199 */
+/* { dg-do run } */
+
+int u[1024], v[1024], w[1024];
+
+__attribute__((noinline, noclone)) long
+f1 (long a, long b)
+{
+ long d;
+ #pragma omp teams default(none) shared(a, b, d, u, v, w)
+ #pragma omp distribute simd firstprivate (a, b)
+ for (d = a; d < b; d++)
+ u[d] = v[d] + w[d];
+ return d;
+}
+
+__attribute__((noinline, noclone)) long
+f2 (long a, long b, long c)
+{
+ long d, e;
+ #pragma omp teams default(none) firstprivate (a, b, c) shared(d, e, u, v, w)
+ #pragma omp distribute simd linear(d) lastprivate(e)
+ for (d = a; d < b; d++)
+ {
+ u[d] = v[d] + w[d];
+ e = c + d * 5;
+ }
+ return d + e;
+}
+
+__attribute__((noinline, noclone)) long
+f3 (long a1, long b1, long a2, long b2)
+{
+ long d1, d2;
+ #pragma omp teams default(none) shared(a1, b1, a2, b2, d1, d2, u, v, w)
+ #pragma omp distribute simd firstprivate (a1, b1, a2, b2) lastprivate(d1, d2) collapse(2)
+ for (d1 = a1; d1 < b1; d1++)
+ for (d2 = a2; d2 < b2; d2++)
+ u[d1 * 32 + d2] = v[d1 * 32 + d2] + w[d1 * 32 + d2];
+ return d1 + d2;
+}
+
+__attribute__((noinline, noclone)) long
+f4 (long a1, long b1, long a2, long b2)
+{
+ long d1, d2;
+ #pragma omp teams default(none) firstprivate (a1, b1, a2, b2) shared(d1, d2, u, v, w)
+ #pragma omp distribute simd collapse(2)
+ for (d1 = a1; d1 < b1; d1++)
+ for (d2 = a2; d2 < b2; d2++)
+ u[d1 * 32 + d2] = v[d1 * 32 + d2] + w[d1 * 32 + d2];
+ return d1 + d2;
+}
+
+int
+main ()
+{
+ if (f1 (0, 1024) != 1024
+ || f2 (0, 1024, 17) != 1024 + (17 + 5 * 1023)
+ || f3 (0, 32, 0, 32) != 64
+ || f4 (0, 32, 0, 32) != 64)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/pr66199-14.c b/libgomp/testsuite/libgomp.c-c++-common/pr66199-14.c
new file mode 100644
index 0000000..21936bf
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/pr66199-14.c
@@ -0,0 +1,39 @@
+/* PR middle-end/66199 */
+/* { dg-do run } */
+
+int u[1024], v[1024], w[1024];
+
+__attribute__((noinline, noclone)) long
+f2 (long a, long b, long c)
+{
+ long d, e;
+ #pragma omp teams default(none) firstprivate (a, b, c) shared(d, e, u, v, w)
+ #pragma omp distribute lastprivate(d, e)
+ for (d = a; d < b; d++)
+ {
+ u[d] = v[d] + w[d];
+ e = c + d * 5;
+ }
+ return d + e;
+}
+
+__attribute__((noinline, noclone)) long
+f3 (long a1, long b1, long a2, long b2)
+{
+ long d1, d2;
+ #pragma omp teams default(none) shared(a1, b1, a2, b2, d1, d2, u, v, w)
+ #pragma omp distribute firstprivate (a1, b1, a2, b2) lastprivate(d1, d2) collapse(2)
+ for (d1 = a1; d1 < b1; d1++)
+ for (d2 = a2; d2 < b2; d2++)
+ u[d1 * 32 + d2] = v[d1 * 32 + d2] + w[d1 * 32 + d2];
+ return d1 + d2;
+}
+
+int
+main ()
+{
+ if (f2 (0, 1024, 17) != 1024 + (17 + 5 * 1023)
+ || f3 (0, 32, 0, 32) != 64)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/simd-1.c b/libgomp/testsuite/libgomp.c-c++-common/simd-1.c
new file mode 100644
index 0000000..cce234d
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/simd-1.c
@@ -0,0 +1,71 @@
+// { dg-do run }
+// { dg-additional-options "-msse2" { target sse2_runtime } }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+#define N 1024
+int a[N], b[N];
+
+int
+f1 (void)
+{
+ int i;
+ #pragma omp simd private (i)
+ for (i = 0; i < N; i++)
+ a[i] = b[i] * 2;
+ #pragma omp simd lastprivate (i)
+ for (i = 0; i < N; i++)
+ a[i] += b[i] * 2;
+ return i;
+}
+
+int
+f2 (void)
+{
+ int i, j;
+ #pragma omp simd private (i), collapse (2), lastprivate (j)
+ for (i = 0; i < 32; i++)
+ for (j = 0; j < 32; ++j)
+ a[i * 32 + j] += b[i * 32 + j] * 2;
+ return j;
+}
+
+int
+f3 (void)
+{
+ static int i;
+ #pragma omp for simd private (i)
+ for (i = 0; i < N; ++i)
+ a[i] = b[i] * 2;
+ #pragma omp for simd lastprivate (i)
+ for (i = 0; i < N; ++i)
+ a[i] += b[i] * 2;
+ return i;
+}
+
+int
+f4 (void)
+{
+ static int i, j;
+ #pragma omp for simd private (i)collapse (2)lastprivate (j)
+ for (i = 0; i < 32; ++i)
+ for (j = 0; j < 32; j++)
+ a[i * 32 + j] += b[i * 32 + j] * 2;
+ return j;
+}
+
+int
+main ()
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ a[i] = b[i] = i;
+ if (f1 () != 1024 || f2 () != 32)
+ __builtin_abort ();
+ #pragma omp parallel num_threads(4)
+ if (f3 () != 1024 || f4 () != 32)
+ __builtin_abort ();
+ for (i = 0; i < N; ++i)
+ if (a[i] != 6 * i || b[i] != i)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/task-reduction-1.c b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-1.c
new file mode 100644
index 0000000..6c6191d
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-1.c
@@ -0,0 +1,58 @@
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int a;
+long int b = 1;
+
+void
+foo (void)
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a) in_reduction (*: b)
+ {
+ a += 7;
+ b *= 2;
+ }
+}
+
+int
+main ()
+{
+ int c = 0;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ long int d = 1;
+ #pragma omp taskgroup task_reduction (+: a, c) task_reduction (*: b, d)
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b, d)
+ {
+ int j;
+ a += 7;
+ b *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b, d)
+ {
+ a += 7;
+ b *= 2;
+ c += 9;
+ d *= 3;
+ foo ();
+ }
+ c += 9;
+ d *= 3;
+ }
+ }
+#define THREEP4 (3L * 3L * 3L * 3L)
+ if (d != (THREEP4 * THREEP4 * THREEP4))
+ abort ();
+ }
+ if (a != 28 * 7 || b != (1L << 28) || c != 12 * 9)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/task-reduction-11.c b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-11.c
new file mode 100644
index 0000000..038b0e2
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-11.c
@@ -0,0 +1,56 @@
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort (void);
+int a, b[3] = { 1, 1, 1 };
+unsigned long int c[2] = { ~0UL, ~0UL };
+
+void
+bar (int i)
+{
+ #pragma omp task in_reduction (*: b[:3]) in_reduction (&: c[1:]) \
+ in_reduction (+: a)
+ {
+ a += 4;
+ b[1] *= 4;
+ c[1] &= ~(1UL << (i + 16));
+ }
+}
+
+void
+foo (unsigned long long int x, unsigned long long int y, unsigned long long int z)
+{
+ unsigned long long int i;
+ #pragma omp for schedule(runtime) reduction (task, +: a) \
+ reduction (task, *: b) reduction (task, &: c[1:1])
+ for (i = x; i < y; i += z)
+ {
+ a++;
+ b[0] *= 2;
+ bar (i);
+ b[2] *= 3;
+ c[1] &= ~(1UL << i);
+ }
+}
+
+int
+main ()
+{
+ volatile int two = 2;
+ foo (two, 7 * two, two);
+ if (a != 30 || b[0] != 64 || b[1] != (1 << 12) || b[2] != 3 * 3 * 3 * 3 * 3 * 3
+ || c[0] != ~0UL || c[1] != ~0x15541554UL)
+ abort ();
+ a = 0;
+ b[0] = 1;
+ b[1] = 1;
+ b[2] = 1;
+ c[1] = ~0UL;
+ #pragma omp parallel
+ foo (two, 8 * two, two);
+ if (a != 35 || b[0] != 128 || b[1] != (1 << 14) || b[2] != 3 * 3 * 3 * 3 * 3 * 3 * 3
+ || c[0] != ~0UL || c[1] != ~0x55545554UL)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/task-reduction-12.c b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-12.c
new file mode 100644
index 0000000..0ad9273
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-12.c
@@ -0,0 +1,67 @@
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort (void);
+int a, b[3] = { 1, 1, 1 };
+unsigned long int c[2] = { ~0UL, ~0UL };
+
+void
+bar (int i)
+{
+ #pragma omp task in_reduction (*: b[:3]) in_reduction (&: c[1:]) \
+ in_reduction (+: a)
+ {
+ a += 4;
+ b[1] *= 4;
+ c[1] &= ~(1UL << (i + 16));
+ }
+}
+
+void
+foo (int x)
+{
+ #pragma omp sections reduction (task, +: a) reduction (task, *: b) \
+ reduction (task, &: c[1:1])
+ {
+ {
+ a++; b[0] *= 2; bar (2); b[2] *= 3; c[1] &= ~(1UL << 2);
+ }
+ #pragma omp section
+ { b[0] *= 2; bar (4); b[2] *= 3; c[1] &= ~(1UL << 4); a++; }
+ #pragma omp section
+ { bar (6); b[2] *= 3; c[1] &= ~(1UL << 6); a++; b[0] *= 2; }
+ #pragma omp section
+ { b[2] *= 3; c[1] &= ~(1UL << 8); a++; b[0] *= 2; bar (8); }
+ #pragma omp section
+ { c[1] &= ~(1UL << 10); a++; b[0] *= 2; bar (10); b[2] *= 3; }
+ #pragma omp section
+ { a++; b[0] *= 2; b[2] *= 3; c[1] &= ~(1UL << 12); bar (12); }
+ #pragma omp section
+ if (x)
+ {
+ a++; b[0] *= 2; b[2] *= 3; bar (14); c[1] &= ~(1UL << 14);
+ }
+ }
+}
+
+int
+main ()
+{
+ volatile int one = 1;
+ foo (!one);
+ if (a != 30 || b[0] != 64 || b[1] != (1 << 12) || b[2] != 3 * 3 * 3 * 3 * 3 * 3
+ || c[0] != ~0UL || c[1] != ~0x15541554UL)
+ abort ();
+ a = 0;
+ b[0] = 1;
+ b[1] = 1;
+ b[2] = 1;
+ c[1] = ~0UL;
+ #pragma omp parallel
+ foo (one);
+ if (a != 35 || b[0] != 128 || b[1] != (1 << 14) || b[2] != 3 * 3 * 3 * 3 * 3 * 3 * 3
+ || c[0] != ~0UL || c[1] != ~0x55545554UL)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/task-reduction-2.c b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-2.c
new file mode 100644
index 0000000..aad725c
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-2.c
@@ -0,0 +1,90 @@
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+struct S { long int s, t; };
+
+void
+bar (struct S *p, struct S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+baz (struct S *o, struct S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: struct S : omp_out.s += omp_in.s) initializer (omp_priv = { 0, 3 })
+#pragma omp declare reduction (*: struct S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
+
+struct S a = { 0, 7 };
+struct S b = { 1, 5 };
+
+void
+foo (void)
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (*: b) in_reduction (+: a)
+ {
+ a.s += 7;
+ b.s *= 2;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9))
+ abort ();
+ }
+}
+
+int
+main ()
+{
+ struct S c = { 0, 7 };
+ #pragma omp parallel
+ #pragma omp single
+ {
+ struct S d = { 1, 5 };
+ #pragma omp taskgroup task_reduction (+: a, c) task_reduction (*: b, d)
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ #pragma omp task in_reduction (*: b, d) in_reduction (+: a, c)
+ {
+ int j;
+ a.s += 7;
+ b.s *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a) in_reduction (*: b) \
+ in_reduction (+: c) in_reduction (*: d)
+ {
+ a.s += 7;
+ b.s *= 2;
+ c.s += 9;
+ d.s *= 3;
+ foo ();
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+ c.s += 9;
+ d.s *= 3;
+ if ((a.t != 7 && a.t != 3) || (b.t != 5 && b.t != 9)
+ || (c.t != 7 && c.t != 3) || (d.t != 5 && d.t != 9))
+ abort ();
+ }
+ }
+#define THREEP4 (3L * 3L * 3L * 3L)
+ if (d.s != (THREEP4 * THREEP4 * THREEP4) || d.t != 5)
+ abort ();
+ }
+ if (a.s != 28 * 7 || a.t != 7 || b.s != (1L << 28) || b.t != 5
+ || c.s != 12 * 9 || c.t != 7)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/task-reduction-3.c b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-3.c
new file mode 100644
index 0000000..8a90e86e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-3.c
@@ -0,0 +1,218 @@
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int a[2];
+long long int b[7] = { 9, 11, 1, 1, 1, 13, 15 };
+int e[3] = { 5, 0, 5 };
+int f[5] = { 6, 7, 0, 0, 9 };
+int g[4] = { 1, 0, 0, 2 };
+int h[3] = { 0, 1, 4 };
+int k[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+long long *s;
+long long (*t)[2];
+
+void
+foo (int n, int *c, long long int *d, int m[3], int *r, int o[4], int *p, int q[4][2])
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ a[0] += 7;
+ a[1] += 17;
+ b[2] *= 2;
+ b[4] *= 2;
+ c[0] += 6;
+ d[1] *= 2;
+ e[1] += 19;
+ f[2] += 21;
+ f[3] += 23;
+ g[1] += 25;
+ g[2] += 27;
+ h[0] += 29;
+ k[1][0] += 31;
+ k[2][1] += 33;
+ m[1] += 19;
+ r[2] += 21;
+ r[3] += 23;
+ o[1] += 25;
+ o[2] += 27;
+ p[0] += 29;
+ q[1][0] += 31;
+ q[2][1] += 33;
+ s[1] *= 2;
+ t[2][0] *= 2;
+ t[3][1] *= 2;
+ }
+}
+
+void
+test (int n)
+{
+ int c[2] = { 0, 0 };
+ int p[3] = { 0, 1, 4 };
+ int q[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+ long long ss[4] = { 5, 1, 1, 6 };
+ long long tt[5][2] = { { 9, 10 }, { 11, 12 }, { 1, 1 }, { 1, 1 }, { 13, 14 } };
+ s = ss;
+ t = tt;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ long long int d[] = { 1, 1 };
+ int m[3] = { 5, 0, 5 };
+ int r[5] = { 6, 7, 0, 0, 9 };
+ int o[4] = { 1, 0, 0, 2 };
+ #pragma omp taskgroup task_reduction (+: a, c) task_reduction (*: b[2 * n:3 * n], d) \
+ task_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ task_reduction (+: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ task_reduction (*: t[2:2][:], s[1:n + 1])
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
+ in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
+ in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ int j;
+ a[0] += 2;
+ a[1] += 3;
+ b[2] *= 2;
+ f[3] += 8;
+ g[1] += 9;
+ g[2] += 10;
+ h[0] += 11;
+ k[1][1] += 13;
+ k[2][1] += 15;
+ m[1] += 16;
+ r[2] += 8;
+ s[1] *= 2;
+ t[2][1] *= 2;
+ t[3][1] *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:])
+ {
+ m[1] += 6;
+ r[2] += 7;
+ q[1][0] += 17;
+ q[2][0] += 19;
+ a[0] += 4;
+ a[1] += 5;
+ b[3] *= 2;
+ b[4] *= 2;
+ f[3] += 18;
+ g[1] += 29;
+ g[2] += 18;
+ h[0] += 19;
+ s[2] *= 2;
+ t[2][0] *= 2;
+ t[3][0] *= 2;
+ foo (n, c, d, m, r, o, p, q);
+ r[3] += 18;
+ o[1] += 29;
+ o[2] += 18;
+ p[0] += 19;
+ c[0] += 4;
+ c[1] += 5;
+ d[0] *= 2;
+ e[1] += 6;
+ f[2] += 7;
+ k[1][0] += 17;
+ k[2][0] += 19;
+ }
+ r[3] += 8;
+ o[1] += 9;
+ o[2] += 10;
+ p[0] += 11;
+ q[1][1] += 13;
+ q[2][1] += 15;
+ b[3] *= 2;
+ c[0] += 4;
+ c[1] += 9;
+ d[0] *= 2;
+ e[1] += 16;
+ f[2] += 8;
+ }
+ }
+ if (d[0] != 1LL << (8 + 4)
+ || d[1] != 1LL << 16
+ || m[0] != 5
+ || m[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2] != 5
+ || r[0] != 6
+ || r[1] != 7
+ || r[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4] != 9
+ || o[0] != 1
+ || o[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3] != 2)
+ abort ();
+ }
+ if (a[0] != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1] != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0] != 9 || b[1] != 11
+ || b[2] != 1LL << (16 + 4)
+ || b[3] != 1LL << (8 + 4)
+ || b[4] != 1LL << (16 + 8)
+ || b[5] != 13 || b[6] != 15
+ || c[0] != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1] != 5 * 8 + 9 * 4
+ || e[0] != 5
+ || e[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2] != 5
+ || f[0] != 6
+ || f[1] != 7
+ || f[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4] != 9
+ || g[0] != 1
+ || g[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3] != 2
+ || h[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1] != 1 || h[2] != 4
+ || k[0][0] != 5 || k[0][1] != 6
+ || k[1][0] != 31 * 16 + 17 * 8
+ || k[1][1] != 13 * 4
+ || k[2][0] != 19 * 8
+ || k[2][1] != 33 * 16 + 15 * 4
+ || k[3][0] != 7 || k[3][1] != 8
+ || p[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1] != 1 || p[2] != 4
+ || q[0][0] != 5 || q[0][1] != 6
+ || q[1][0] != 31 * 16 + 17 * 8
+ || q[1][1] != 13 * 4
+ || q[2][0] != 19 * 8
+ || q[2][1] != 33 * 16 + 15 * 4
+ || q[3][0] != 7 || q[3][1] != 8
+ || ss[0] != 5
+ || ss[1] != 1LL << (16 + 4)
+ || ss[2] != 1LL << 8
+ || ss[3] != 6
+ || tt[0][0] != 9 || tt[0][1] != 10 || tt[1][0] != 11 || tt[1][1] != 12
+ || tt[2][0] != 1LL << (16 + 8)
+ || tt[2][1] != 1LL << 4
+ || tt[3][0] != 1LL << 8
+ || tt[3][1] != 1LL << (16 + 4)
+ || tt[4][0] != 13 || tt[4][1] != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ test (1);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/task-reduction-4.c b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-4.c
new file mode 100644
index 0000000..b0e5197
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-4.c
@@ -0,0 +1,70 @@
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort (void);
+
+void
+bar (long long int *p)
+{
+ p[0] *= 2;
+ #pragma omp task in_reduction (*: p[0])
+ p[0] *= 3;
+}
+
+void
+foo (long long int *p, long long int *q)
+{
+ #pragma omp taskgroup task_reduction (*: p[0])
+ {
+ #pragma omp task in_reduction (*: p[0])
+ bar (p);
+ #pragma omp task in_reduction (*: p[0])
+ bar (p);
+ bar (p);
+ #pragma omp taskgroup task_reduction (*: q[0])
+ {
+ #pragma omp task in_reduction (*: q[0])
+ bar (q);
+ #pragma omp task in_reduction (*: q[0])
+ bar (q);
+ #pragma omp task in_reduction (*: q[0])
+ bar (q);
+ bar (q);
+ #pragma omp task in_reduction (*: p[0])
+ {
+ #pragma omp taskgroup task_reduction (*: p[0])
+ {
+ #pragma omp task in_reduction (*: p[0])
+ bar (p);
+ p[0] *= 2;
+ #pragma omp task in_reduction (*: p[0])
+ bar (p);
+ }
+ }
+ }
+ }
+}
+
+int
+main ()
+{
+ long long int p = 1LL, q = 1LL;
+ foo (&p, &q);
+ if (p != 6LL * 6LL * 6LL * 6LL * 6LL * 2LL || q != 6LL * 6LL * 6LL * 6LL)
+ abort ();
+ p = 1LL;
+ q = 1LL;
+ #pragma omp taskgroup
+ foo (&p, &q);
+ if (p != 6LL * 6LL * 6LL * 6LL * 6LL * 2LL || q != 6LL * 6LL * 6LL * 6LL)
+ abort ();
+ p = 1LL;
+ q = 1LL;
+ #pragma omp parallel
+ #pragma omp single
+ foo (&p, &q);
+ if (p != 6LL * 6LL * 6LL * 6LL * 6LL * 2LL || q != 6LL * 6LL * 6LL * 6LL)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/task-reduction-5.c b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-5.c
new file mode 100644
index 0000000..018dc4f
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-5.c
@@ -0,0 +1,65 @@
+typedef __SIZE_TYPE__ size_t;
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort (void);
+
+int *q;
+
+void
+bar (int *p, int *r, int *t, int s, size_t u)
+{
+ #pragma omp task in_reduction (*: p[0], q[0], r[s - 1], t[0:u + 1])
+ {
+ *p *= 4;
+ *q *= 5;
+ r[s - 1] *= 6;
+ t[0] *= 8;
+ t[1] *= 9;
+ }
+}
+
+void
+foo (int *p, int *r, int *t, int s, size_t u)
+{
+ int *p2 = p;
+ #pragma omp taskgroup task_reduction (*: p[0], q[0], r[s], t[0:u + 1])
+ {
+ p = (int *) 0;
+ s++;
+ bar (p2, r, t, s, u);
+ r++;
+ #pragma omp taskwait
+ #pragma omp task in_reduction (*: p2[0], q[0], r[s - 2], t[0:u + 1])
+ {
+ *p2 *= 2;
+ *q *= 3;
+ r[s - 2] *= 7;
+ t[0] *= 10;
+ t[1] *= 11;
+ }
+ u = (~(size_t) 0) / 4;
+ s++;
+ p2 = (int *) 0;
+ q = (int *) 0;
+ r = (int *) 0;
+ t = (int *) 0;
+ }
+}
+
+int
+main ()
+{
+ int a = 1, b = 1, c[2] = { 1, 0 }, d[3] = { 1, 1, -1 };
+ volatile int zero;
+ zero = 0;
+ q = &b;
+ #pragma omp parallel num_threads (2)
+ #pragma omp master
+ foo (&a, &c[0], &d[0], zero, zero + 1);
+ if (a != 8 || b != 15 || c[0] != 42 || c[1] != 0
+ || d[0] != 80 || d[1] != 99 || d[2] != -1)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/task-reduction-6.c b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-6.c
new file mode 100644
index 0000000..09cbea6
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-6.c
@@ -0,0 +1,125 @@
+#include <omp.h>
+#include <stdlib.h>
+
+struct S { unsigned long long int s, t; };
+
+void
+rbar (struct S *p, struct S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+rbaz (struct S *o, struct S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: struct S : omp_out.s += omp_in.s) \
+ initializer (omp_priv = { 0, 3 })
+#pragma omp declare reduction (*: struct S : rbaz (&omp_out, &omp_in)) \
+ initializer (rbar (&omp_priv, &omp_orig))
+
+struct S g = { 0, 7 };
+struct S h = { 1, 5 };
+
+int
+foo (int *a, int *b)
+{
+ int x = 0;
+ #pragma omp taskloop reduction (+:x) in_reduction (+:b[0])
+ for (int i = 0; i < 64; i++)
+ {
+ x += a[i];
+ *b += a[i] * 2;
+ }
+ return x;
+}
+
+unsigned long long int
+bar (int *a, unsigned long long int *b)
+{
+ unsigned long long int x = 1;
+ #pragma omp taskloop reduction (*:x) in_reduction (*:b[0])
+ for (int i = 0; i < 64; i++)
+ {
+ #pragma omp task in_reduction (*:x)
+ x *= a[i];
+ #pragma omp task in_reduction (*:b[0])
+ *b *= (3 - a[i]);
+ }
+ return x;
+}
+
+void
+baz (int i, int *a, int *c)
+{
+ #pragma omp task in_reduction (*:h) in_reduction (+:g)
+ {
+ g.s += 7 * a[i];
+ h.s *= (3 - c[i]);
+ if ((g.t != 7 && g.t != 3) || (h.t != 5 && h.t != 9))
+ abort ();
+ }
+}
+
+int
+main ()
+{
+ int i, j, a[64], b = 0, c[64];
+ unsigned long long int d = 1, e;
+ int r = 0, t;
+ struct S m = { 0, 7 };
+ struct S n = { 1, 5 };
+ for (i = 0; i < 64; i++)
+ {
+ a[i] = 2 * i;
+ c[i] = 1 + ((i % 3) != 1);
+ }
+ #pragma omp parallel reduction (task, +:b) reduction(+:r) \
+ reduction(task,*:d) reduction (task, +: g, m) \
+ reduction (task, *: h, n) shared(t)
+ {
+ #pragma omp master
+ {
+ j = foo (a, &b);
+ t = omp_get_num_threads ();
+ }
+ r++;
+ #pragma omp single nowait
+ e = bar (c, &d);
+ #pragma omp master
+ #pragma omp taskloop in_reduction (+: g, m) in_reduction (*: h, n)
+ for (i = 0; i < 64; ++i)
+ {
+ g.s += 3 * a[i];
+ h.s *= (3 - c[i]);
+ m.s += 4 * a[i];
+ n.s *= c[i];
+ if ((g.t != 7 && g.t != 3) || (h.t != 5 && h.t != 9)
+ || (m.t != 7 && m.t != 3) || (n.t != 5 && n.t != 9))
+ abort ();
+ baz (i, a, c);
+ }
+ }
+ if (n.s != (1ULL << 43) || n.t != 5)
+ abort ();
+ if (j != 63 * 64 || b != 63 * 64 * 2)
+ abort ();
+ if (e != (1ULL << 43) || d != (1ULL << 21))
+ abort ();
+ if (g.s != 63 * 64 * 10 || g.t != 7)
+ abort ();
+ if (h.s != (1ULL << 42) || h.t != 5)
+ abort ();
+ if (m.s != 63 * 64 * 4 || m.t != 7)
+ abort ();
+ if (r != t)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/task-reduction-7.c b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-7.c
new file mode 100644
index 0000000..c656f5f
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-7.c
@@ -0,0 +1,216 @@
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int a[2];
+long long int b[7] = { 9, 11, 1, 1, 1, 13, 15 };
+int e[3] = { 5, 0, 5 };
+int f[5] = { 6, 7, 0, 0, 9 };
+int g[4] = { 1, 0, 0, 2 };
+int h[3] = { 0, 1, 4 };
+int k[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+long long *s;
+long long (*t)[2];
+
+void
+foo (int n, int *c, long long int *d, int m[3], int *r, int o[4], int *p, int q[4][2])
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ a[0] += 7;
+ a[1] += 17;
+ b[2] *= 2;
+ b[4] *= 2;
+ c[0] += 6;
+ d[1] *= 2;
+ e[1] += 19;
+ f[2] += 21;
+ f[3] += 23;
+ g[1] += 25;
+ g[2] += 27;
+ h[0] += 29;
+ k[1][0] += 31;
+ k[2][1] += 33;
+ m[1] += 19;
+ r[2] += 21;
+ r[3] += 23;
+ o[1] += 25;
+ o[2] += 27;
+ p[0] += 29;
+ q[1][0] += 31;
+ q[2][1] += 33;
+ s[1] *= 2;
+ t[2][0] *= 2;
+ t[3][1] *= 2;
+ }
+}
+
+void
+test (int n)
+{
+ int c[2] = { 0, 0 };
+ int p[3] = { 0, 1, 4 };
+ int q[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+ long long ss[4] = { 5, 1, 1, 6 };
+ long long tt[5][2] = { { 9, 10 }, { 11, 12 }, { 1, 1 }, { 1, 1 }, { 13, 14 } };
+ long long int d[] = { 1, 1 };
+ int m[3] = { 5, 0, 5 };
+ int r[5] = { 6, 7, 0, 0, 9 };
+ int o[4] = { 1, 0, 0, 2 };
+ s = ss;
+ t = tt;
+ #pragma omp parallel reduction (task, +: a, c) reduction (task, *: b[2 * n:3 * n], d) \
+ reduction (task, +: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ reduction (task, +: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ reduction (task, *: t[2:2][:], s[1:n + 1]) num_threads(4)
+ {
+ int i;
+ #pragma omp for
+ for (i = 0; i < 4; i++)
+ {
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
+ in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
+ in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ int j;
+ a[0] += 2;
+ a[1] += 3;
+ b[2] *= 2;
+ f[3] += 8;
+ g[1] += 9;
+ g[2] += 10;
+ h[0] += 11;
+ k[1][1] += 13;
+ k[2][1] += 15;
+ m[1] += 16;
+ r[2] += 8;
+ s[1] *= 2;
+ t[2][1] *= 2;
+ t[3][1] *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:])
+ {
+ m[1] += 6;
+ r[2] += 7;
+ q[1][0] += 17;
+ q[2][0] += 19;
+ a[0] += 4;
+ a[1] += 5;
+ b[3] *= 2;
+ b[4] *= 2;
+ f[3] += 18;
+ g[1] += 29;
+ g[2] += 18;
+ h[0] += 19;
+ s[2] *= 2;
+ t[2][0] *= 2;
+ t[3][0] *= 2;
+ foo (n, c, d, m, r, o, p, q);
+ r[3] += 18;
+ o[1] += 29;
+ o[2] += 18;
+ p[0] += 19;
+ c[0] += 4;
+ c[1] += 5;
+ d[0] *= 2;
+ e[1] += 6;
+ f[2] += 7;
+ k[1][0] += 17;
+ k[2][0] += 19;
+ }
+ r[3] += 8;
+ o[1] += 9;
+ o[2] += 10;
+ p[0] += 11;
+ q[1][1] += 13;
+ q[2][1] += 15;
+ b[3] *= 2;
+ c[0] += 4;
+ c[1] += 9;
+ d[0] *= 2;
+ e[1] += 16;
+ f[2] += 8;
+ }
+ }
+ }
+ if (a[0] != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1] != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0] != 9 || b[1] != 11
+ || b[2] != 1LL << (16 + 4)
+ || b[3] != 1LL << (8 + 4)
+ || b[4] != 1LL << (16 + 8)
+ || b[5] != 13 || b[6] != 15
+ || c[0] != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1] != 5 * 8 + 9 * 4
+ || d[0] != 1LL << (8 + 4)
+ || d[1] != 1LL << 16
+ || e[0] != 5
+ || e[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2] != 5
+ || f[0] != 6
+ || f[1] != 7
+ || f[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4] != 9
+ || g[0] != 1
+ || g[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3] != 2
+ || h[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1] != 1 || h[2] != 4
+ || k[0][0] != 5 || k[0][1] != 6
+ || k[1][0] != 31 * 16 + 17 * 8
+ || k[1][1] != 13 * 4
+ || k[2][0] != 19 * 8
+ || k[2][1] != 33 * 16 + 15 * 4
+ || k[3][0] != 7 || k[3][1] != 8
+ || m[0] != 5
+ || m[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2] != 5
+ || o[0] != 1
+ || o[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3] != 2
+ || p[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1] != 1 || p[2] != 4
+ || q[0][0] != 5 || q[0][1] != 6
+ || q[1][0] != 31 * 16 + 17 * 8
+ || q[1][1] != 13 * 4
+ || q[2][0] != 19 * 8
+ || q[2][1] != 33 * 16 + 15 * 4
+ || q[3][0] != 7 || q[3][1] != 8
+ || r[0] != 6
+ || r[1] != 7
+ || r[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4] != 9
+ || ss[0] != 5
+ || ss[1] != 1LL << (16 + 4)
+ || ss[2] != 1LL << 8
+ || ss[3] != 6
+ || tt[0][0] != 9 || tt[0][1] != 10 || tt[1][0] != 11 || tt[1][1] != 12
+ || tt[2][0] != 1LL << (16 + 8)
+ || tt[2][1] != 1LL << 4
+ || tt[3][0] != 1LL << 8
+ || tt[3][1] != 1LL << (16 + 4)
+ || tt[4][0] != 13 || tt[4][1] != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ test (1);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/task-reduction-8.c b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-8.c
new file mode 100644
index 0000000..7b0859d
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-8.c
@@ -0,0 +1,141 @@
+#include <omp.h>
+#include <stdlib.h>
+
+struct S { unsigned long long int s, t; };
+
+void
+rbar (struct S *p, struct S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+rbaz (struct S *o, struct S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: struct S : omp_out.s += omp_in.s) \
+ initializer (omp_priv = { 0, 3 })
+#pragma omp declare reduction (*: struct S : rbaz (&omp_out, &omp_in)) \
+ initializer (rbar (&omp_priv, &omp_orig))
+
+struct S g = { 0, 7 };
+struct S h = { 1, 5 };
+
+int
+foo (int z, int *a, int *b)
+{
+ int x = 0;
+ #pragma omp taskloop reduction (+:x) in_reduction (+:b[0])
+ for (int i = z; i < z + 8; i++)
+ {
+ x += a[i];
+ *b += a[i] * 2;
+ }
+ return x;
+}
+
+unsigned long long int
+bar (int z, int *a, unsigned long long int *b, int *s)
+{
+ unsigned long long int x = 1;
+ #pragma omp taskloop reduction (*:x) in_reduction (*:b[0])
+ for (int i = z; i < z + 8; i++)
+ {
+ #pragma omp task in_reduction (*:x)
+ x *= a[i];
+ #pragma omp task in_reduction (*:b[0])
+ *b *= (3 - a[i]);
+ s[0]++;
+ }
+ return x;
+}
+
+void
+baz (int i, int *a, int *c)
+{
+ #pragma omp task in_reduction (*:h) in_reduction (+:g)
+ {
+ g.s += 7 * a[i];
+ h.s *= (3 - c[i]);
+ if ((g.t != 7 && g.t != 3) || (h.t != 5 && h.t != 9))
+ abort ();
+ }
+}
+
+int
+main ()
+{
+ int i, j = 0, a[64], b = 0, c[64], f = 0;
+ unsigned long long int d = 1, e = 1;
+ volatile int one = 1;
+ int r = 0, s = 0, t;
+ struct S m = { 0, 7 };
+ struct S n = { 1, 5 };
+ for (i = 0; i < 64; i++)
+ {
+ a[i] = 2 * i;
+ c[i] = 1 + ((i % 3) != 1);
+ }
+ #pragma omp parallel reduction (task, +:b) shared(t) reduction(+:r, s)
+ {
+ int z, q1, q2, q3;
+ #pragma omp master
+ t = omp_get_num_threads ();
+ #pragma omp for schedule(static) reduction (task, +: f) reduction (+: j)
+ for (z = 0; z < 64; z += 8)
+ {
+ f++;
+ j += foo (z, a, &b);
+ j += foo (z, a, &f);
+ }
+ if (j != 63 * 64 * 2 || f != 63 * 64 * 2 + 8)
+ abort ();
+ r++;
+ #pragma omp taskgroup task_reduction (+: s)
+ {
+ #pragma omp for schedule(static, 1) reduction(task, *: d) reduction (*: e)
+ for (z = 0; z < 64; z += 8)
+ e *= bar (z, c, &d, &s);
+ }
+ if (e != (1ULL << 43) || d != (1ULL << 21))
+ abort ();
+ #pragma omp for schedule(monotonic: dynamic, 1) reduction (task, +: g, m) \
+ reduction (task, *: h, n) collapse(3)
+ for (q1 = 0; q1 < one; q1++)
+ for (q2 = 0; q2 < 64; q2 += 8)
+ for (q3 = 0; q3 < one; ++q3)
+ #pragma omp taskloop in_reduction (+: g, m) in_reduction (*: h, n) \
+ nogroup
+ for (i = q2; i < q2 + 8; ++i)
+ {
+ g.s += 3 * a[i];
+ h.s *= (3 - c[i]);
+ m.s += 4 * a[i];
+ n.s *= c[i];
+ if ((g.t != 7 && g.t != 3) || (h.t != 5 && h.t != 9)
+ || (m.t != 7 && m.t != 3) || (n.t != 5 && n.t != 9))
+ abort ();
+ baz (i, a, c);
+ }
+ if (n.s != (1ULL << 43) || n.t != 5)
+ abort ();
+ if (g.s != 63 * 64 * 10 || g.t != 7)
+ abort ();
+ if (h.s != (1ULL << 42) || h.t != 5)
+ abort ();
+ if (m.s != 63 * 64 * 4 || m.t != 7)
+ abort ();
+ }
+ if (b != 63 * 64 * 2)
+ abort ();
+ if (r != t || s != 64)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/task-reduction-9.c b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-9.c
new file mode 100644
index 0000000..3d71fef
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/task-reduction-9.c
@@ -0,0 +1,217 @@
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int a[2];
+long long int b[7] = { 9, 11, 1, 1, 1, 13, 15 };
+int e[3] = { 5, 0, 5 };
+int f[5] = { 6, 7, 0, 0, 9 };
+int g[4] = { 1, 0, 0, 2 };
+int h[3] = { 0, 1, 4 };
+int k[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+long long *s;
+long long (*t)[2];
+
+void
+foo (int n, int *c, long long int *d, int m[3], int *r, int o[4], int *p, int q[4][2])
+{
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ a[0] += 7;
+ a[1] += 17;
+ b[2] *= 2;
+ b[4] *= 2;
+ c[0] += 6;
+ d[1] *= 2;
+ e[1] += 19;
+ f[2] += 21;
+ f[3] += 23;
+ g[1] += 25;
+ g[2] += 27;
+ h[0] += 29;
+ k[1][0] += 31;
+ k[2][1] += 33;
+ m[1] += 19;
+ r[2] += 21;
+ r[3] += 23;
+ o[1] += 25;
+ o[2] += 27;
+ p[0] += 29;
+ q[1][0] += 31;
+ q[2][1] += 33;
+ s[1] *= 2;
+ t[2][0] *= 2;
+ t[3][1] *= 2;
+ }
+}
+
+void
+test (int n)
+{
+ int c[2] = { 0, 0 };
+ int p[3] = { 0, 1, 4 };
+ int q[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+ long long ss[4] = { 5, 1, 1, 6 };
+ long long tt[5][2] = { { 9, 10 }, { 11, 12 }, { 1, 1 }, { 1, 1 }, { 13, 14 } };
+ long long int d[] = { 1, 1 };
+ int m[3] = { 5, 0, 5 };
+ int r[5] = { 6, 7, 0, 0, 9 };
+ int o[4] = { 1, 0, 0, 2 };
+ s = ss;
+ t = tt;
+ #pragma omp parallel num_threads(4)
+ {
+ int i;
+ #pragma omp for reduction (task, +: a, c) reduction (task, *: b[2 * n:3 * n], d) \
+ reduction (task, +: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ reduction (task, +: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ reduction (task, *: t[2:2][:], s[1:n + 1]) \
+ schedule(nonmonotonic: runtime)
+ for (i = 0; i < 4; i++)
+ {
+ #pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
+ in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
+ in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:])
+ {
+ int j;
+ a[0] += 2;
+ a[1] += 3;
+ b[2] *= 2;
+ f[3] += 8;
+ g[1] += 9;
+ g[2] += 10;
+ h[0] += 11;
+ k[1][1] += 13;
+ k[2][1] += 15;
+ m[1] += 16;
+ r[2] += 8;
+ s[1] *= 2;
+ t[2][1] *= 2;
+ t[3][1] *= 2;
+ for (j = 0; j < 2; j++)
+ #pragma omp task in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:])
+ {
+ m[1] += 6;
+ r[2] += 7;
+ q[1][0] += 17;
+ q[2][0] += 19;
+ a[0] += 4;
+ a[1] += 5;
+ b[3] *= 2;
+ b[4] *= 2;
+ f[3] += 18;
+ g[1] += 29;
+ g[2] += 18;
+ h[0] += 19;
+ s[2] *= 2;
+ t[2][0] *= 2;
+ t[3][0] *= 2;
+ foo (n, c, d, m, r, o, p, q);
+ r[3] += 18;
+ o[1] += 29;
+ o[2] += 18;
+ p[0] += 19;
+ c[0] += 4;
+ c[1] += 5;
+ d[0] *= 2;
+ e[1] += 6;
+ f[2] += 7;
+ k[1][0] += 17;
+ k[2][0] += 19;
+ }
+ r[3] += 8;
+ o[1] += 9;
+ o[2] += 10;
+ p[0] += 11;
+ q[1][1] += 13;
+ q[2][1] += 15;
+ b[3] *= 2;
+ c[0] += 4;
+ c[1] += 9;
+ d[0] *= 2;
+ e[1] += 16;
+ f[2] += 8;
+ }
+ }
+ }
+ if (a[0] != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1] != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0] != 9 || b[1] != 11
+ || b[2] != 1LL << (16 + 4)
+ || b[3] != 1LL << (8 + 4)
+ || b[4] != 1LL << (16 + 8)
+ || b[5] != 13 || b[6] != 15
+ || c[0] != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1] != 5 * 8 + 9 * 4
+ || d[0] != 1LL << (8 + 4)
+ || d[1] != 1LL << 16
+ || e[0] != 5
+ || e[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2] != 5
+ || f[0] != 6
+ || f[1] != 7
+ || f[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4] != 9
+ || g[0] != 1
+ || g[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3] != 2
+ || h[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1] != 1 || h[2] != 4
+ || k[0][0] != 5 || k[0][1] != 6
+ || k[1][0] != 31 * 16 + 17 * 8
+ || k[1][1] != 13 * 4
+ || k[2][0] != 19 * 8
+ || k[2][1] != 33 * 16 + 15 * 4
+ || k[3][0] != 7 || k[3][1] != 8
+ || m[0] != 5
+ || m[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2] != 5
+ || o[0] != 1
+ || o[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3] != 2
+ || p[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1] != 1 || p[2] != 4
+ || q[0][0] != 5 || q[0][1] != 6
+ || q[1][0] != 31 * 16 + 17 * 8
+ || q[1][1] != 13 * 4
+ || q[2][0] != 19 * 8
+ || q[2][1] != 33 * 16 + 15 * 4
+ || q[3][0] != 7 || q[3][1] != 8
+ || r[0] != 6
+ || r[1] != 7
+ || r[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4] != 9
+ || ss[0] != 5
+ || ss[1] != 1LL << (16 + 4)
+ || ss[2] != 1LL << 8
+ || ss[3] != 6
+ || tt[0][0] != 9 || tt[0][1] != 10 || tt[1][0] != 11 || tt[1][1] != 12
+ || tt[2][0] != 1LL << (16 + 8)
+ || tt[2][1] != 1LL << 4
+ || tt[3][0] != 1LL << 8
+ || tt[3][1] != 1LL << (16 + 4)
+ || tt[4][0] != 13 || tt[4][1] != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ test (1);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-1.c b/libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-1.c
new file mode 100644
index 0000000..d44b471
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-1.c
@@ -0,0 +1,119 @@
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort (void);
+
+struct S { unsigned long long int s, t; };
+
+void
+rbar (struct S *p, struct S *o)
+{
+ p->s = 1;
+ if (o->t != 5)
+ abort ();
+ p->t = 9;
+}
+
+static inline void
+rbaz (struct S *o, struct S *i)
+{
+ if (o->t != 5 || i->t != 9)
+ abort ();
+ o->s *= i->s;
+}
+
+#pragma omp declare reduction (+: struct S : omp_out.s += omp_in.s) \
+ initializer (omp_priv = { 0, 3 })
+#pragma omp declare reduction (*: struct S : rbaz (&omp_out, &omp_in)) \
+ initializer (rbar (&omp_priv, &omp_orig))
+
+struct S g = { 0, 7 };
+struct S h = { 1, 5 };
+
+int
+foo (int *a, int *b)
+{
+ int x = 0;
+ #pragma omp taskloop reduction (+:x) in_reduction (+:b[0])
+ for (int i = 0; i < 64; i++)
+ {
+ x += a[i];
+ *b += a[i] * 2;
+ }
+ return x;
+}
+
+unsigned long long int
+bar (int *a, unsigned long long int *b)
+{
+ unsigned long long int x = 1;
+ #pragma omp taskloop reduction (*:x) in_reduction (*:b[0])
+ for (int i = 0; i < 64; i++)
+ {
+ #pragma omp task in_reduction (*:x)
+ x *= a[i];
+ #pragma omp task in_reduction (*:b[0])
+ *b *= (3 - a[i]);
+ }
+ return x;
+}
+
+void
+baz (int i, int *a, int *c)
+{
+ #pragma omp task in_reduction (*:h) in_reduction (+:g)
+ {
+ g.s += 7 * a[i];
+ h.s *= (3 - c[i]);
+ if ((g.t != 7 && g.t != 3) || (h.t != 5 && h.t != 9))
+ abort ();
+ }
+}
+
+int
+main ()
+{
+ int i, j, a[64], b = 0, c[64];
+ unsigned long long int d = 1, e;
+ struct S m = { 0, 7 };
+ for (i = 0; i < 64; i++)
+ {
+ a[i] = 2 * i;
+ c[i] = 1 + ((i % 3) != 1);
+ }
+ #pragma omp parallel
+ #pragma omp master
+ {
+ struct S n = { 1, 5 };
+ #pragma omp taskgroup task_reduction (+:b)
+ j = foo (a, &b);
+ #pragma omp taskgroup task_reduction (*:d)
+ e = bar (c, &d);
+ #pragma omp taskloop reduction (+: g, m) reduction (*: h, n)
+ for (i = 0; i < 64; ++i)
+ {
+ g.s += 3 * a[i];
+ h.s *= (3 - c[i]);
+ m.s += 4 * a[i];
+ n.s *= c[i];
+ if ((g.t != 7 && g.t != 3) || (h.t != 5 && h.t != 9)
+ || (m.t != 7 && m.t != 3) || (n.t != 5 && n.t != 9))
+ abort ();
+ baz (i, a, c);
+ }
+ if (n.s != (1ULL << 43) || n.t != 5)
+ abort ();
+ }
+ if (j != 63 * 64 || b != 63 * 64 * 2)
+ abort ();
+ if (e != (1ULL << 43) || d != (1ULL << 21))
+ abort ();
+ if (g.s != 63 * 64 * 10 || g.t != 7)
+ abort ();
+ if (h.s != (1ULL << 42) || h.t != 5)
+ abort ();
+ if (m.s != 63 * 64 * 4 || m.t != 7)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-2.c b/libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-2.c
new file mode 100644
index 0000000..8fc05dc
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-2.c
@@ -0,0 +1,212 @@
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int a[2];
+long long int b[7] = { 9, 11, 1, 1, 1, 13, 15 };
+int e[3] = { 5, 0, 5 };
+int f[5] = { 6, 7, 0, 0, 9 };
+int g[4] = { 1, 0, 0, 2 };
+int h[3] = { 0, 1, 4 };
+int k[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+long long *s;
+long long (*t)[2];
+
+void
+foo (int n, int *c, long long int *d, int m[3], int *r, int o[4], int *p, int q[4][2])
+{
+ int i;
+ #pragma omp taskloop in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
+ in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
+ in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
+ in_reduction (*: s[1:2], t[2:2][:]) nogroup
+ for (i = 0; i < 2; i++)
+ {
+ a[0] += 7;
+ a[1] += 17;
+ b[2] *= 2;
+ b[4] *= 2;
+ c[0] += 6;
+ d[1] *= 2;
+ e[1] += 19;
+ f[2] += 21;
+ f[3] += 23;
+ g[1] += 25;
+ g[2] += 27;
+ h[0] += 29;
+ k[1][0] += 31;
+ k[2][1] += 33;
+ m[1] += 19;
+ r[2] += 21;
+ r[3] += 23;
+ o[1] += 25;
+ o[2] += 27;
+ p[0] += 29;
+ q[1][0] += 31;
+ q[2][1] += 33;
+ s[1] *= 2;
+ t[2][0] *= 2;
+ t[3][1] *= 2;
+ }
+}
+
+void
+test (int n)
+{
+ int c[2] = { 0, 0 };
+ int p[3] = { 0, 1, 4 };
+ int q[4][2] = { { 5, 6 }, { 0, 0 }, { 0, 0 }, { 7, 8 } };
+ long long ss[4] = { 5, 1, 1, 6 };
+ long long tt[5][2] = { { 9, 10 }, { 11, 12 }, { 1, 1 }, { 1, 1 }, { 13, 14 } };
+ s = ss;
+ t = tt;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ long long int d[] = { 1, 1 };
+ int m[3] = { 5, 0, 5 };
+ int r[5] = { 6, 7, 0, 0, 9 };
+ int o[4] = { 1, 0, 0, 2 };
+ int i;
+ #pragma omp taskloop reduction (+: a, c) reduction (default, *: b[2 * n:3 * n], d) \
+ reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
+ reduction (default, +: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
+ reduction (*: t[2:2][:], s[1:n + 1])
+ for (i = 0; i < 4; i++)
+ {
+ int j;
+ a[0] += 2;
+ a[1] += 3;
+ b[2] *= 2;
+ f[3] += 8;
+ g[1] += 9;
+ g[2] += 10;
+ h[0] += 11;
+ k[1][1] += 13;
+ k[2][1] += 15;
+ m[1] += 16;
+ r[2] += 8;
+ s[1] *= 2;
+ t[2][1] *= 2;
+ t[3][1] *= 2;
+ #pragma omp taskloop in_reduction (+: a, c[:2]) \
+ in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
+ in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
+ in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
+ in_reduction (*: s[n:2], t[2:2][:]) nogroup
+ for (j = 0; j < 2; j++)
+ {
+ m[1] += 6;
+ r[2] += 7;
+ q[1][0] += 17;
+ q[2][0] += 19;
+ a[0] += 4;
+ a[1] += 5;
+ b[3] *= 2;
+ b[4] *= 2;
+ f[3] += 18;
+ g[1] += 29;
+ g[2] += 18;
+ h[0] += 19;
+ s[2] *= 2;
+ t[2][0] *= 2;
+ t[3][0] *= 2;
+ foo (n, c, d, m, r, o, p, q);
+ r[3] += 18;
+ o[1] += 29;
+ o[2] += 18;
+ p[0] += 19;
+ c[0] += 4;
+ c[1] += 5;
+ d[0] *= 2;
+ e[1] += 6;
+ f[2] += 7;
+ k[1][0] += 17;
+ k[2][0] += 19;
+ }
+ r[3] += 8;
+ o[1] += 9;
+ o[2] += 10;
+ p[0] += 11;
+ q[1][1] += 13;
+ q[2][1] += 15;
+ b[3] *= 2;
+ c[0] += 4;
+ c[1] += 9;
+ d[0] *= 2;
+ e[1] += 16;
+ f[2] += 8;
+ }
+ if (d[0] != 1LL << (8 + 4)
+ || d[1] != 1LL << 16
+ || m[0] != 5
+ || m[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || m[2] != 5
+ || r[0] != 6
+ || r[1] != 7
+ || r[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || r[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || r[4] != 9
+ || o[0] != 1
+ || o[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || o[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || o[3] != 2)
+ abort ();
+ }
+ if (a[0] != 7 * 16 + 4 * 8 + 2 * 4
+ || a[1] != 17 * 16 + 5 * 8 + 3 * 4
+ || b[0] != 9 || b[1] != 11
+ || b[2] != 1LL << (16 + 4)
+ || b[3] != 1LL << (8 + 4)
+ || b[4] != 1LL << (16 + 8)
+ || b[5] != 13 || b[6] != 15
+ || c[0] != 6 * 16 + 4 * 8 + 4 * 4
+ || c[1] != 5 * 8 + 9 * 4
+ || e[0] != 5
+ || e[1] != 19 * 16 + 6 * 8 + 16 * 4
+ || e[2] != 5
+ || f[0] != 6
+ || f[1] != 7
+ || f[2] != 21 * 16 + 7 * 8 + 8 * 4
+ || f[3] != 23 * 16 + 18 * 8 + 8 * 4
+ || f[4] != 9
+ || g[0] != 1
+ || g[1] != 25 * 16 + 29 * 8 + 9 * 4
+ || g[2] != 27 * 16 + 18 * 8 + 10 * 4
+ || g[3] != 2
+ || h[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || h[1] != 1 || h[2] != 4
+ || k[0][0] != 5 || k[0][1] != 6
+ || k[1][0] != 31 * 16 + 17 * 8
+ || k[1][1] != 13 * 4
+ || k[2][0] != 19 * 8
+ || k[2][1] != 33 * 16 + 15 * 4
+ || k[3][0] != 7 || k[3][1] != 8
+ || p[0] != 29 * 16 + 19 * 8 + 11 * 4
+ || p[1] != 1 || p[2] != 4
+ || q[0][0] != 5 || q[0][1] != 6
+ || q[1][0] != 31 * 16 + 17 * 8
+ || q[1][1] != 13 * 4
+ || q[2][0] != 19 * 8
+ || q[2][1] != 33 * 16 + 15 * 4
+ || q[3][0] != 7 || q[3][1] != 8
+ || ss[0] != 5
+ || ss[1] != 1LL << (16 + 4)
+ || ss[2] != 1LL << 8
+ || ss[3] != 6
+ || tt[0][0] != 9 || tt[0][1] != 10 || tt[1][0] != 11 || tt[1][1] != 12
+ || tt[2][0] != 1LL << (16 + 8)
+ || tt[2][1] != 1LL << 4
+ || tt[3][0] != 1LL << 8
+ || tt[3][1] != 1LL << (16 + 4)
+ || tt[4][0] != 13 || tt[4][1] != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ test (1);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-3.c b/libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-3.c
new file mode 100644
index 0000000..30a8324
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-3.c
@@ -0,0 +1,45 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-std=c99" { target c } } */
+/* { dg-additional-options "-msse2" { target sse2_runtime } } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+
+#define N 1024
+long int u[N], m, n;
+
+__attribute__((noipa)) void
+foo (void)
+{
+ int i;
+ #pragma omp taskloop simd reduction (+:m) grainsize (64)
+ for (i = 0; i < N; ++i)
+ m += u[i];
+}
+
+__attribute__((noipa)) void
+bar (int x)
+{
+ #pragma omp taskloop simd in_reduction (+:n) grainsize (64) nogroup
+ for (int i = (x & 1) * (N / 2); i < (x & 1) * (N / 2) + (N / 2); i++)
+ n += 2 * u[i];
+}
+
+int
+main ()
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ u[i] = i;
+ #pragma omp parallel master
+ {
+ foo ();
+ #pragma omp taskgroup task_reduction (+:n)
+ {
+ bar (0);
+ bar (1);
+ }
+ }
+ if (m != (long)(N - 1) * (N / 2) || n != (long)(N - 1) * N)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-4.c b/libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-4.c
new file mode 100644
index 0000000..c1c29b3
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-4.c
@@ -0,0 +1,65 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-std=c99" { target c } } */
+/* { dg-additional-options "-msse2" { target sse2_runtime } } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+
+#include <omp.h>
+#include <stdlib.h>
+
+#define N 1024
+long int u[N], m, n, o;
+
+__attribute__((noipa)) void
+foo (void)
+{
+ int i = -1;
+ #pragma omp master taskloop simd reduction (+:m) grainsize (64)
+ for (i = 0; i < N; ++i)
+ m += u[i];
+ if (i != (omp_get_thread_num () ? -1 : N))
+ abort ();
+}
+
+__attribute__((noipa)) void
+bar (int x)
+{
+ int i = -1;
+ #pragma omp master taskloop simd in_reduction (+:n) grainsize (64)
+ for (i = (x & 1) * (N / 2); i < (x & 1) * (N / 2) + (N / 2); i++)
+ n += 2 * u[i];
+ if (i != (omp_get_thread_num () ? -1 : (x & 1) * (N / 2) + (N / 2)))
+ abort ();
+}
+
+__attribute__((noipa)) void
+baz (void)
+{
+ int i;
+ #pragma omp parallel master taskloop simd reduction (+:o) grainsize (64)
+ for (i = 0; i < N; ++i)
+ o += u[i];
+ if (i != N)
+ abort ();
+}
+
+int
+main ()
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ u[i] = i;
+ #pragma omp parallel
+ {
+ foo ();
+ #pragma omp taskgroup task_reduction (+:n)
+ {
+ bar (0);
+ bar (1);
+ }
+ }
+ baz ();
+ if (m != (long)(N - 1) * (N / 2) || n != (long)(N - 1) * N || o != m)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/taskwait-depend-1.c b/libgomp/testsuite/libgomp.c-c++-common/taskwait-depend-1.c
new file mode 100644
index 0000000..094b4b3
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/taskwait-depend-1.c
@@ -0,0 +1,29 @@
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int
+main ()
+{
+ int a, b, c, d;
+ #pragma omp parallel num_threads (4)
+ #pragma omp single
+ {
+ #pragma omp task depend(out : a)
+ a = 6;
+ #pragma omp task depend(out : b)
+ b = 7;
+ #pragma omp task depend(out : c)
+ c = 8;
+ #pragma omp taskwait depend(in : a, c)
+ d = a + c;
+ #pragma omp task depend(out : a)
+ a = 9;
+ #pragma omp task depend(out : c)
+ c = 10;
+ }
+ if (a != 9 || b != 7 || c != 10 || d != 6 + 8)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/cancel-for-2.c b/libgomp/testsuite/libgomp.c/cancel-for-2.c
index 30cfbb1..d1d6f86 100644
--- a/libgomp/testsuite/libgomp.c/cancel-for-2.c
+++ b/libgomp/testsuite/libgomp.c/cancel-for-2.c
@@ -20,7 +20,7 @@ foo (int *x)
#pragma omp for
for (i = 0; i < 1000; ++i)
{
- #pragma omp cancel for if (x[1])
+ #pragma omp cancel for if (cancel: x[1])
#pragma omp atomic
v++;
}
@@ -34,7 +34,7 @@ foo (int *x)
#pragma omp for
for (i = 0; i < 1000; ++i)
{
- #pragma omp cancel for if (x[3])
+ #pragma omp cancel for if ( cancel : x[3])
#pragma omp atomic
v += 2;
}
@@ -54,7 +54,7 @@ foo (int *x)
#pragma omp cancel for if (x[0])
abort ();
}
- #pragma omp cancel parallel if (omp_get_thread_num () == 2 && x[4])
+ #pragma omp cancel parallel if (cancel:omp_get_thread_num () == 2 && x[4])
#pragma omp for
for (i = 0; i < 1000; ++i)
{
diff --git a/libgomp/testsuite/libgomp.c/task-reduction-1.c b/libgomp/testsuite/libgomp.c/task-reduction-1.c
new file mode 100644
index 0000000..224d995
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/task-reduction-1.c
@@ -0,0 +1,137 @@
+typedef __SIZE_TYPE__ size_t;
+extern void abort (void);
+
+void
+bar (int *a, int *b, int *c, int (*d)[2], int (*e)[4], size_t n, int f[1][n], int g[1][n * 2])
+{
+ #pragma omp task in_reduction (*: a[:n], b[3:n], c[n:n], d[0][:n], e[0][1:n], f[0][:], g[0][1:n])
+ {
+ a[0] *= 12;
+ a[1] *= 13;
+ b[3] *= 14;
+ b[4] *= 15;
+ c[n] *= 16;
+ c[n + 1] *= 17;
+ d[0][0] *= 18;
+ d[0][1] *= 19;
+ e[0][1] *= 20;
+ e[0][2] *= 21;
+ f[0][0] *= 22;
+ f[0][1] *= 23;
+ g[0][1] *= 24;
+ g[0][2] *= 25;
+ }
+}
+
+void
+foo (size_t n, void *x, void *y, int f[1][n], int g[1][n * 2])
+{
+ int a[n], b[n + 3], c[2 * n];
+ int (*d)[n] = (int (*)[n]) x;
+ int (*e)[n * 2] = (int (*)[n * 2]) y;
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ a[i] = 1;
+ b[i + 3] = 1;
+ c[i + n] = 1;
+ d[0][i] = 1;
+ e[0][i + 1] = 1;
+ f[0][i] = 1;
+ g[0][i + 1] = 1;
+ }
+ #pragma omp taskgroup task_reduction (*: a, b[3:n], c[n:n], d[0][:n], e[0][1:n], f[0][:], g[0][1:n])
+ {
+ bar (a, b, c, (int (*)[2]) d, (int (*)[4]) e, n, f, g);
+ #pragma omp task in_reduction (*: a, b[3:n], c[n:n], d[0][:n], e[0][1:n], f[0][:], g[0][1:n])
+ {
+ a[0] *= 2;
+ a[1] *= 3;
+ b[3] *= 4;
+ b[4] *= 5;
+ c[n] *= 6;
+ c[n + 1] *= 7;
+ d[0][0] *= 8;
+ d[0][1] *= 9;
+ e[0][1] *= 10;
+ e[0][2] *= 11;
+ f[0][0] *= 12;
+ f[0][1] *= 13;
+ g[0][1] *= 14;
+ g[0][2] *= 15;
+ }
+ n = 0;
+ }
+ if (a[0] != 24 || a[1] != 39 || b[3] != 56 || b[4] != 75)
+ abort ();
+ if (c[2] != 96 || c[3] != 119 || d[0][0] != 144 || d[0][1] != 171)
+ abort ();
+ if (e[0][1] != 200 || e[0][2] != 231 || f[0][0] != 264 || f[0][1] != 299)
+ abort ();
+ if (g[0][1] != 336 || g[0][2] != 375)
+ abort ();
+}
+
+void
+baz (size_t n, void *x, void *y, int f[1][n], int g[1][n * 2])
+{
+ int a[n], b[n + 3], c[2 * n];
+ int (*d)[n] = (int (*)[n]) x;
+ int (*e)[n * 2] = (int (*)[n * 2]) y;
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ a[i] = 1;
+ b[i + 3] = 1;
+ c[i + n] = 1;
+ d[0][i] = 1;
+ e[0][i + 1] = 1;
+ f[0][i] = 1;
+ g[0][i + 1] = 1;
+ }
+ #pragma omp parallel num_threads(2)
+ #pragma omp master
+ #pragma omp taskgroup task_reduction (*: a, b[3:n], c[n:n], d[0][:n], e[0][1:n], f[0][:], g[0][1:n])
+ {
+ bar (a, b, c, (int (*)[2]) d, (int (*)[4]) e, n, f, g);
+ #pragma omp task in_reduction (*: a, b[3:n], c[n:n], d[0][:n], e[0][1:n], f[0][:], g[0][1:n])
+ {
+ a[0] *= 2;
+ a[1] *= 3;
+ b[3] *= 4;
+ b[4] *= 5;
+ c[n] *= 6;
+ c[n + 1] *= 7;
+ d[0][0] *= 8;
+ d[0][1] *= 9;
+ e[0][1] *= 10;
+ e[0][2] *= 11;
+ f[0][0] *= 12;
+ f[0][1] *= 13;
+ g[0][1] *= 14;
+ g[0][2] *= 15;
+ }
+ n = 0;
+ }
+ if (a[0] != 24 || a[1] != 39 || b[3] != 56 || b[4] != 75)
+ abort ();
+ if (c[2] != 96 || c[3] != 119 || d[0][0] != 144 || d[0][1] != 171)
+ abort ();
+ if (e[0][1] != 200 || e[0][2] != 231 || f[0][0] != 264 || f[0][1] != 299)
+ abort ();
+ if (g[0][1] != 336 || g[0][2] != 375)
+ abort ();
+}
+
+int
+main ()
+{
+ int d[1][2], e[1][4], f[1][2], g[1][4];
+ volatile int two;
+ two = 2;
+ #pragma omp parallel num_threads (2)
+ #pragma omp master
+ foo (two, (void *) d, (void *) e, f, g);
+ baz (two, (void *) d, (void *) e, f, g);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/task-reduction-2.c b/libgomp/testsuite/libgomp.c/task-reduction-2.c
new file mode 100644
index 0000000..f5d48c3
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/task-reduction-2.c
@@ -0,0 +1,86 @@
+typedef __SIZE_TYPE__ size_t;
+extern void abort (void);
+
+void
+bar (int *a, int *b, int *c, int (*d)[2], int (*e)[4], size_t n, int f[1][n], int g[1][n * 2])
+{
+ #pragma omp task in_reduction (*: a[:n], b[3:n], c[n:n], d[0][:n], e[0][1:n], f[0][:], g[0][1:n])
+ {
+ a[0] *= 12;
+ a[1] *= 13;
+ b[3] *= 14;
+ b[4] *= 15;
+ c[n] *= 16;
+ c[n + 1] *= 17;
+ d[0][0] *= 18;
+ d[0][1] *= 19;
+ e[0][1] *= 20;
+ e[0][2] *= 21;
+ f[0][0] *= 22;
+ f[0][1] *= 23;
+ g[0][1] *= 24;
+ g[0][2] *= 25;
+ }
+}
+
+void
+baz (size_t n, void *x, void *y, int f[1][n], int g[1][n * 2])
+{
+ int a[n], b[n + 3], c[2 * n];
+ int (*d)[n] = (int (*)[n]) x;
+ int (*e)[n * 2] = (int (*)[n * 2]) y;
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ a[i] = 1;
+ b[i + 3] = 1;
+ c[i + n] = 1;
+ d[0][i] = 1;
+ e[0][i + 1] = 1;
+ f[0][i] = 1;
+ g[0][i + 1] = 1;
+ }
+ #pragma omp parallel num_threads(2) firstprivate (n) \
+ reduction (task, *: a, b[3:n], c[n:n], d[0][:n], e[0][1:n], f[0][:], g[0][1:n])
+ {
+ #pragma omp master
+ bar (a, b, c, (int (*)[2]) d, (int (*)[4]) e, n, f, g);
+ #pragma omp master
+ #pragma omp task in_reduction (*: a, b[3:n], c[n:n], d[0][:n], e[0][1:n], f[0][:], g[0][1:n])
+ {
+ a[0] *= 2;
+ a[1] *= 3;
+ b[3] *= 4;
+ b[4] *= 5;
+ c[n] *= 6;
+ c[n + 1] *= 7;
+ d[0][0] *= 8;
+ d[0][1] *= 9;
+ e[0][1] *= 10;
+ e[0][2] *= 11;
+ f[0][0] *= 12;
+ f[0][1] *= 13;
+ g[0][1] *= 14;
+ g[0][2] *= 15;
+ }
+ n = 0;
+ }
+ if (a[0] != 24 || a[1] != 39 || b[3] != 56 || b[4] != 75)
+ abort ();
+ if (c[2] != 96 || c[3] != 119 || d[0][0] != 144 || d[0][1] != 171)
+ abort ();
+ if (e[0][1] != 200 || e[0][2] != 231 || f[0][0] != 264 || f[0][1] != 299)
+ abort ();
+ if (g[0][1] != 336 || g[0][2] != 375)
+ abort ();
+}
+
+int
+main ()
+{
+ int d[1][2], e[1][4], f[1][2], g[1][4];
+ volatile int two;
+ two = 2;
+ baz (two, (void *) d, (void *) e, f, g);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/teams-1.c b/libgomp/testsuite/libgomp.c/teams-1.c
new file mode 100644
index 0000000..c5df837
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/teams-1.c
@@ -0,0 +1,27 @@
+#include <omp.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+ #pragma omp teams thread_limit (2)
+ {
+ if (omp_in_parallel ()
+ || omp_get_level () != 0
+ || omp_get_ancestor_thread_num (0) != 0
+ || omp_get_ancestor_thread_num (1) != -1)
+ abort ();
+ omp_set_dynamic (0);
+ omp_set_nested (1);
+ #pragma omp parallel num_threads (2)
+ {
+ if (!omp_in_parallel ()
+ || omp_get_level () != 1
+ || omp_get_ancestor_thread_num (0) != 0
+ || omp_get_ancestor_thread_num (1) != omp_get_thread_num ()
+ || omp_get_ancestor_thread_num (2) != -1)
+ abort ();
+ }
+ }
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/teams-2.c b/libgomp/testsuite/libgomp.c/teams-2.c
new file mode 100644
index 0000000..2ddf508
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/teams-2.c
@@ -0,0 +1,123 @@
+#include <omp.h>
+#include <stdlib.h>
+
+__attribute__((noinline))
+void
+foo (int x, int y, int z, int *a, int *b)
+{
+ if (x == 0)
+ {
+ int i, j;
+ for (i = 0; i < 64; i++)
+ #pragma omp parallel for shared (a, b)
+ for (j = 0; j < 32; j++)
+ foo (3, i, j, a, b);
+ }
+ else if (x == 1)
+ {
+ int i, j;
+ #pragma omp distribute dist_schedule (static, 1)
+ for (i = 0; i < 64; i++)
+ #pragma omp parallel for shared (a, b)
+ for (j = 0; j < 32; j++)
+ foo (3, i, j, a, b);
+ }
+ else if (x == 2)
+ {
+ int j;
+ #pragma omp parallel for shared (a, b)
+ for (j = 0; j < 32; j++)
+ foo (3, y, j, a, b);
+ }
+ else
+ {
+ #pragma omp atomic
+ b[y] += z;
+ #pragma omp atomic
+ *a += 1;
+ }
+}
+
+__attribute__((noinline))
+int
+bar (int x, int y, int z)
+{
+ int a, b[64], i;
+ a = 8;
+ for (i = 0; i < 64; i++)
+ b[i] = i;
+ foo (x, y, z, &a, b);
+ if (x == 0)
+ {
+ if (a != 8 + 64 * 32)
+ return 1;
+ for (i = 0; i < 64; i++)
+ if (b[i] != i + 31 * 32 / 2)
+ return 1;
+ }
+ else if (x == 1)
+ {
+ int c = omp_get_num_teams ();
+ int d = omp_get_team_num ();
+ int e = d;
+ int f = 0;
+ for (i = 0; i < 64; i++)
+ if (i == e)
+ {
+ if (b[i] != i + 31 * 32 / 2)
+ return 1;
+ f++;
+ e = e + c;
+ }
+ else if (b[i] != i)
+ return 1;
+ if (a < 8 || a > 8 + f * 32)
+ return 1;
+ }
+ else if (x == 2)
+ {
+ if (a != 8 + 32)
+ return 1;
+ for (i = 0; i < 64; i++)
+ if (b[i] != i + (i == y ? 31 * 32 / 2 : 0))
+ return 1;
+ }
+ else if (x == 3)
+ {
+ if (a != 8 + 1)
+ return 1;
+ for (i = 0; i < 64; i++)
+ if (b[i] != i + (i == y ? z : 0))
+ return 1;
+ }
+ return 0;
+}
+
+int
+main ()
+{
+ int i, j, err = 0;
+ #pragma omp teams reduction(+:err)
+ err += bar (0, 0, 0);
+ if (err)
+ abort ();
+ #pragma omp teams reduction(+:err)
+ err += bar (1, 0, 0);
+ if (err)
+ abort ();
+ #pragma omp teams reduction(+:err)
+ #pragma omp distribute
+ for (i = 0; i < 64; i++)
+ err += bar (2, i, 0);
+ if (err)
+ abort ();
+ #pragma omp teams reduction(+:err)
+ #pragma omp distribute
+ for (i = 0; i < 64; i++)
+ #pragma omp parallel for reduction(+:err)
+ for (j = 0; j < 32; j++)
+ err += bar (3, i, j);
+ if (err)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/thread-limit-4.c b/libgomp/testsuite/libgomp.c/thread-limit-4.c
new file mode 100644
index 0000000..5642e6a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/thread-limit-4.c
@@ -0,0 +1,57 @@
+/* { dg-do run } */
+/* { dg-set-target-env-var OMP_THREAD_LIMIT "9" } */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <omp.h>
+
+int
+main ()
+{
+ if (omp_get_thread_limit () != 9)
+ return 0;
+ omp_set_dynamic (0);
+ #pragma omp parallel num_threads (8)
+ if (omp_get_num_threads () != 8)
+ abort ();
+ #pragma omp parallel num_threads (16)
+ if (omp_get_num_threads () > 9)
+ abort ();
+ #pragma omp teams thread_limit (6)
+ {
+ if (omp_get_thread_limit () > 6)
+ abort ();
+ if (omp_get_thread_limit () == 6)
+ {
+ omp_set_dynamic (0);
+ omp_set_nested (1);
+ #pragma omp parallel num_threads (3)
+ if (omp_get_num_threads () != 3)
+ abort ();
+ #pragma omp parallel num_threads (3)
+ if (omp_get_num_threads () != 3)
+ abort ();
+ #pragma omp parallel num_threads (8)
+ if (omp_get_num_threads () > 6)
+ abort ();
+ #pragma omp parallel num_threads (6)
+ if (omp_get_num_threads () != 6)
+ abort ();
+ int cnt = 0;
+ #pragma omp parallel num_threads (5)
+ #pragma omp parallel num_threads (5)
+ #pragma omp parallel num_threads (2)
+ {
+ int v;
+ #pragma omp atomic capture
+ v = ++cnt;
+ if (v > 6)
+ abort ();
+ usleep (10000);
+ #pragma omp atomic
+ --cnt;
+ }
+ }
+ }
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/thread-limit-5.c b/libgomp/testsuite/libgomp.c/thread-limit-5.c
new file mode 100644
index 0000000..d3d22b1
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/thread-limit-5.c
@@ -0,0 +1,11 @@
+#include <stdlib.h>
+#include <omp.h>
+
+int
+main ()
+{
+ #pragma omp teams thread_limit (1)
+ if (omp_get_thread_limit () != 1)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.fortran/display-affinity-1.f90 b/libgomp/testsuite/libgomp.fortran/display-affinity-1.f90
new file mode 100644
index 0000000..4811b6f
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/display-affinity-1.f90
@@ -0,0 +1,34 @@
+! { dg-set-target-env-var OMP_PROC_BIND "spread,close" }
+! { dg-set-target-env-var OMP_PLACES "cores" }
+! { dg-set-target-env-var OMP_NUM_THREADS "4" }
+! { dg-set-target-env-var OMP_AFFINITY_FORMAT "hello" }
+
+ use omp_lib
+ character(len=68) :: buf, buf2
+ character(len=8) :: buf3
+ character(len=1) :: buf4
+ integer :: l1, l2
+
+ buf = 'L:%0.5L%%%n>%32H<!%.33{host}!%.6P_%i_%0.18i_%0.7{ancestor_tnum} %18A'
+ call omp_set_affinity_format (format = buf)
+ if (omp_get_affinity_format (buf4) /= 68) stop 1
+ if (buf4 /= 'L') stop 2
+ if (omp_get_affinity_format (buf2) /= 68) stop 3
+ if (buf2 /= buf) stop 4
+ if (omp_get_affinity_format (buf3) /= 68) stop 5
+ if (buf3 /= 'L:%0.5L%') stop 6
+ call omp_display_affinity ('')
+ call omp_display_affinity ('%%%0.9N')
+ l1 = omp_capture_affinity (buf4, '%0.5{nesting_level}%%|||%0.7a%3N!%N!')
+ buf = '%.5L%%|||%0.7{ancestor_tnum}%3{num_threads}!%{num_threads}!'
+ call omp_set_affinity_format (trim (buf))
+ l2 = omp_capture_affinity (buf2, '')
+ if (l1 /= l2) stop 7
+ if (l1 /= 22) stop 8
+ if (buf2 /= ' 0%|||-0000011 !1!') stop 9
+ if (buf4 /= '0') stop 10
+!$omp parallel num_threads (4) proc_bind(spread)
+ call omp_display_affinity ('%0.2a!%n!%.4L!%N;%.2t;%0.2T;&
+ &%{team_num};%{num_teams};%A')
+!$omp end parallel
+end