public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Thomas Schwinge <thomas@codesourcery.com>
To: Julian Brown <julian@codesourcery.com>
Cc: Jakub Jelinek <jakub@redhat.com>, <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH 3/3] OpenACC dynamic data lifetimes ending within structured blocks
Date: Mon, 11 May 2020 17:05:29 +0200	[thread overview]
Message-ID: <87d07aa4w6.fsf@euler.schwinge.homeip.net> (raw)
In-Reply-To: <4673a5070087e465f6dd123715d409b35b875ca1.1579292772.git.julian@codesourcery.com>

Hi Julian!

On 2020-01-17T13:18:21-0800, Julian Brown <julian@codesourcery.com> wrote:
> This patch adds a new function to logically decrement the "dynamic
> reference counter" for a mapped OpenACC variable, and handles some cases
> in which that counter drops to zero inside a structured data
> block. Previously, it's likely that at least in some cases, ending a
> dynamic data lifetime in this way could behave unpredictably.
>
> Several new test cases are included.

As discussed before, all these test cases were already PASSing before any
of this thread's suggested patches (also for GCC 9), so "from a user's
point of view", all we get here are testsuite regressions:

  - 'libgomp.oacc-c-c++-common/structured-dynamic-lifetimes-6-lib.c'
  - 'libgomp.oacc-c-c++-common/structured-dynamic-lifetimes-6.c'
  - 'libgomp.oacc-c-c++-common/structured-dynamic-lifetimes-7-lib.c'
  - 'libgomp.oacc-c-c++-common/structured-dynamic-lifetimes-7.c'
  - 'libgomp.oacc-c-c++-common/structured-dynamic-lifetimes-8-lib.c'
  - 'libgomp.oacc-c-c++-common/structured-dynamic-lifetimes-8.c'

(Adjusted for the version of the test cases already committed; but
already XFAILed in your original patch submission, see below.)


And: the code changes proposed here are breaking compatibility with GCC
9, such that OpenACC/Fortran code compiled with GCC 9, but running with
recent runtime libraries (common case for users, distributions) would
then terminate with: 'libgomp: cannot handle 'exit data' within data
region'.  For example, half of all 'libgomp.oacc-fortran' test cases
using OpenACC 'exit data':

  - 'libgomp.oacc-fortran/data-2.f90'
  - 'libgomp.oacc-fortran/data-3.f90'
  - 'libgomp.oacc-fortran/data-4-2.f90'
  - 'libgomp.oacc-fortran/data-4.f90'
  - 'libgomp.oacc-fortran/if-1.f90'

Even though that "code generation problem" doesn't exist with GCC 10 and
newer, we still have to maintain ABI compatibility with existing binaries
compiled compiled with GCC 9.  (Or, as a less preferred solution, arrange
so that they use host-fallback execution insted of offloading.)


Grüße
 Thomas


> This patch is strongly related to the previous two, but is somewhat of
> a separate change, and those two patches can stand alone if this one
> gets deferred.
>
> Tested alongside the previous patches in the series with offloading to NVPTX.
>
> OK?
>
> Thanks,
>
> Julian
>
> ChangeLog
>
>       libgomp/
>       * oacc-mem.c (decr_dynamic_refcount): New function.
>       (goacc_exit_datum): Call above function.
>       (goacc_exit_data_internal): Call above function.
>       * testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-1.c: New
>       test.
>       * testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-1-lib.c:
>       Likewise.
>       * testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-6.c:
>       Likewise.
>       * testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-6-lib.c:
>       Likewise.
>       * testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-7.c:
>       Likewise.
>       * testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-7-lib.c:
>       Likewise.
>       * testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-8.c:
>       Likewise.
>       * testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-8-lib.c:
>       Likewise.
> ---
>  libgomp/oacc-mem.c                            | 128 ++++++++++----
>  .../static-dynamic-lifetimes-1-lib.c          |   3 +
>  .../static-dynamic-lifetimes-1.c              | 160 ++++++++++++++++++
>  .../static-dynamic-lifetimes-6-lib.c          |   5 +
>  .../static-dynamic-lifetimes-6.c              |  46 +++++
>  .../static-dynamic-lifetimes-7-lib.c          |   5 +
>  .../static-dynamic-lifetimes-7.c              |  45 +++++
>  .../static-dynamic-lifetimes-8-lib.c          |   5 +
>  .../static-dynamic-lifetimes-8.c              |  50 ++++++
>  9 files changed, 412 insertions(+), 35 deletions(-)
>  create mode 100644 libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-1-lib.c
>  create mode 100644 libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-1.c
>  create mode 100644 libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-6-lib.c
>  create mode 100644 libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-6.c
>  create mode 100644 libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-7-lib.c
>  create mode 100644 libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-7.c
>  create mode 100644 libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-8-lib.c
>  create mode 100644 libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-8.c
>
> diff --git a/libgomp/oacc-mem.c b/libgomp/oacc-mem.c
> index 783e7f363fb..f34ffa67079 100644
> --- a/libgomp/oacc-mem.c
> +++ b/libgomp/oacc-mem.c
> @@ -725,6 +725,92 @@ acc_pcopyin (void *h, size_t s)
>  #endif
>
>
> +/* Perform actions necessary to decrement the dynamic reference counter for
> +   splay tree key N.  Returns TRUE on success, or FALSE on failure (e.g. if we
> +   hit a case we can't presently handle inside a data region).  */
> +
> +static bool
> +decr_dynamic_refcount (splay_tree_key n, bool finalize)
> +{
> +  if (finalize)
> +    {
> +      if (n->refcount != REFCOUNT_INFINITY)
> +     n->refcount -= n->virtual_refcount;
> +      n->virtual_refcount = 0;
> +    }
> +
> +  if (n->virtual_refcount > 0)
> +    {
> +      if (n->refcount != REFCOUNT_INFINITY)
> +     n->refcount--;
> +      n->virtual_refcount--;
> +    }
> +  /* An initial "enter data" mapping might create a target_mem_desc (in
> +     gomp_map_vars_async via goacc_enter_datum or
> +     goacc_enter_data_internal).  In that case we have a structural
> +     reference count but a zero virtual reference count: we nevertheless
> +     want to do the "exit data" operation here.  Detect the special case
> +     using a sentinel value stored in the "prev" field, which is otherwise
> +     unused for dynamic data mappings.  */
> +  else if (n->refcount > 0
> +        && n->refcount != REFCOUNT_INFINITY
> +        && n->tgt->prev == &dyn_tgt_sentinel)
> +    {
> +      n->refcount--;
> +      /* We know n->virtual_refcount is zero here, so if we still have a
> +      non-zero n->refcount we are ending a dynamically-scoped variable
> +      lifetime in the middle of a static lifetime for the same variable.
> +      If we're not careful this results in a dangling reference.  Attempt
> +      to handle this here, if only in simple cases.  E.g.:
> +
> +        #pragma acc enter data copyin(var)
> +        #pragma acc data copy(var{, ...})
> +        {
> +          #pragma acc exit data copyout(var)
> +        }
> +
> +      Here (the "exit data"), we reattach the relevant fields of the
> +      previously dynamically-scoped target_mem_desc to the static data
> +      region's target_mem_desc, hence merging the former into the latter.
> +      The old dynamic target_mem_desc can then be freed.
> +
> +      We can't deal with static data regions that refer to existing dynamic
> +      data mappings or that introduce new static lifetimes of their own.  */
> +      if (n->refcount > 0
> +       && n->tgt->list_count == 1
> +       && n->tgt->refcount == 1)
> +     {
> +       struct goacc_thread *thr = goacc_thread ();
> +       struct target_mem_desc *tgt, *static_tgt = NULL;
> +       for (tgt = thr->mapped_data;
> +            tgt != NULL && static_tgt == NULL;
> +            tgt = tgt->prev)
> +         for (int j = 0; j < tgt->list_count; j++)
> +           if (tgt->list[j].key == n)
> +             {
> +               static_tgt = tgt;
> +               break;
> +             }
> +       if (!static_tgt
> +           || static_tgt->to_free != NULL
> +           || static_tgt->array != NULL)
> +         return false;
> +       static_tgt->to_free = n->tgt->to_free;
> +       static_tgt->array = n->tgt->array;
> +       static_tgt->tgt_start = n->tgt->tgt_start;
> +       static_tgt->tgt_end = n->tgt->tgt_end;
> +       static_tgt->to_free = n->tgt->to_free;
> +       static_tgt->refcount++;
> +       free (n->tgt);
> +       n->tgt = static_tgt;
> +     }
> +      else if (n->refcount > 0)
> +     return false;
> +    }
> +
> +  return true;
> +}
> +
>  /* Exit a dynamic mapping for a single variable.  */
>
>  static void
> @@ -767,29 +853,12 @@ goacc_exit_datum (void *h, size_t s, unsigned short kind, int async)
>
>    bool finalize = (kind == GOMP_MAP_DELETE
>                  || kind == GOMP_MAP_FORCE_FROM);
> -  if (finalize)
> -    {
> -      if (n->refcount != REFCOUNT_INFINITY)
> -     n->refcount -= n->virtual_refcount;
> -      n->virtual_refcount = 0;
> -    }
>
> -  if (n->virtual_refcount > 0)
> +  if (!decr_dynamic_refcount (n, finalize))
>      {
> -      if (n->refcount != REFCOUNT_INFINITY)
> -     n->refcount--;
> -      n->virtual_refcount--;
> +      gomp_mutex_unlock (&acc_dev->lock);
> +      gomp_fatal ("cannot handle delete/copyout within data region");
>      }
> -  /* An initial "enter data" mapping might create a target_mem_desc (in
> -     gomp_map_vars_async via goacc_enter_datum).  In that case we have a
> -     structural reference count but a zero virtual reference count: we
> -     nevertheless want to do the "exit data" operation here.  Detect the
> -     special case using a sentinel value stored in the "prev" field, which is
> -     otherwise unused for dynamic data mappings.  */
> -  else if (n->refcount > 0
> -        && n->refcount != REFCOUNT_INFINITY
> -        && n->tgt->prev == &dyn_tgt_sentinel)
> -    n->refcount--;
>
>    if (n->refcount == 0)
>      {
> @@ -1216,23 +1285,12 @@ goacc_exit_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum,
>           if (n == NULL)
>             continue;
>
> -         if (finalize)
> -           {
> -             if (n->refcount != REFCOUNT_INFINITY)
> -               n->refcount -= n->virtual_refcount;
> -             n->virtual_refcount = 0;
> -           }
> -
> -         if (n->virtual_refcount > 0)
> +         if (!decr_dynamic_refcount (n, finalize))
>             {
> -             if (n->refcount != REFCOUNT_INFINITY)
> -               n->refcount--;
> -             n->virtual_refcount--;
> +             /* The user is trying to do something too tricky for us.  */
> +             gomp_mutex_unlock (&acc_dev->lock);
> +             gomp_fatal ("cannot handle 'exit data' within data region");
>             }
> -         else if (n->refcount > 0
> -                  && n->refcount != REFCOUNT_INFINITY
> -                  && n->tgt->prev == &dyn_tgt_sentinel)
> -           n->refcount--;
>
>           if (copyfrom
>               && n->refcount != REFCOUNT_INFINITY
> diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-1-lib.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-1-lib.c
> new file mode 100644
> index 00000000000..23c20d4fab7
> --- /dev/null
> +++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-1-lib.c
> @@ -0,0 +1,3 @@
> +/* { dg-skip-if "" { *-*-* } { "-DACC_MEM_SHARED=1" } } */
> +/* { dg-additional-options "-DOPENACC_API" } */
> +#include "static-dynamic-lifetimes-1.c"
> diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-1.c
> new file mode 100644
> index 00000000000..a743660f53e
> --- /dev/null
> +++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-1.c
> @@ -0,0 +1,160 @@
> +/* Test transitioning of data lifetimes between static and dynamic.  */
> +
> +/* { dg-skip-if "" { *-*-* } { "-DACC_MEM_SHARED=1" } } */
> +
> +#include <openacc.h>
> +#include <assert.h>
> +#include <stdlib.h>
> +
> +#define SIZE 1024
> +
> +void
> +f1 (void)
> +{
> +  char *block1 = (char *) malloc (SIZE);
> +
> +#ifdef OPENACC_API
> +  acc_copyin (block1, SIZE);
> +  acc_copyin (block1, SIZE);
> +#else
> +#pragma acc enter data copyin(block1[0:SIZE])
> +#pragma acc enter data copyin(block1[0:SIZE])
> +#endif
> +
> +#pragma acc data copy(block1[0:SIZE])
> +  {
> +#ifdef OPENACC_API
> +    acc_copyin (block1, SIZE);
> +#else
> +#pragma acc enter data copyin(block1[0:SIZE])
> +#endif
> +  }
> +
> +  assert (acc_is_present (block1, SIZE));
> +
> +#ifdef OPENACC_API
> +  acc_copyout (block1, SIZE);
> +  assert (acc_is_present (block1, SIZE));
> +  acc_copyout (block1, SIZE);
> +  assert (acc_is_present (block1, SIZE));
> +  acc_copyout (block1, SIZE);
> +  assert (!acc_is_present (block1, SIZE));
> +#else
> +#pragma acc exit data copyout(block1[0:SIZE])
> +  assert (acc_is_present (block1, SIZE));
> +#pragma acc exit data copyout(block1[0:SIZE])
> +  assert (acc_is_present (block1, SIZE));
> +#pragma acc exit data copyout(block1[0:SIZE])
> +  assert (!acc_is_present (block1, SIZE));
> +#endif
> +
> +  free (block1);
> +}
> +
> +void
> +f2 (void)
> +{
> +  char *block1 = (char *) malloc (SIZE);
> +
> +#ifdef OPENACC_API
> +  acc_copyin (block1, SIZE);
> +#else
> +#pragma acc enter data copyin(block1[0:SIZE])
> +#endif
> +
> +#pragma acc data copy(block1[0:SIZE])
> +  {
> +#ifdef OPENACC_API
> +    acc_copyout (block1, SIZE);
> +#else
> +#pragma acc exit data copyout(block1[0:SIZE])
> +#endif
> +    /* This should stay present until the end of the static data lifetime.  */
> +    assert (acc_is_present (block1, SIZE));
> +  }
> +
> +  assert (!acc_is_present (block1, SIZE));
> +
> +  free (block1);
> +}
> +
> +void
> +f3 (void)
> +{
> +  char *block1 = (char *) malloc (SIZE);
> +
> +#ifdef OPENACC_API
> +  acc_copyin (block1, SIZE);
> +#else
> +#pragma acc enter data copyin(block1[0:SIZE])
> +#endif
> +
> +#pragma acc data copy(block1[0:SIZE])
> +  {
> +#ifdef OPENACC_API
> +    acc_copyout (block1, SIZE);
> +    acc_copyin (block1, SIZE);
> +#else
> +#pragma acc exit data copyout(block1[0:SIZE])
> +#pragma acc enter data copyin(block1[0:SIZE])
> +#endif
> +    assert (acc_is_present (block1, SIZE));
> +  }
> +
> +  assert (acc_is_present (block1, SIZE));
> +#ifdef OPENACC_API
> +  acc_copyout (block1, SIZE);
> +#else
> +#pragma acc exit data copyout(block1[0:SIZE])
> +#endif
> +  assert (!acc_is_present (block1, SIZE));
> +
> +  free (block1);
> +}
> +
> +void
> +f4 (void)
> +{
> +  char *block1 = (char *) malloc (SIZE);
> +  char *block2 = (char *) malloc (SIZE);
> +  char *block3 = (char *) malloc (SIZE);
> +
> +#pragma acc data copy(block1[0:SIZE], block2[0:SIZE], block3[0:SIZE])
> +  {
> +  /* The first copyin of block2 is the enclosing data region.  This
> +     "enter data" should make it live beyond the end of this region.
> +     This works, though the on-target copies of block1, block2 and block3
> +     will stay allocated until block2 is unmapped because they are bound
> +     together in a single target_mem_desc.  */
> +#ifdef OPENACC_API
> +    acc_copyin (block2, SIZE);
> +#else
> +#pragma acc enter data copyin(block2[0:SIZE])
> +#endif
> +  }
> +
> +  assert (!acc_is_present (block1, SIZE));
> +  assert (acc_is_present (block2, SIZE));
> +  assert (!acc_is_present (block3, SIZE));
> +
> +#ifdef OPENACC_API
> +  acc_copyout (block2, SIZE);
> +#else
> +#pragma acc exit data copyout(block2[0:SIZE])
> +#endif
> +  assert (!acc_is_present (block2, SIZE));
> +
> +  free (block1);
> +  free (block2);
> +  free (block3);
> +}
> +
> +int
> +main (int argc, char *argv[])
> +{
> +  f1 ();
> +  f2 ();
> +  f3 ();
> +  f4 ();
> +  return 0;
> +}
> diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-6-lib.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-6-lib.c
> new file mode 100644
> index 00000000000..8507a0586a5
> --- /dev/null
> +++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-6-lib.c
> @@ -0,0 +1,5 @@
> +/* { dg-skip-if "" { *-*-* } { "-DACC_MEM_SHARED=1" } } */
> +/* { dg-additional-options "-DOPENACC_API" } */
> +#include "static-dynamic-lifetimes-6.c"
> +/* { dg-output "libgomp: cannot handle delete/copyout within data region" } */
> +/* { dg-shouldfail "" } */
> diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-6.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-6.c
> new file mode 100644
> index 00000000000..ca3b385fbcc
> --- /dev/null
> +++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-6.c
> @@ -0,0 +1,46 @@
> +/* { dg-skip-if "" { *-*-* } { "-DACC_MEM_SHARED=1" } } */
> +
> +#include <openacc.h>
> +#include <assert.h>
> +#include <stdlib.h>
> +
> +#define SIZE 1024
> +
> +int
> +main (int argc, char *argv[])
> +{
> +  char *block1 = (char *) malloc (SIZE);
> +  char *block2 = (char *) malloc (SIZE);
> +
> +#ifdef OPENACC_API
> +  acc_copyin (block1, SIZE);
> +  acc_copyin (block2, SIZE);
> +#else
> +#pragma acc enter data copyin(block1[0:SIZE], block2[0:SIZE])
> +#endif
> +
> +#pragma acc data copy(block1[0:SIZE], block2[0:SIZE])
> +  {
> +#ifdef OPENACC_API
> +    acc_copyout (block1, SIZE);
> +    acc_copyout (block2, SIZE);
> +    /* Error output checked in static-dynamic-lifetimes-6-lib.c.  */
> +#else
> +#pragma acc exit data copyout(block1[0:SIZE], block2[0:SIZE])
> +/* We can only do this for a single dynamic data mapping at present.  */
> +/* { dg-output "libgomp: cannot handle .exit data. within data region" } */
> +/* { dg-shouldfail "" } */
> +#endif
> +    /* These should stay present until the end of the static data lifetime.  */
> +    assert (acc_is_present (block1, SIZE));
> +    assert (acc_is_present (block2, SIZE));
> +  }
> +
> +  assert (!acc_is_present (block1, SIZE));
> +  assert (!acc_is_present (block2, SIZE));
> +
> +  free (block1);
> +  free (block2);
> +
> +  return 0;
> +}
> diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-7-lib.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-7-lib.c
> new file mode 100644
> index 00000000000..962b5926f79
> --- /dev/null
> +++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-7-lib.c
> @@ -0,0 +1,5 @@
> +/* { dg-skip-if "" { *-*-* } { "-DACC_MEM_SHARED=1" } } */
> +/* { dg-additional-options "-DOPENACC_API" } */
> +#include "static-dynamic-lifetimes-7.c"
> +/* { dg-output "libgomp: cannot handle delete/copyout within data region" } */
> +/* { dg-shouldfail "" } */
> diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-7.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-7.c
> new file mode 100644
> index 00000000000..dfcc7cae961
> --- /dev/null
> +++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-7.c
> @@ -0,0 +1,45 @@
> +/* { dg-skip-if "" { *-*-* } { "-DACC_MEM_SHARED=1" } } */
> +
> +#include <openacc.h>
> +#include <assert.h>
> +#include <stdlib.h>
> +
> +#define SIZE 1024
> +
> +int
> +main (int argc, char *argv[])
> +{
> +  char *block1 = (char *) malloc (SIZE);
> +  char *block2 = (char *) malloc (SIZE);
> +
> +#ifdef OPENACC_API
> +  acc_copyin (block1, SIZE);
> +#else
> +#pragma acc enter data copyin(block1[0:SIZE])
> +#endif
> +
> +#pragma acc data copy(block1[0:SIZE], block2[0:SIZE])
> +  {
> +/* We can't attach the dynamic data mapping's (block1) target_mem_desc to the
> +   enclosing static data region here, because that region maps block2 also.  */
> +#ifdef OPENACC_API
> +    acc_copyout (block1, SIZE);
> +    /* Error output checked in static-dynamic-lifetimes-7-lib.c.  */
> +#else
> +#pragma acc exit data copyout(block1[0:SIZE])
> +/* { dg-output "libgomp: cannot handle .exit data. within data region" } */
> +/* { dg-shouldfail "" } */
> +#endif
> +    /* These should stay present until the end of the static data lifetime.  */
> +    assert (acc_is_present (block1, SIZE));
> +    assert (acc_is_present (block2, SIZE));
> +  }
> +
> +  assert (!acc_is_present (block1, SIZE));
> +  assert (!acc_is_present (block2, SIZE));
> +
> +  free (block1);
> +  free (block2);
> +
> +  return 0;
> +}
> diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-8-lib.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-8-lib.c
> new file mode 100644
> index 00000000000..2581d7e2559
> --- /dev/null
> +++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-8-lib.c
> @@ -0,0 +1,5 @@
> +/* { dg-skip-if "" { *-*-* } { "-DACC_MEM_SHARED=1" } } */
> +/* { dg-additional-options "-DOPENACC_API" } */
> +#include "static-dynamic-lifetimes-8.c"
> +/* { dg-output "libgomp: cannot handle delete/copyout within data region" } */
> +/* { dg-shouldfail "" } */
> diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-8.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-8.c
> new file mode 100644
> index 00000000000..e3a64399fe9
> --- /dev/null
> +++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/static-dynamic-lifetimes-8.c
> @@ -0,0 +1,50 @@
> +/* { dg-skip-if "" { *-*-* } { "-DACC_MEM_SHARED=1" } } */
> +
> +#include <openacc.h>
> +#include <assert.h>
> +#include <stdlib.h>
> +
> +#define SIZE 1024
> +
> +int
> +main (int argc, char *argv[])
> +{
> +  char *block1 = (char *) malloc (SIZE);
> +  char *block2 = (char *) malloc (SIZE);
> +
> +#ifdef OPENACC_API
> +  acc_copyin (block1, SIZE);
> +#else
> +#pragma acc enter data copyin(block1[0:SIZE])
> +#endif
> +
> +#pragma acc data copy(block1[0:SIZE], block2[0:SIZE])
> +  {
> +#ifdef OPENACC_API
> +    acc_copyout (block1, SIZE);
> +    acc_copyin (block2, SIZE);
> +    /* Error output checked in static-dynamic-lifetimes-8-lib.c.  */
> +#else
> +#pragma acc exit data copyout(block1[0:SIZE])
> +/* { dg-output "libgomp: cannot handle .exit data. within data region" } */
> +/* { dg-shouldfail "" } */
> +#pragma acc enter data copyin(block2[0:SIZE])
> +#endif
> +    assert (acc_is_present (block1, SIZE));
> +    assert (acc_is_present (block2, SIZE));
> +  }
> +
> +  assert (!acc_is_present (block1, SIZE));
> +  assert (acc_is_present (block2, SIZE));
> +#ifdef OPENACC_API
> +  acc_copyout (block2, SIZE);
> +#else
> +#pragma acc exit data copyout(block2[0:SIZE])
> +#endif
> +  assert (!acc_is_present (block2, SIZE));
> +
> +  free (block1);
> +  free (block2);
> +
> +  return 0;
> +}
-----------------
Mentor Graphics (Deutschland) GmbH, Arnulfstraße 201, 80634 München / Germany
Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Alexander Walter

  reply	other threads:[~2020-05-11 15:05 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-17 21:18 [PATCH 0/3] Mixed static/dynamic data lifetimes with OpenACC (PR92843) Julian Brown
2020-01-17 21:20 ` [PATCH 2/3] Don't copy back vars mapped with acc_map_data Julian Brown
2020-07-03 15:53   ` Thomas Schwinge
2020-01-17 21:31 ` [PATCH 3/3] OpenACC dynamic data lifetimes ending within structured blocks Julian Brown
2020-05-11 15:05   ` Thomas Schwinge [this message]
2020-01-17 21:31 ` [PATCH 1/3] Introduce dynamic data mapping sentinel for OpenACC Julian Brown
2020-04-10 14:44 ` Test cases for mixed structured/dynamic data lifetimes with OpenACC [PR92843] (was: [PATCH 0/3] Mixed static/dynamic data lifetimes with OpenACC (PR92843)) Thomas Schwinge
2020-04-13  7:23   ` Test cases for mixed structured/dynamic data lifetimes with OpenACC [PR92843] Thomas Schwinge

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87d07aa4w6.fsf@euler.schwinge.homeip.net \
    --to=thomas@codesourcery.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jakub@redhat.com \
    --cc=julian@codesourcery.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).