Hi!

I'm currently working on an OpenACC thing, which in 'omp-low' separately
for each OpenACC 'loop' construct, collects variable declarations
referenced in 'private' clauses as well as those from inner binds
(simplified).  Accidently that was also enabled for OpenMP, and for a few
testcases of OpenMP 'simd', I found unexpected nesting of variable
declaration in bind vs. 'private' clause.

I'm having a check that each variable declaration encounter has not yet
been seen for the respective context, and there are a few testcases where
this triggers, all involving OpenMP 'simd', and all seem to exhibit the
similar pattern, that in the 'gimple' dump, we have:

    #pragma omp simd [...] private(D.2992)
    for ([...])
      {
        {
          const difference_type D.2992;

Notice that's a 'private' clause (created during gimplification?)
referring to a variable declaration of an *inner* bind.  In our code, the
'private' clause is processed first, and then later the inner bind
visited, where we again encounter the same variable declaration, and
crash.

Eventually, I'll of course disable this OpenACC-specific processing for
OpenMP contexts, but I'd like to know if I might encounter such a
scenario also for OpenACC (haven't quickly been able to replicate, is it
maybe really specific to OpenMP 'simd'?), and secondly, whether there's
something wrong in the OpenMP 'simd' implementation?

I'm seeing this for:

  - 'g++.dg/gomp/pr60682.C'
  - 'libgomp.c/pr90811.c'
  - 'libgomp.c++/loop-13.C'
  - 'libgomp.c++/loop-14.C'
  - 'libgomp.c++/loop-15.C'
  - 'libgomp.fortran/examples-4/simd-2.f90'

..., and I'm attaching a few reduced testcases.


Grüße
 Thomas


-----------------
Mentor Graphics (Deutschland) GmbH, Arnulfstrasse 201, 80634 München 
Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Frank 
Thürauf
// Reduced from 'g++.dg/gomp/pr60682.C'.

struct A
{
  float a;
  A () {}
};

void
foo (int x)
{
#pragma omp simd
  for (int i = 0; i < x; ++i)
    A a;
}
// Reduced from 'libgomp.c++/loop-13.C'.

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>
static inline void
baz (I<T> &i)
{
  results[*i]++;
}

void
f1 (const I<int> &x, const I<int> &y)
{
#pragma omp parallel loop
  for (I<int> i = x; i <= y; i += 6)
    baz (i);
}
// Reduced from 'libgomp.c/pr90811.c'.

void
f ()
{
  #pragma omp simd
  for (int i = 0; i < 100; i++)
    {
      const int d[] = { 0 };
      int j = 0;
      (void) d[j];
    }
}
! Reduced from 'libgomp.fortran/examples-4/simd-2.f90'.

module SIMD2_mod
contains
  function add2(a) result(c)
  !$omp declare simd(add2) uniform(a)
     double precision, dimension(:) :: a
     double precision               :: c

     c = 0
  end function

  subroutine work(a, n)
     implicit none
     double precision           :: a(n)
     integer                    :: n, i

     !$omp simd
     do i = 1,n
        a(i) = add2(a)
     end do
  end subroutine
end module

Reply via email to