Update OpenACC data clause semantics to the 2.5 behavior
gcc/c-family/
* c-pragma.h (enum pragma_omp_clause): Add
PRAGMA_OACC_CLAUSE_{FINALIZE,IF_PRESENT}. Remove
PRAGMA_OACC_CLAUSE_PRESENT_OR_{COPY,COPYIN,COPYOUT,CREATE}.
gcc/c/
* c-parser.c (c_parser_omp_clause_name): Add support for finalize
and if_present. Make present_or_{copy,copyin,copyout,create} aliases
to their non-present_or_* counterparts. Make 'self' an alias to
PRAGMA_OACC_CLAUSE_HOST.
(c_parser_oacc_data_clause): Update GOMP mappings for
PRAGMA_OACC_CLAUSE_{COPY,COPYIN,COPYOUT,CREATE,DELETE}. Remove
PRAGMA_OACC_CLAUSE_{SELF,PRESENT_OR_*}.
(c_parser_oacc_all_clauses): Handle finalize and if_present clauses.
Remove support for present_or_* clauses.
(OACC_KERNELS_CLAUSE_MASK): Remove PRESENT_OR_* clauses.
(OACC_PARALLEL_CLAUSE_MASK): Likewise.
(OACC_DECLARE_CLAUSE_MASK): Likewise.
(OACC_DATA_CLAUSE_MASK): Likewise.
(OACC_ENTER_DATA_CLAUSE_MASK): Remove PRESENT_OR_* clauses.
(OACC_EXIT_DATA_CLAUSE_MASK): Add FINALIZE clause.
(OACC_UPDATE_CLAUSE_MASK): Remove SELF, add IF_PRESENT.
(c_parser_oacc_declare): Remove PRESENT_OR_* clauses.
* c-typeck.c (c_finish_omp_clauses): Handle IF_PRESENT and FINALIZE.
gcc/cp/
* parser.c (cp_parser_omp_clause_name): Add support for finalize
and if_present. Make present_or_{copy,copyin,copyout,create} aliases
to their non-present_or_* counterparts. Make 'self' an alias to
PRAGMA_OACC_CLAUSE_HOST.
(cp_parser_oacc_data_clause): Update GOMP mappings for
PRAGMA_OACC_CLAUSE_{COPY,COPYIN,COPYOUT,CREATE,DELETE}. Remove
PRAGMA_OACC_CLAUSE_{SELF,PRESENT_OR_*}.
(cp_parser_oacc_all_clauses): Handle finalize and if_present clauses.
Remove support for present_or_* clauses.
(OACC_KERNELS_CLAUSE_MASK): Remove PRESENT_OR_* clauses.
(OACC_PARALLEL_CLAUSE_MASK): Likewise.
(OACC_DECLARE_CLAUSE_MASK): Likewise.
(OACC_DATA_CLAUSE_MASK): Likewise.
(OACC_ENTER_DATA_CLAUSE_MASK): Remove PRESENT_OR_* clauses.
(OACC_EXIT_DATA_CLAUSE_MASK): Add FINALIZE clause.
(OACC_UPDATE_CLAUSE_MASK): Remove SELF, add IF_PRESENT.
(cp_parser_oacc_declare): Remove PRESENT_OR_* clauses.
* pt.c (tsubst_omp_clauses): Handle IF_PRESENT and FINALIZE.
* semantics.c (finish_omp_clauses): Handle IF_PRESENT and FINALIZE.
gcc/fortran/
* gfortran.h (gfc_omp_clauses): Add unsigned if_present, finalize
bitfields.
* openmp.c (enum omp_mask2): Remove OMP_CLAUSE_PRESENT_OR_*. Add
OMP_CLAUSE_{IF_PRESENT,FINALIZE}.
(gfc_match_omp_clauses): Update handling of copy, copyin, copyout,
create, deviceptr, present_of_*. Add support for finalize and
if_present.
(OACC_PARALLEL_CLAUSES): Remove PRESENT_OR_* clauses.
(OACC_KERNELS_CLAUSES): Likewise.
(OACC_DATA_CLAUSES): Likewise.
(OACC_DECLARE_CLAUSES): Likewise.
(OACC_UPDATE_CLAUSES): Add IF_PRESENT clause.
(OACC_ENTER_DATA_CLAUSES): Remove PRESENT_OR_* clauses.
(OACC_EXIT_DATA_CLAUSES): Add FINALIZE clause.
(gfc_match_oacc_declare): Update to OpenACC 2.5 semantics.
* trans-openmp.c (gfc_trans_omp_clauses): Add support for IF_PRESENT
and FINALIZE.
gcc/
* gimplify.c (gimplify_scan_omp_clauses): Add support for
OMP_CLAUSE_{IF_PRESENT,FINALIZE}.
(gimplify_adjust_omp_clauses): Likewise.
(gimplify_oacc_declare_1): Add support for GOMP_MAP_RELEASE, remove
support for GOMP_MAP_FORCE_{ALLOC,TO,FROM,TOFROM}.
(gimplify_omp_target_update): Update handling of acc update and
enter/exit data.
* omp-low.c (install_var_field): Remove unused parameter
base_pointers_restrict.
(scan_sharing_clauses): Remove base_pointers_restrict parameter.
Update call to install_var_field. Handle OMP_CLAUSE_{IF_PRESENT,
FINALIZE}
(omp_target_base_pointers_restrict_p): Delete.
(scan_omp_target): Update call to scan_sharing_clauses.
* tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_{IF_PRESENT,
FINALIZE}.
* tree-nested.c (convert_nonlocal_omp_clauses): Handle
OMP_CLAUSE_{IF_PRESENT,FINALIZE}.
(convert_local_omp_clauses): Likewise.
* tree-pretty-print.c (dump_omp_clause): Likewise.
* tree.c (omp_clause_num_ops): Add entries for OMP_CLAUSE_{IF_PRESENT,
FINALIZE}.
(omp_clause_code_name): Likewise.
gcc/testsuite/
* c-c++-common/goacc/declare-1.c: Update test case to utilize OpenACC
2.5 data clause semantics.
* c-c++-common/goacc/declare-2.c: Likewise.
* c-c++-common/goacc/default-4.c: Likewise.
* c-c++-common/goacc/finalize-1.c: New test.
* c-c++-common/goacc/kernels-alias-2.c: Update test case to utilize
OpenACC 2.5 data clause semantics.
* c-c++-common/goacc/kernels-alias.c: Likewise.
* c-c++-common/goacc/routine-5.c: Likewise.
* c-c++-common/goacc/update-if_present-1.c: New test.
* c-c++-common/goacc/update-if_present-2.c: New test.
* g++.dg/goacc/template.C: Update test case to utilize OpenACC
2.5 data clause semantics.
* gfortran.dg/goacc/combined-directives.f90: Likewise.
* gfortran.dg/goacc/data-tree.f95: Likewise.
* gfortran.dg/goacc/declare-2.f95: Likewise.
* gfortran.dg/goacc/default-4.f: Likewise.
* gfortran.dg/goacc/enter-exit-data.f95: Likewise.
* gfortran.dg/goacc/finalize-1.f: New test.
* gfortran.dg/goacc/kernels-alias-2.f95: Update test case to utilize
OpenACC 2.5 data clause semantics.
* gfortran.dg/goacc/kernels-alias.f95: Likewise.
* gfortran.dg/goacc/kernels-tree.f95: Likewise.
* gfortran.dg/goacc/nested-function-1.f90: Likewise.
* gfortran.dg/goacc/parallel-tree.f95: Likewise.
* gfortran.dg/goacc/reduction-promotions.f90: Likewise.
* gfortran.dg/goacc/update-if_present-1.f90: New test.
* gfortran.dg/goacc/update-if_present-2.f90: New test.
libgomp/
* libgomp.h (struct splay_tree_key_s): Add dynamic_refcount member.
(gomp_acc_remove_pointer): Update declaration.
(gomp_acc_declare_allocate): Declare.
(gomp_remove_var): Declare.
* libgomp.map (OACC_2.5): Define.
* oacc-mem.c (acc_map_data): Update refcount.
(acc_unmap_data): Likewise.
(present_create_copy): Likewise.
(acc_create): Add FLAG_PRESENT when calling present_create_copy.
(acc_copyin): Likewise.
(FLAG_FINALIZE): Define.
(delete_copyout): Update dynamic refcounts, add support for FINALIZE.
(acc_delete_finalize): New function.
(acc_delete_finalize_async): New function.
(acc_copyout_finalize): New function.
(acc_copyout_finalize_async): New function.
(gomp_acc_insert_pointer): Update refcounts.
(gomp_acc_remove_pointer): Return if data is not present on the
accelerator.
* oacc-parallel.c (find_pset): Rename to find_pointer.
(find_pointer): Add support for GOMP_MAP_POINTER.
(handle_ftn_pointers): New function.
(GOACC_parallel_keyed): Update refcounts of variables.
(GOACC_enter_exit_data): Add support for finalized data mappings.
Add support for GOMP_MAP_{TO,ALLOC,RELESE,FROM}. Update handling
of fortran arrays.
(GOACC_update): Add support for GOMP_MAP_{ALWAYS_POINTER,TO,FROM}.
(GOACC_declare): Add support for GOMP_MAP_RELEASE, remove support
for GOMP_MAP_FORCE_FROM.
* openacc.f90 (module openacc_internal): Add
acc_copyout_finalize_{32_h,64_h,array_h,_l}, and
acc_delete_finalize_{32_h,64_h,array_h,_l}. Add interfaces for
acc_copyout_finalize and acc_delete_finalize.
(acc_copyout_finalize_32_h): New subroutine.
(acc_copyout_finalize_64_h): New subroutine.
(acc_copyout_finalize_array_h): New subroutine.
(acc_delete_finalize_32_h): New subroutine.
(acc_delete_finalize_64_h): New subroutine.
(acc_delete_finalize_array_h): New subroutine.
* openacc.h (acc_copyout_finalize): Declare.
(acc_copyout_finalize_async): Declare.
(acc_delete_finalize): Declare.
(acc_delete_finalize_async): Declare.
* openacc_lib.h (acc_copyout_finalize): New interface.
(acc_delete_finalize): New interface.
* target.c (gomp_map_vars): Update dynamic_refcount.
(gomp_remove_var): New function.
(gomp_unmap_vars): Use it.
(gomp_unload_image_from_device): Likewise.
* testsuite/libgomp.oacc-c-c++-common/data-already-1.c: Update test
case to utilize OpenACC 2.5 data clause semantics.
* testsuite/libgomp.oacc-c-c++-common/data-already-2.c: Likewise.
* testsuite/libgomp.oacc-c-c++-common/data-already-3.c: Likewise.
* testsuite/libgomp.oacc-c-c++-common/data-already-4.c: Likewise.
* testsuite/libgomp.oacc-c-c++-common/data-already-5.c: Likewise.
* testsuite/libgomp.oacc-c-c++-common/data-already-6.c: Likewise.
* testsuite/libgomp.oacc-c-c++-common/data-already-7.c: Likewise.
* testsuite/libgomp.oacc-c-c++-common/data-already-8.c: Likewise.
* testsuite/libgomp.oacc-c-c++-common/lib-16.c: Likewise.
* testsuite/libgomp.oacc-c-c++-common/lib-25.c: Likewise.
* testsuite/libgomp.oacc-c-c++-common/lib-32.c: Likewise.
* testsuite/libgomp.oacc-c-c++-common/lib-83.c: Likewise.
* testsuite/libgomp.oacc-fortran/data-5.f90: New test.
* testsuite/libgomp.oacc-fortran/data-already-1.f: Update test case to
utilize OpenACC 2.5 data clause semantics.
* testsuite/libgomp.oacc-fortran/data-already-2.f: Likewise.
* testsuite/libgomp.oacc-fortran/data-already-3.f: Likewise.
* testsuite/libgomp.oacc-fortran/data-already-4.f: Likewise.
* testsuite/libgomp.oacc-fortran/data-already-5.f: Likewise.
* testsuite/libgomp.oacc-fortran/data-already-6.f: Likewise.
* testsuite/libgomp.oacc-fortran/data-already-7.f: Likewise.
* testsuite/libgomp.oacc-fortran/data-already-8.f: Likewise.
* testsuite/libgomp.oacc-fortran/lib-32-1.f: Likewise.
* testsuite/libgomp.oacc-fortran/lib-32-2.f: Likewise.
Co-Authored-By: Cesar Philippidis <cesar@codesourcery.com>
Co-Authored-By: Thomas Schwinge <thomas@codesourcery.com>
From-SVN: r261813
diff --git a/libgomp/oacc-parallel.c b/libgomp/oacc-parallel.c
index 9eae431..b80ace5 100644
--- a/libgomp/oacc-parallel.c
+++ b/libgomp/oacc-parallel.c
@@ -38,15 +38,68 @@
#include <stdarg.h>
#include <assert.h>
+/* Returns the number of mappings associated with the pointer or pset. PSET
+ have three mappings, whereas pointer have two. */
+
static int
-find_pset (int pos, size_t mapnum, unsigned short *kinds)
+find_pointer (int pos, size_t mapnum, unsigned short *kinds)
{
if (pos + 1 >= mapnum)
return 0;
unsigned char kind = kinds[pos+1] & 0xff;
- return kind == GOMP_MAP_TO_PSET;
+ if (kind == GOMP_MAP_TO_PSET)
+ return 3;
+ else if (kind == GOMP_MAP_POINTER)
+ return 2;
+
+ return 0;
+}
+
+/* Handle the mapping pair that are presented when a
+ deviceptr clause is used with Fortran. */
+
+static void
+handle_ftn_pointers (size_t mapnum, void **hostaddrs, size_t *sizes,
+ unsigned short *kinds)
+{
+ int i;
+
+ for (i = 0; i < mapnum; i++)
+ {
+ unsigned short kind1 = kinds[i] & 0xff;
+
+ /* Handle Fortran deviceptr clause. */
+ if (kind1 == GOMP_MAP_FORCE_DEVICEPTR)
+ {
+ unsigned short kind2;
+
+ if (i < (signed)mapnum - 1)
+ kind2 = kinds[i + 1] & 0xff;
+ else
+ kind2 = 0xffff;
+
+ if (sizes[i] == sizeof (void *))
+ continue;
+
+ /* At this point, we're dealing with a Fortran deviceptr.
+ If the next element is not what we're expecting, then
+ this is an instance of where the deviceptr variable was
+ not used within the region and the pointer was removed
+ by the gimplifier. */
+ if (kind2 == GOMP_MAP_POINTER
+ && sizes[i + 1] == 0
+ && hostaddrs[i] == *(void **)hostaddrs[i + 1])
+ {
+ kinds[i+1] = kinds[i];
+ sizes[i+1] = sizeof (void *);
+ }
+
+ /* Invalidate the entry. */
+ hostaddrs[i] = NULL;
+ }
+ }
}
static void goacc_wait (int async, int num_waits, va_list *ap);
@@ -88,6 +141,8 @@
thr = goacc_thread ();
acc_dev = thr->dev;
+ handle_ftn_pointers (mapnum, hostaddrs, sizes, kinds);
+
/* Host fallback if "if" clause is false or if the current device is set to
the host. */
if (host_fallback)
@@ -183,10 +238,29 @@
async, dims, tgt);
/* If running synchronously, unmap immediately. */
+ bool copyfrom = true;
if (async_synchronous_p (async))
gomp_unmap_vars (tgt, true);
else
- tgt->device_descr->openacc.register_async_cleanup_func (tgt, async);
+ {
+ bool async_unmap = false;
+ for (size_t i = 0; i < tgt->list_count; i++)
+ {
+ splay_tree_key k = tgt->list[i].key;
+ if (k && k->refcount == 1)
+ {
+ async_unmap = true;
+ break;
+ }
+ }
+ if (async_unmap)
+ tgt->device_descr->openacc.register_async_cleanup_func (tgt, async);
+ else
+ {
+ copyfrom = false;
+ gomp_unmap_vars (tgt, copyfrom);
+ }
+ }
acc_dev->openacc.async_set_async_func (acc_async_sync);
}
@@ -286,6 +360,17 @@
va_end (ap);
}
+ /* Determine whether "finalize" semantics apply to all mappings of this
+ OpenACC directive. */
+ bool finalize = false;
+ if (mapnum > 0)
+ {
+ unsigned char kind = kinds[0] & 0xff;
+ if (kind == GOMP_MAP_DELETE
+ || kind == GOMP_MAP_FORCE_FROM)
+ finalize = true;
+ }
+
acc_dev->openacc.async_set_async_func (async);
/* Determine if this is an "acc enter data". */
@@ -298,13 +383,17 @@
if (kind == GOMP_MAP_FORCE_ALLOC
|| kind == GOMP_MAP_FORCE_PRESENT
- || kind == GOMP_MAP_FORCE_TO)
+ || kind == GOMP_MAP_FORCE_TO
+ || kind == GOMP_MAP_TO
+ || kind == GOMP_MAP_ALLOC)
{
data_enter = true;
break;
}
- if (kind == GOMP_MAP_DELETE
+ if (kind == GOMP_MAP_RELEASE
+ || kind == GOMP_MAP_DELETE
+ || kind == GOMP_MAP_FROM
|| kind == GOMP_MAP_FORCE_FROM)
break;
@@ -312,31 +401,39 @@
kind);
}
+ /* In c, non-pointers and arrays are represented by a single data clause.
+ Dynamically allocated arrays and subarrays are represented by a data
+ clause followed by an internal GOMP_MAP_POINTER.
+
+ In fortran, scalars and not allocated arrays are represented by a
+ single data clause. Allocated arrays and subarrays have three mappings:
+ 1) the original data clause, 2) a PSET 3) a pointer to the array data.
+ */
+
if (data_enter)
{
for (i = 0; i < mapnum; i++)
{
unsigned char kind = kinds[i] & 0xff;
- /* Scan for PSETs. */
- int psets = find_pset (i, mapnum, kinds);
+ /* Scan for pointers and PSETs. */
+ int pointer = find_pointer (i, mapnum, kinds);
- if (!psets)
+ if (!pointer)
{
switch (kind)
{
- case GOMP_MAP_POINTER:
- gomp_acc_insert_pointer (1, &hostaddrs[i], &sizes[i],
- &kinds[i]);
+ case GOMP_MAP_ALLOC:
+ acc_present_or_create (hostaddrs[i], sizes[i]);
break;
case GOMP_MAP_FORCE_ALLOC:
acc_create (hostaddrs[i], sizes[i]);
break;
- case GOMP_MAP_FORCE_PRESENT:
+ case GOMP_MAP_TO:
acc_present_or_copyin (hostaddrs[i], sizes[i]);
break;
case GOMP_MAP_FORCE_TO:
- acc_present_or_copyin (hostaddrs[i], sizes[i]);
+ acc_copyin (hostaddrs[i], sizes[i]);
break;
default:
gomp_fatal (">>>> GOACC_enter_exit_data UNHANDLED kind 0x%.2x",
@@ -346,12 +443,13 @@
}
else
{
- gomp_acc_insert_pointer (3, &hostaddrs[i], &sizes[i], &kinds[i]);
+ gomp_acc_insert_pointer (pointer, &hostaddrs[i],
+ &sizes[i], &kinds[i]);
/* Increment 'i' by two because OpenACC requires fortran
arrays to be contiguous, so each PSET is associated with
one of MAP_FORCE_ALLOC/MAP_FORCE_PRESET/MAP_FORCE_TO, and
one MAP_POINTER. */
- i += 2;
+ i += pointer - 1;
}
}
}
@@ -360,22 +458,28 @@
{
unsigned char kind = kinds[i] & 0xff;
- int psets = find_pset (i, mapnum, kinds);
+ int pointer = find_pointer (i, mapnum, kinds);
- if (!psets)
+ if (!pointer)
{
switch (kind)
{
- case GOMP_MAP_POINTER:
- gomp_acc_remove_pointer (hostaddrs[i], (kinds[i] & 0xff)
- == GOMP_MAP_FORCE_FROM,
- async, 1);
- break;
+ case GOMP_MAP_RELEASE:
case GOMP_MAP_DELETE:
- acc_delete (hostaddrs[i], sizes[i]);
+ if (acc_is_present (hostaddrs[i], sizes[i]))
+ {
+ if (finalize)
+ acc_delete_finalize (hostaddrs[i], sizes[i]);
+ else
+ acc_delete (hostaddrs[i], sizes[i]);
+ }
break;
+ case GOMP_MAP_FROM:
case GOMP_MAP_FORCE_FROM:
- acc_copyout (hostaddrs[i], sizes[i]);
+ if (finalize)
+ acc_copyout_finalize (hostaddrs[i], sizes[i]);
+ else
+ acc_copyout (hostaddrs[i], sizes[i]);
break;
default:
gomp_fatal (">>>> GOACC_enter_exit_data UNHANDLED kind 0x%.2x",
@@ -385,10 +489,12 @@
}
else
{
- gomp_acc_remove_pointer (hostaddrs[i], (kinds[i] & 0xff)
- == GOMP_MAP_FORCE_FROM, async, 3);
+ bool copyfrom = (kind == GOMP_MAP_FORCE_FROM
+ || kind == GOMP_MAP_FROM);
+ gomp_acc_remove_pointer (hostaddrs[i], sizes[i], copyfrom, async,
+ finalize, pointer);
/* See the above comment. */
- i += 2;
+ i += pointer - 1;
}
}
@@ -447,6 +553,7 @@
acc_dev->openacc.async_set_async_func (async);
+ bool update_device = false;
for (i = 0; i < mapnum; ++i)
{
unsigned char kind = kinds[i] & 0xff;
@@ -457,11 +564,46 @@
case GOMP_MAP_TO_PSET:
break;
+ case GOMP_MAP_ALWAYS_POINTER:
+ if (update_device)
+ {
+ /* Save the contents of the host pointer. */
+ void *dptr = acc_deviceptr (hostaddrs[i-1]);
+ uintptr_t t = *(uintptr_t *) hostaddrs[i];
+
+ /* Update the contents of the host pointer to reflect
+ the value of the allocated device memory in the
+ previous pointer. */
+ *(uintptr_t *) hostaddrs[i] = (uintptr_t)dptr;
+ acc_update_device (hostaddrs[i], sizeof (uintptr_t));
+
+ /* Restore the host pointer. */
+ *(uintptr_t *) hostaddrs[i] = t;
+ update_device = false;
+ }
+ break;
+
+ case GOMP_MAP_TO:
+ if (!acc_is_present (hostaddrs[i], sizes[i]))
+ {
+ update_device = false;
+ break;
+ }
+ /* Fallthru */
case GOMP_MAP_FORCE_TO:
+ update_device = true;
acc_update_device (hostaddrs[i], sizes[i]);
break;
+ case GOMP_MAP_FROM:
+ if (!acc_is_present (hostaddrs[i], sizes[i]))
+ {
+ update_device = false;
+ break;
+ }
+ /* Fallthru */
case GOMP_MAP_FORCE_FROM:
+ update_device = false;
acc_update_self (hostaddrs[i], sizes[i]);
break;
@@ -522,6 +664,7 @@
case GOMP_MAP_FORCE_FROM:
case GOMP_MAP_FORCE_TO:
case GOMP_MAP_POINTER:
+ case GOMP_MAP_RELEASE:
case GOMP_MAP_DELETE:
GOACC_enter_exit_data (device, 1, &hostaddrs[i], &sizes[i],
&kinds[i], GOMP_ASYNC_SYNC, 0);
@@ -543,7 +686,6 @@
break;
case GOMP_MAP_FROM:
- kinds[i] = GOMP_MAP_FORCE_FROM;
GOACC_enter_exit_data (device, 1, &hostaddrs[i], &sizes[i],
&kinds[i], GOMP_ASYNC_SYNC, 0);
break;