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

Reply via email to