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
next prev parent 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).