Hi! This undoes the splitting of private clauses to parallel instead of innermost. I should one day change the clause splitting to match exactly what was agreed on in OpenMP 5.0, without the exceptions because we've done something differently in the past, but I'm afraid it will be a lot of work.
Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk, queued for backporting. 2019-07-31 Jakub Jelinek <ja...@redhat.com> PR middle-end/91301 * gimplify.c (gimplify_omp_for): If for class iterator on distribute parallel for there is no data sharing clause on inner_for_stmt, look for private clause on combined parallel too and if found, move it to inner_for_stmt. * testsuite/libgomp.c++/for-27.C: New test. --- gcc/gimplify.c.jj 2019-07-30 17:21:17.189694558 +0200 +++ gcc/gimplify.c 2019-07-30 18:56:54.342267818 +0200 @@ -10668,6 +10668,22 @@ gimplify_omp_for (tree *expr_p, gimple_s && OMP_CLAUSE_DECL (*pc) == orig_decl) break; if (*pc == NULL_TREE) + { + tree *spc; + for (spc = &OMP_PARALLEL_CLAUSES (*data[1]); + *spc; spc = &OMP_CLAUSE_CHAIN (*spc)) + if (OMP_CLAUSE_CODE (*spc) == OMP_CLAUSE_PRIVATE + && OMP_CLAUSE_DECL (*spc) == orig_decl) + break; + if (*spc) + { + tree c = *spc; + *spc = OMP_CLAUSE_CHAIN (c); + OMP_CLAUSE_CHAIN (c) = NULL_TREE; + *pc = c; + } + } + if (*pc == NULL_TREE) ; else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_PRIVATE) { --- libgomp/testsuite/libgomp.c++/for-27.C.jj 2019-07-30 19:26:45.321254401 +0200 +++ libgomp/testsuite/libgomp.c++/for-27.C 2019-07-30 19:25:27.455384720 +0200 @@ -0,0 +1,169 @@ +// { dg-do run } + +typedef __PTRDIFF_TYPE__ ptrdiff_t; +extern "C" void abort (); + +int a[2000]; + +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]++; +} + +static inline void +baz (int i) +{ + results[i]++; +} + +void +f1 () +{ +#pragma omp simd + for (auto i : a) + baz (i); +} + +void +f2 (const I<int> &x, const I<int> &y) +{ + I<int> i; +#pragma omp distribute parallel for + for (i = x; i <= y; i += 6) + baz (*i); +} + +void +f3 (const I<int> &x, const I<int> &y) +{ + I<int> i; +#pragma omp distribute parallel for private (i) + for (i = x; i < y - 1; i = 1 - 6 + 7 + i) + baz (*i); +} + +void +f4 (const I<int> &x, const I<int> &y) +{ + I<int> i; +#pragma omp teams distribute parallel for lastprivate (i) + for (i = x + 2000 - 64; i > y + 10; --i) + 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 () +{ + for (int i = 0; i < 2000; i++) + a[i] = i; + f1 (); + check (1); + #pragma omp teams + f2 (&a[10], &a[1990]); + check (i >= 10 && i <= 1990 && (i - 10) % 6 == 0); + #pragma omp teams + f3 (&a[0], &a[1999]); + check (i < 1998 && (i & 1) == 0); + f4 (&a[0], &a[30]); + check (i > 40 && i <= 2000 - 64); +} Jakub