public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* OpenMP 'simd', unexpected nesting of variable declaration in bind vs. 'private' clause
@ 2021-05-07 20:20 Thomas Schwinge
  2021-05-07 21:20 ` Jakub Jelinek
  0 siblings, 1 reply; 2+ messages in thread
From: Thomas Schwinge @ 2021-05-07 20:20 UTC (permalink / raw)
  To: Jakub Jelinek, gcc; +Cc: Julian Brown

[-- Attachment #1: Type: text/plain, Size: 1903 bytes --]

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

[-- Attachment #2: pr60682.C --]
[-- Type: text/plain, Size: 155 bytes --]

// 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;
}

[-- Attachment #3: loop-13.C --]
[-- Type: text/plain, Size: 4691 bytes --]

// 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);
}

[-- Attachment #4: pr90811.c --]
[-- Type: text/plain, Size: 182 bytes --]

// 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];
    }
}

[-- Attachment #5: simd-2.f90 --]
[-- Type: text/plain, Size: 479 bytes --]

! 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

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: OpenMP 'simd', unexpected nesting of variable declaration in bind vs. 'private' clause
  2021-05-07 20:20 OpenMP 'simd', unexpected nesting of variable declaration in bind vs. 'private' clause Thomas Schwinge
@ 2021-05-07 21:20 ` Jakub Jelinek
  0 siblings, 0 replies; 2+ messages in thread
From: Jakub Jelinek @ 2021-05-07 21:20 UTC (permalink / raw)
  To: Thomas Schwinge; +Cc: gcc, Julian Brown

On Fri, May 07, 2021 at 10:20:11PM +0200, Thomas Schwinge wrote:
> 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

That is intentional for TREE_ADDRESSABLE variables inside of simd, see
r10-2271-gd81ab49d0586fca0f3ee2f49c4581dd02508fcca
Even if they are local to the body, as they are addressable, we need to
ensure they are omplowered as the SIMD magic arrays, otherwise different
iterations could access the same copy and because we tell vectorizer
etc. the iterations are safe to be vectorized or even independent, we would
miscompile things.
This is the only exception when this happens and is a temporary thing from
the gimplification till OpenMP lowering/expansion.

	Jakub


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-05-07 21:20 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-07 20:20 OpenMP 'simd', unexpected nesting of variable declaration in bind vs. 'private' clause Thomas Schwinge
2021-05-07 21:20 ` Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).