From d81ab49d0586fca0f3ee2f49c4581dd02508fcca Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 6 Aug 2019 09:26:32 +0200 Subject: tree.h (OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV): Rename to ... * tree.h (OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV): Rename to ... (OMP_CLAUSE_LASTPRIVATE_LOOP_IV): ... this. Adjust comment. * gimplify.c (gimple_add_tmp_var): In SIMD contexts, turn addressable new vars into GOVD_PRIVATE rather than GOVD_LOCAL. (gimplify_omp_for): Don't do C++ random access iterator clause adjustments on combined constructs from OMP_LOOP. For OMP_LOOP, don't predetermine the artificial iterator in case of C++ random access iterators as lastprivate, but private. For OMP_LOOP, force bind expr around simd body and force for_pre_body before the construct. Use OMP_CLAUSE_LASTPRIVATE_LOOP_IV instead of OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV. (gimplify_omp_loop): Add firstprivate clauses on OMP_PARALLEL for diff var of C++ random access iterators. Handle OMP_CLAUSE_FIRSTPRIVATE. For OMP_CLAUSE_LASTPRIVATE_LOOP_IV, if not outermost also add OMP_CLAUSE_FIRSTPRIVATE, and in both cases clear OMP_CLAUSE_LASTPRIVATE_LOOP_IV on the lastprivate clause on the OMP_FOR and OMP_DISTRIBUTE constructs if any. * omp-low.c (lower_rec_input_clauses): For OMP_CLAUSE_LASTPRIVATE_LOOP_IV on simd copy construct the private variables instead of default constructing them. (lower_lastprivate_clauses): Use OMP_CLAUSE_LASTPRIVATE_LOOP_IV instead of OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV and move the is_taskloop_ctx check from the assert to the guarding condition. gcc/cp/ * parser.c (cp_parser_omp_for_loop): For OMP_LOOP, ignore parallel clauses and predetermine iterator as lastprivate. * semantics.c (handle_omp_for_class_iterator): Use OMP_CLAUSE_LASTPRIVATE_LOOP_IV instead of OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV, set it for lastprivate also on OMP_LOOP construct. If a clause is missing for class iterator on OMP_LOOP, add firstprivate clause, and if there is private clause, turn it into firstprivate too. (finish_omp_for): Formatting fix. For OMP_LOOP, adjust OMP_CLAUSE_LASTPRIVATE_LOOP_IV clause CP_CLAUSE_INFO, so that it uses copy ctor instead of default ctor. * cp-gimplify.c (cp_gimplify_expr): Handle OMP_LOOP like OMP_DISTRIBUTE etc. (cp_fold_r): Likewise. (cp_genericize_r): Likewise. (cxx_omp_finish_clause): Also finish lastprivate clause with OMP_CLAUSE_LASTPRIVATE_LOOP_IV flag. * pt.c (tsubst_omp_clauses): Handle OMP_CLAUSE_BIND. (tsubst_omp_for_iterator): For OMP_LOOP, ignore parallel clauses and predetermine iterator as lastprivate. * constexpr.c (potential_constant_expression_1): Handle OMP_LOOP like OMP_DISTRIBUTE etc. libgomp/ * testsuite/libgomp.c++/loop-13.C: New test. * testsuite/libgomp.c++/loop-14.C: New test. * testsuite/libgomp.c++/loop-15.C: New test. From-SVN: r274138 --- libgomp/ChangeLog | 6 + libgomp/testsuite/libgomp.c++/loop-13.C | 298 +++++++++++++++++++++++ libgomp/testsuite/libgomp.c++/loop-14.C | 301 +++++++++++++++++++++++ libgomp/testsuite/libgomp.c++/loop-15.C | 417 ++++++++++++++++++++++++++++++++ 4 files changed, 1022 insertions(+) create mode 100644 libgomp/testsuite/libgomp.c++/loop-13.C create mode 100644 libgomp/testsuite/libgomp.c++/loop-14.C create mode 100644 libgomp/testsuite/libgomp.c++/loop-15.C (limited to 'libgomp') diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index 5adcd74..0331c51 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,9 @@ +2019-08-06 Jakub Jelinek + + * testsuite/libgomp.c++/loop-13.C: New test. + * testsuite/libgomp.c++/loop-14.C: New test. + * testsuite/libgomp.c++/loop-15.C: New test. + 2019-07-31 Jakub Jelinek PR middle-end/91301 diff --git a/libgomp/testsuite/libgomp.c++/loop-13.C b/libgomp/testsuite/libgomp.c++/loop-13.C new file mode 100644 index 0000000..663212c --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/loop-13.C @@ -0,0 +1,298 @@ +// { dg-do run } + +typedef __PTRDIFF_TYPE__ ptrdiff_t; +extern "C" void abort (); + +template +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 friend bool operator == (I &, I &); + template friend bool operator == (const I &, const I &); + template friend bool operator < (I &, I &); + template friend bool operator < (const I &, const I &); + template friend bool operator <= (I &, I &); + template friend bool operator <= (const I &, const I &); + template friend bool operator > (I &, I &); + template friend bool operator > (const I &, const I &); + template friend bool operator >= (I &, I &); + template friend bool operator >= (const I &, const I &); + template friend typename I::difference_type operator - (I &, I &); + template friend typename I::difference_type operator - (const I &, const I &); + template friend I operator + (typename I::difference_type , const I &); +private: + T *p; +}; +template I::I () : p (0) {} +template I::~I () {} +template I::I (T *x) : p (x) {} +template I::I (const I &x) : p (x.p) {} +template T &I::operator * () { return *p; } +template T *I::operator -> () { return p; } +template T &I::operator [] (const difference_type &x) const { return p[x]; } +template I &I::operator = (const I &x) { p = x.p; return *this; } +template I &I::operator ++ () { ++p; return *this; } +template I I::operator ++ (int) { return I (p++); } +template I &I::operator -- () { --p; return *this; } +template I I::operator -- (int) { return I (p--); } +template I &I::operator += (const difference_type &x) { p += x; return *this; } +template I &I::operator -= (const difference_type &x) { p -= x; return *this; } +template I I::operator + (const difference_type &x) const { return I (p + x); } +template I I::operator - (const difference_type &x) const { return I (p - x); } +template bool operator == (I &x, I &y) { return x.p == y.p; } +template bool operator == (const I &x, const I &y) { return x.p == y.p; } +template bool operator != (I &x, I &y) { return !(x == y); } +template bool operator != (const I &x, const I &y) { return !(x == y); } +template bool operator < (I &x, I &y) { return x.p < y.p; } +template bool operator < (const I &x, const I &y) { return x.p < y.p; } +template bool operator <= (I &x, I &y) { return x.p <= y.p; } +template bool operator <= (const I &x, const I &y) { return x.p <= y.p; } +template bool operator > (I &x, I &y) { return x.p > y.p; } +template bool operator > (const I &x, const I &y) { return x.p > y.p; } +template bool operator >= (I &x, I &y) { return x.p >= y.p; } +template bool operator >= (const I &x, const I &y) { return x.p >= y.p; } +template typename I::difference_type operator - (I &x, I &y) { return x.p - y.p; } +template typename I::difference_type operator - (const I &x, const I &y) { return x.p - y.p; } +template I operator + (typename I::difference_type x, const I &y) { return I (x + y.p); } + +template +class J +{ +public: + J(const I &x, const I &y) : b (x), e (y) {} + const I &begin (); + const I &end (); +private: + I b, e; +}; + +template const I &J::begin () { return b; } +template const I &J::end () { return e; } + +int results[2000]; + +template +static inline void +baz (I &i) +{ + results[*i]++; +} + +void +f1 (const I &x, const I &y) +{ +#pragma omp parallel loop order(concurrent) + for (I i = x; i <= y; i += 6) + baz (i); +} + +void +f2 (const I &x, const I &y) +{ + I i; +#pragma omp loop private(i) bind(parallel) + for (i = x; i < y - 1; i = 1 - 6 + 7 + i) + baz (i); +} + +template +void +f3 (const I &x, const I &y) +{ +#pragma omp loop bind(thread) order(concurrent) + for (I i = x; i <= y; i = i + 9 - 8) + baz (i); +} + +template +void +f4 (const I &x, const I &y) +{ + I i; +#pragma omp parallel loop lastprivate(i) + for (i = x + 2000 - 64; i > y + 10; --i) + baz (i); +} + +void +f5 (const I &x, const I &y) +{ +#pragma omp loop bind(teams) + for (I i = x + 2000 - 64; i > y + 10; i -= 10) + baz (i); +} + +template +void +f6 (const I &x, const I &y) +{ + I i; +#pragma omp teams loop order(concurrent) + for (i = x + 2000 - 64; i > y + 10; i = i - 12 + 2) + { + I j = i + N; + baz (j); + } +} + +template +void +f7 (I i, const I &x, const I &y) +{ +#pragma omp master +#pragma omp loop + for (i = x - 10; i <= y + 10; i += N) + baz (i); +} + +template +void +f8 (J j) +{ + I i; +#pragma omp parallel loop + for (i = j.begin (); i <= j.end () + N; i += 2) + baz (i); +} + +template +void +f9 (const I &x, const I &y) +{ + I i; +#pragma omp loop bind(teams) private(i) + for (i = x; i <= y; i = i + N) + baz (i); +} + +template +void +f10 (const I &x, const I &y) +{ + I i; +#pragma omp loop bind(thread) private(i) + for (i = x; i > y; i = i + N) + baz (i); +} + +template +void +f11 (const T &x, const T &y) +{ +#pragma omp parallel + { +#pragma omp loop + for (T i = x; i <= y; i += 3) + baz (i); +#pragma omp single + { + T j = y + 3; + baz (j); + } + } +} + +template +void +f12 (const T &x, const T &y) +{ + T i; +#pragma omp loop lastprivate(i) bind(thread) + for (i = x; i > y; --i) + baz (i); +} + +template +struct K +{ + template + static void + f13 (const T &x, const T &y) + { + T i; +#pragma omp teams loop order(concurrent) bind(teams) lastprivate (i) + for (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 && (i - 10) % 6 == 0); + #pragma omp parallel + f2 (&a[0], &a[1999]); + check (i < 1998 && (i & 1) == 0); + f3 (&a[20], &a[1837]); + check (i >= 20 && i <= 1837); + f4 (&a[0], &a[30]); + check (i > 40 && i <= 2000 - 64); + #pragma omp teams + f5 (&a[0], &a[100]); + check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0); + f6<-10> (&a[10], &a[110]); + check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0); + #pragma omp parallel num_threads(2) + f7<6> (I (), &a[12], &a[1800]); + check (i >= 2 && i <= 1808 && (i - 2) % 6 == 0); + f8<121> (J (&a[14], &a[1803])); + check (i >= 14 && i <= 1924 && (i & 1) == 0); + #pragma omp teams + f9 (&a[33], &a[1967]); + check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0); + f10 (&a[1939], &a[17]); + check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0); + f11 > (&a[16], &a[1981]); + check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0); + f12 > (&a[1761], &a[37]); + check (i > 37 && i <= 1761); + K<5>::f13 > (&a[1], &a[1935]); + check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0); + #pragma omp teams + f9 (&b[33], &b[1967]); + check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0); + f10 (&b[1939], &b[17]); + check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0); + f11 > (&b[16], &b[1981]); + check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0); + f12 > (&b[1761], &b[37]); + check (i > 37 && i <= 1761); + K<5>::f13 > (&b[1], &b[1935]); + check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0); +} diff --git a/libgomp/testsuite/libgomp.c++/loop-14.C b/libgomp/testsuite/libgomp.c++/loop-14.C new file mode 100644 index 0000000..191ab68 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/loop-14.C @@ -0,0 +1,301 @@ +// { dg-do run } + +typedef __PTRDIFF_TYPE__ ptrdiff_t; +extern "C" void abort (); + +template +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 friend bool operator == (I &, I &); + template friend bool operator == (const I &, const I &); + template friend bool operator < (I &, I &); + template friend bool operator < (const I &, const I &); + template friend bool operator <= (I &, I &); + template friend bool operator <= (const I &, const I &); + template friend bool operator > (I &, I &); + template friend bool operator > (const I &, const I &); + template friend bool operator >= (I &, I &); + template friend bool operator >= (const I &, const I &); + template friend typename I::difference_type operator - (I &, I &); + template friend typename I::difference_type operator - (const I &, const I &); + template friend I operator + (typename I::difference_type , const I &); +private: + T *p; +}; +template I::I () : p (0) {} +template I::~I () { p = (T *) 0; } +template I::I (T *x) : p (x) {} +template I::I (const I &x) : p (x.p) {} +template T &I::operator * () { return *p; } +template T *I::operator -> () { return p; } +template T &I::operator [] (const difference_type &x) const { return p[x]; } +template I &I::operator = (const I &x) { p = x.p; return *this; } +template I &I::operator ++ () { ++p; return *this; } +template I I::operator ++ (int) { return I (p++); } +template I &I::operator -- () { --p; return *this; } +template I I::operator -- (int) { return I (p--); } +template I &I::operator += (const difference_type &x) { p += x; return *this; } +template I &I::operator -= (const difference_type &x) { p -= x; return *this; } +template I I::operator + (const difference_type &x) const { return I (p + x); } +template I I::operator - (const difference_type &x) const { return I (p - x); } +template bool operator == (I &x, I &y) { return x.p == y.p; } +template bool operator == (const I &x, const I &y) { return x.p == y.p; } +template bool operator != (I &x, I &y) { return !(x == y); } +template bool operator != (const I &x, const I &y) { return !(x == y); } +template bool operator < (I &x, I &y) { return x.p < y.p; } +template bool operator < (const I &x, const I &y) { return x.p < y.p; } +template bool operator <= (I &x, I &y) { return x.p <= y.p; } +template bool operator <= (const I &x, const I &y) { return x.p <= y.p; } +template bool operator > (I &x, I &y) { return x.p > y.p; } +template bool operator > (const I &x, const I &y) { return x.p > y.p; } +template bool operator >= (I &x, I &y) { return x.p >= y.p; } +template bool operator >= (const I &x, const I &y) { return x.p >= y.p; } +template typename I::difference_type operator - (I &x, I &y) { return x.p - y.p; } +template typename I::difference_type operator - (const I &x, const I &y) { return x.p - y.p; } +template I operator + (typename I::difference_type x, const I &y) { return I (x + y.p); } + +template +class J +{ +public: + J(const I &x, const I &y) : b (x), e (y) {} + const I &begin (); + const I &end (); +private: + I b, e; +}; + +template const I &J::begin () { return b; } +template const I &J::end () { return e; } + +int results[2000]; + +template +static inline void +baz (I &i) +{ + results[*i]++; +} + +I +f1 (const I &x, const I &y) +{ + I i; +#pragma omp parallel shared (i) + { + #pragma omp loop lastprivate (i) order(concurrent) + for (i = x; i < y - 1; ++i) + baz (i); + #pragma omp single + i += 3; + } + return I (i); +} + +I +f2 (const I &x, const I &y) +{ + I i; +#pragma omp parallel loop bind(parallel) + for (i = x; i < y - 1; i = 1 - 6 + 7 + i) + baz (i); + return I (i); +} + +template +I +f3 (const I &x, const I &y) +{ + I i; +#pragma omp teams + #pragma omp loop order(concurrent) + for (i = x + 1000 - 64; i <= y - 10; i++) + baz (i); + return i; +} + +template +I +f4 (const I &x, const I &y) +{ + I i; +#pragma omp teams loop lastprivate (i) + for (i = x + 2000 - 64; i > y + 10; --i) + baz (i); + return I (i); +} + +template +I +f5 (const I &x, const I &y) +{ + I i; +#pragma omp loop lastprivate (i) bind(thread) + for (i = x; i > y + T (6); i--) + baz (i); + return i; +} + +template +I +f6 (const I &x, const I &y) +{ + I i; +#pragma omp loop bind(thread) + for (i = x - T (7); i > y; i -= T (2)) + baz (i); + return I (i); +} + +template +I +f7 (I i, const I &x, const I &y) +{ +#pragma omp parallel for lastprivate (i) + for (i = x - 10; i <= y + 10; i += N) + baz (i); + return I (i); +} + +template +I +f8 (J j) +{ + I i; +#pragma omp parallel shared (i) + #pragma omp loop lastprivate (i) + for (i = j.begin (); i <= j.end () + N; i += 2) + baz (i); + return i; +} + +I i9; + +template +I & +f9 (J j) +{ +#pragma omp loop bind(parallel) + for (i9 = j.begin () + N; i9 <= j.end () - N; i9 = i9 - N) + baz (i9); + return i9; +} + +template +I +f10 (const I &x, const I &y) +{ + I i; +#pragma omp parallel loop lastprivate (i) + for (i = x; i > y; i = i + N) + baz (i); + return i; +} + +template +T +f11 (T i, const T &x, const T &y) +{ + #pragma omp loop bind(thread) + for (i = x + U (2); i <= y + U (1); i = U (2) + U (3) + i) + baz (i); + return T (i); +} + +template +T +f12 (const T &x, const T &y) +{ + T i; +#pragma omp teams loop + 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[1873]) != 1875) + abort (); + check (i >= 10 && i < 1872); + if (*f2 (&a[0], &a[1998]) != 1998) + abort (); + check (i < 1997 && (i & 1) == 0); + if (*f3 (&a[10], &a[1971]) != 1962) + abort (); + check (i >= 946 && i <= 1961); + if (*f4 (&a[0], &a[30]) != 40) + abort (); + check (i > 40 && i <= 2000 - 64); + if (*f5 (&a[1931], &a[17]) != 23) + abort (); + check (i > 23 && i <= 1931); + if (*f6 (&a[1931], &a[17]) != 16) + abort (); + check (i > 17 && i <= 1924 && (i & 1) == 0); + if (*f7<6> (I (), &a[12], &a[1800]) != 1814) + abort (); + check (i >= 2 && i <= 1808 && (i - 2) % 6 == 0); + if (*f8<121> (J (&a[14], &a[1803])) != 1926) + abort (); + check (i >= 14 && i <= 1924 && (i & 1) == 0); + #pragma omp parallel + if (*f9<-3L> (J (&a[27], &a[1761])) != 1767) + abort (); + check (i >= 24 && i <= 1764 && (i % 3) == 0); + if (*f10 (&a[1939], &a[17]) != 14) + abort (); + check (i >= 21 && i <= 1939 && i % 7 == 0); + if (*f11, short> (I (), &a[71], &a[1941]) != 1943) + abort (); + check (i >= 73 && i <= 1938 && (i - 73) % 5 == 0); + if (*f12 > (&a[1761], &a[37]) != 37) + abort (); + check (i > 37 && i <= 1761); + if (*f10 (&b[1939], &b[17]) != 14) + abort (); + check (i >= 21 && i <= 1939 && i % 7 == 0); + if (*f11, short> (I (), &b[71], &b[1941]) != 1943) + abort (); + check (i >= 73 && i <= 1938 && (i - 73) % 5 == 0); + if (*f12 > (&b[1761], &b[37]) != 37) + abort (); + check (i > 37 && i <= 1761); +} diff --git a/libgomp/testsuite/libgomp.c++/loop-15.C b/libgomp/testsuite/libgomp.c++/loop-15.C new file mode 100644 index 0000000..b523b9b --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/loop-15.C @@ -0,0 +1,417 @@ +// { dg-do run } +// { dg-additional-options "-std=c++17" } + +typedef __PTRDIFF_TYPE__ ptrdiff_t; +extern "C" void abort (); + +namespace std { + template struct tuple_size; + template struct tuple_element; +} + +template +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 friend bool operator == (I &, I &); + template friend bool operator == (const I &, const I &); + template friend bool operator < (I &, I &); + template friend bool operator < (const I &, const I &); + template friend bool operator <= (I &, I &); + template friend bool operator <= (const I &, const I &); + template friend bool operator > (I &, I &); + template friend bool operator > (const I &, const I &); + template friend bool operator >= (I &, I &); + template friend bool operator >= (const I &, const I &); + template friend typename I::difference_type operator - (I &, I &); + template friend typename I::difference_type operator - (const I &, const I &); + template friend I operator + (typename I::difference_type , const I &); +private: + T *p; +}; +template I::I () : p (0) {} +template I::~I () {} +template I::I (T *x) : p (x) {} +template I::I (const I &x) : p (x.p) {} +template T &I::operator * () { return *p; } +template T *I::operator -> () { return p; } +template T &I::operator [] (const difference_type &x) const { return p[x]; } +template I &I::operator = (const I &x) { p = x.p; return *this; } +template I &I::operator ++ () { ++p; return *this; } +template I I::operator ++ (int) { return I (p++); } +template I &I::operator -- () { --p; return *this; } +template I I::operator -- (int) { return I (p--); } +template I &I::operator += (const difference_type &x) { p += x; return *this; } +template I &I::operator -= (const difference_type &x) { p -= x; return *this; } +template I I::operator + (const difference_type &x) const { return I (p + x); } +template I I::operator - (const difference_type &x) const { return I (p - x); } +template bool operator == (I &x, I &y) { return x.p == y.p; } +template bool operator == (const I &x, const I &y) { return x.p == y.p; } +template bool operator != (I &x, I &y) { return !(x == y); } +template bool operator != (const I &x, const I &y) { return !(x == y); } +template bool operator < (I &x, I &y) { return x.p < y.p; } +template bool operator < (const I &x, const I &y) { return x.p < y.p; } +template bool operator <= (I &x, I &y) { return x.p <= y.p; } +template bool operator <= (const I &x, const I &y) { return x.p <= y.p; } +template bool operator > (I &x, I &y) { return x.p > y.p; } +template bool operator > (const I &x, const I &y) { return x.p > y.p; } +template bool operator >= (I &x, I &y) { return x.p >= y.p; } +template bool operator >= (const I &x, const I &y) { return x.p >= y.p; } +template typename I::difference_type operator - (I &x, I &y) { return x.p - y.p; } +template typename I::difference_type operator - (const I &x, const I &y) { return x.p - y.p; } +template I operator + (typename I::difference_type x, const I &y) { return I (x + y.p); } + +template +class J +{ +public: + J(const I &x, const I &y) : b (x), e (y) {} + const I &begin (); + const I &end (); +private: + I b, e; +}; + +template const I &J::begin () { return b; } +template const I &J::end () { return e; } + +template +class K +{ +public: + K (); + ~K (); + template T &get () { if (N == 0) return c; else if (N == 1) return b; return a; } + T a, b, c; +}; + +template K::K () : a {}, b {}, c {} {} +template K::~K () {} +template struct std::tuple_size> { static constexpr int value = 3; }; +template struct std::tuple_element> { using type = T; }; + +template +class L +{ +public: + L (); + ~L (); + T a, b, c; +}; + +template L::L () : a {}, b {}, c {} {} +template L::~L () {} + +int a[2000]; +long b[40]; +short c[50]; +int d[1024]; +K e[1089]; +L f[1093]; +int results[2000]; + +template +static inline void +baz (I &i) +{ + results[*i]++; +} + +static inline void +baz (int i) +{ + results[i]++; +} + +void +f1 () +{ +#pragma omp parallel loop shared(a) default(none) + for (auto i : a) + baz (i); +} + +void +f2 () +{ +#pragma omp loop order(concurrent) bind(parallel) + for (auto &i : a) + if (&i != &a[i]) + abort (); + else + baz (i); +} + +void +f3 () +{ +#pragma omp teams loop 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 j) +{ +#pragma omp loop bind(teams) + for (auto &i : j) + if (&i != &a[i]) + abort (); + else + baz (i); +} + +void +f5 () +{ +#pragma omp loop bind(thread) + for (auto i : d) + results[i % 1024] += 2 * ((unsigned) i >> 10) + 1; +} + +void +f6 (J> j) +{ +#pragma omp loop bind(parallel) + 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> j) +{ +#pragma omp parallel loop 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> j) +{ +#pragma omp parallel loop default(none) shared(j) + for (auto [k, l, m] : j) + if (k != m * 3 || l != m * 2) + abort (); + else + baz (m); +} + +void +f9 (J> j) +{ +#pragma omp teams loop default(none) shared(j) + for (auto [k, l, m] : j) + if (l != k * 4 || m != k * 5) + abort (); + else + baz (k); +} + +template +void +f10 () +{ +#pragma omp loop bind(teams) + for (auto i : a) + baz (i); +} + +template +void +f11 () +{ +#pragma omp loop bind(thread) + for (auto &i : a) + if (&i != &a[i]) + abort (); + else + baz (i); +} + +template +void +f12 () +{ +#pragma omp parallel loop collapse(3) default(none) shared(a, b, c) bind(parallel) + for (auto &i : b) + for (I j = I (&a[9]); j < I (&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 +void +f13 (J j) +{ +#pragma omp loop bind(thread) + for (auto &i : j) + if (&i != &a[i]) + abort (); + else + baz (i); +} + +template +void +f14 () +{ +#pragma omp parallel loop default(none) shared(d, results) + for (auto i : d) + results[i % N] += 2 * ((unsigned) i >> 10) + 1; +} + +template +void +f15 (J> j) +{ +#pragma omp parallel loop default(none) shared(j, e) bind(parallel) + 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 +void +f16 (J> j) +{ +#pragma omp loop bind(parallel) + 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 +void +f17 (J> j) +{ +#pragma omp parallel loop default(none) shared(j) + for (auto [k, l, m] : j) + if (k != m * 3 || l != m * 2) + abort (); + else + baz (m); +} + +template +void +f18 (J> j) +{ +#pragma omp teams loop 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); + #pragma omp parallel + f2 (); + check (1); + f3 (); + check (1); + #pragma omp teams + f4 (J (&a[14], &a[1803])); + check (i >= 14 && i < 1803); + f5 (); + check (i >= 0 && i < 1024); + #pragma omp parallel + f6 (J> (&e[19], &e[1029])); + check (i >= 19 && i < 1029); + f7 (J> (&f[15], &f[1091])); + check (i >= 15 && i < 1091); + f8 (J> (&e[27], &e[1037])); + check (i >= 27 && i < 1037); + f9 (J> (&f[1], &f[1012])); + check (i >= 1 && i < 1012); + #pragma omp teams + f10 <0> (); + check (1); + f11 <1> (); + check (1); + f12 <2> (); + check (1); + f13 (J (&a[24], &a[1703])); + check (i >= 24 && i < 1703); + f14 <1024> (); + check (i >= 0 && i < 1024); + f15 (J> (&e[39], &e[929])); + check (i >= 39 && i < 929); + #pragma omp parallel + f16 (J> (&f[17], &f[1071])); + check (i >= 17 && i < 1071); + f17 <3> (J> (&e[7], &e[1017])); + check (i >= 7 && i < 1017); + f18 <5> (J> (&f[121], &f[1010])); + check (i >= 121 && i < 1010); +} -- cgit v1.1