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