ba40277f6a
libgomp/ PR libgomp/92848 * oacc-mem.c (acc_map_data, present_create_copy) (goacc_insert_pointer): Use 'GOMP_MAP_VARS_ENTER_DATA'. (acc_unmap_data, delete_copyout, goacc_remove_pointer): Adjust. * testsuite/libgomp.oacc-c-c++-common/lib-50.c: Remove. * testsuite/libgomp.oacc-c-c++-common/pr92848-1-d-a.c: New file * testsuite/libgomp.oacc-c-c++-common/pr92848-1-d-p.c: Likewise. * testsuite/libgomp.oacc-c-c++-common/pr92848-1-r-a.c: Likewise. * testsuite/libgomp.oacc-c-c++-common/pr92848-1-r-p.c: Likewise. * testsuite/libgomp.oacc-c-c++-common/subset-subarray-mappings-1-r-p.c: Remove "XFAIL"s. From-SVN: r279530
499 lines
13 KiB
C
499 lines
13 KiB
C
/* Test "subset" subarray mappings
|
|
{ dg-additional-options "-DOPENACC_RUNTIME" } using OpenACC Runtime Library routines,
|
|
{ dg-additional-options "-DPOINTERS" } using pointers. */
|
|
|
|
/* { dg-skip-if "" { *-*-* } { "-DACC_MEM_SHARED=1" } } */
|
|
|
|
#if OPENACC_RUNTIME
|
|
#elif OPENACC_DIRECTIVES
|
|
#else
|
|
# error
|
|
#endif
|
|
|
|
#if POINTERS
|
|
#elif ARRAYS
|
|
#else
|
|
# error
|
|
#endif
|
|
|
|
|
|
#include <openacc.h>
|
|
#include <acc_prof.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
|
|
static bool cb_ev_alloc_expected;
|
|
static size_t cb_ev_alloc_bytes;
|
|
static const void *cb_ev_alloc_device_ptr;
|
|
static void
|
|
cb_ev_alloc (acc_prof_info *prof_info, acc_event_info *event_info, acc_api_info *api_info)
|
|
{
|
|
assert (cb_ev_alloc_expected);
|
|
cb_ev_alloc_expected = false;
|
|
|
|
cb_ev_alloc_bytes = event_info->data_event.bytes;
|
|
cb_ev_alloc_device_ptr = event_info->data_event.device_ptr;
|
|
}
|
|
|
|
static bool cb_ev_free_expected;
|
|
static const void *cb_ev_free_device_ptr;
|
|
static void
|
|
cb_ev_free (acc_prof_info *prof_info, acc_event_info *event_info, acc_api_info *api_info)
|
|
{
|
|
assert (cb_ev_free_expected);
|
|
cb_ev_free_expected = false;
|
|
|
|
cb_ev_free_device_ptr = event_info->data_event.device_ptr;
|
|
}
|
|
|
|
|
|
/* Match the alignment processing that
|
|
'libgomp/target.c:gomp_map_vars_internal' is doing; simplified, not
|
|
considering special alignment requirements of certain data types. */
|
|
|
|
static size_t
|
|
aligned_size (size_t tgt_size)
|
|
{
|
|
size_t tgt_align = sizeof (void *);
|
|
return tgt_size + tgt_align - 1;
|
|
}
|
|
|
|
static const void *
|
|
aligned_address (const void *tgt_start)
|
|
{
|
|
size_t tgt_align = sizeof (void *);
|
|
return (void *) (((uintptr_t) tgt_start + tgt_align - 1) & ~(tgt_align - 1));
|
|
}
|
|
|
|
|
|
#define SIZE 1024
|
|
#define SUBSET 32
|
|
|
|
|
|
static void
|
|
f1 (void)
|
|
{
|
|
cb_ev_alloc_expected = false;
|
|
cb_ev_free_expected = false;
|
|
acc_prof_register (acc_ev_alloc, cb_ev_alloc, acc_reg);
|
|
acc_prof_register (acc_ev_free, cb_ev_free, acc_reg);
|
|
|
|
#if POINTERS
|
|
char* myblock = (char *) malloc (SIZE);
|
|
#else
|
|
char myblock[SIZE];
|
|
#endif
|
|
int i;
|
|
void *dst;
|
|
for (i = 0; i < SIZE; i++)
|
|
myblock[i] = i;
|
|
|
|
cb_ev_alloc_expected = true;
|
|
#if OPENACC_RUNTIME
|
|
dst = acc_copyin (myblock, SIZE);
|
|
#else
|
|
# if POINTERS
|
|
# pragma acc enter data copyin (myblock[0:SIZE])
|
|
# else
|
|
# pragma acc enter data copyin (myblock)
|
|
# endif
|
|
dst = acc_deviceptr (myblock);
|
|
#endif
|
|
assert (dst);
|
|
assert (!cb_ev_alloc_expected);
|
|
assert (cb_ev_alloc_bytes == aligned_size (SIZE));
|
|
assert (aligned_address (cb_ev_alloc_device_ptr) == dst);
|
|
for (i = 0; i < SIZE; i += SUBSET)
|
|
{
|
|
void *partdst = acc_deviceptr (&myblock[i]);
|
|
assert ((uintptr_t) partdst == (uintptr_t) dst + i);
|
|
assert (acc_hostptr (partdst) == &myblock[i]);
|
|
}
|
|
for (i = 0; i < SIZE; i += SUBSET)
|
|
{
|
|
void *partdst;
|
|
#if OPENACC_RUNTIME
|
|
partdst = acc_pcopyin (&myblock[i], SUBSET);
|
|
#else
|
|
# pragma acc enter data pcopyin (myblock[i:SUBSET])
|
|
partdst = acc_deviceptr (&myblock[i]);
|
|
#endif
|
|
assert ((uintptr_t) partdst == (uintptr_t) dst + i);
|
|
}
|
|
/* Dereference first half. */
|
|
for (i = 0; i < 512; i += SUBSET)
|
|
{
|
|
assert (acc_is_present (&myblock[i], SUBSET));
|
|
assert (acc_is_present (myblock, SIZE));
|
|
#if OPENACC_RUNTIME
|
|
acc_delete (&myblock[i], SUBSET);
|
|
#else
|
|
# pragma acc exit data delete (myblock[i:SUBSET])
|
|
#endif
|
|
assert (acc_is_present (&myblock[i], SUBSET));
|
|
assert (acc_is_present (myblock, SIZE));
|
|
}
|
|
/* Dereference all. */
|
|
#if OPENACC_RUNTIME
|
|
acc_delete (myblock, SIZE);
|
|
#else
|
|
# if POINTERS
|
|
# pragma acc exit data delete (myblock[0:SIZE])
|
|
# else
|
|
# pragma acc exit data delete (myblock)
|
|
# endif
|
|
#endif
|
|
/* Expect it's still present. */
|
|
assert (acc_is_present (myblock, SIZE));
|
|
/* Dereference second half. */
|
|
for (i = 512; i < SIZE; i += SUBSET)
|
|
{
|
|
bool last = i >= SIZE - SUBSET;
|
|
|
|
assert (acc_is_present (&myblock[i], SUBSET));
|
|
assert (acc_is_present (myblock, SIZE));
|
|
if (last)
|
|
cb_ev_free_expected = true;
|
|
#if OPENACC_RUNTIME
|
|
acc_delete (&myblock[i], SUBSET);
|
|
#else
|
|
# pragma acc exit data delete (myblock[i:SUBSET])
|
|
#endif
|
|
assert (!cb_ev_free_expected);
|
|
if (last)
|
|
assert (cb_ev_free_device_ptr == cb_ev_alloc_device_ptr);
|
|
assert (acc_is_present (&myblock[i], SUBSET) != last);
|
|
assert (acc_is_present (myblock, SIZE) != last);
|
|
}
|
|
/* Expect it's all gone now. */
|
|
for (i = 512; i < SIZE; i += SUBSET)
|
|
assert (!acc_is_present (&myblock[i], SUBSET));
|
|
assert (!acc_is_present (myblock, SIZE));
|
|
assert (!acc_is_present (myblock, 1));
|
|
|
|
#if POINTERS
|
|
free (myblock);
|
|
#endif
|
|
|
|
acc_prof_unregister (acc_ev_alloc, cb_ev_alloc, acc_reg);
|
|
acc_prof_unregister (acc_ev_free, cb_ev_free, acc_reg);
|
|
}
|
|
|
|
|
|
static void
|
|
f2 (void)
|
|
{
|
|
cb_ev_alloc_expected = false;
|
|
cb_ev_free_expected = false;
|
|
acc_prof_register (acc_ev_alloc, cb_ev_alloc, acc_reg);
|
|
acc_prof_register (acc_ev_free, cb_ev_free, acc_reg);
|
|
|
|
#if POINTERS
|
|
char *block1 = (char *) malloc (SIZE);
|
|
char *block2 = (char *) malloc (SIZE);
|
|
char *block3 = (char *) malloc (SIZE);
|
|
#else
|
|
char block1[SIZE];
|
|
char block2[SIZE];
|
|
char block3[SIZE];
|
|
#endif
|
|
int i;
|
|
for (i = 0; i < SIZE; i++)
|
|
block1[i] = block2[i] = block3[i] = i;
|
|
|
|
cb_ev_alloc_expected = true;
|
|
#if POINTERS
|
|
# pragma acc data copyin(block1[0:SIZE], block2[0:SIZE], block3[0:SIZE])
|
|
#else
|
|
# pragma acc data copyin(block1, block2, block3)
|
|
#endif
|
|
{
|
|
void *block1_d = acc_deviceptr (block1);
|
|
void *block2_d = acc_deviceptr (block2);
|
|
void *block3_d = acc_deviceptr (block3);
|
|
assert (!cb_ev_alloc_expected);
|
|
/* 'block1', 'block2', 'block3' get mapped in one device memory object, in
|
|
reverse order. */
|
|
assert (cb_ev_alloc_bytes == aligned_size (3 * SIZE));
|
|
assert ((void *) ((uintptr_t) aligned_address (cb_ev_alloc_device_ptr) + 2 * SIZE) == block1_d);
|
|
assert ((void *) ((uintptr_t) aligned_address (cb_ev_alloc_device_ptr) + 1 * SIZE) == block2_d);
|
|
assert ((void *) ((uintptr_t) aligned_address (cb_ev_alloc_device_ptr) + 0 * SIZE) == block3_d);
|
|
|
|
for (i = 0; i < SIZE; i += SUBSET)
|
|
{
|
|
void *block2_part_d;
|
|
#if OPENACC_RUNTIME
|
|
block2_part_d = acc_pcopyin (&block2[i], SUBSET);
|
|
#else
|
|
# pragma acc enter data pcopyin (block2[i:SUBSET])
|
|
block2_part_d = acc_deviceptr (&block2[i]);
|
|
#endif
|
|
assert ((uintptr_t) block2_part_d == (uintptr_t) block2_d + i);
|
|
}
|
|
}
|
|
/* The mappings have been removed, but the device memory object has not yet
|
|
been 'free'd. */
|
|
assert (!acc_is_present (block1, SIZE));
|
|
assert (acc_is_present (block2, SIZE));
|
|
assert (!acc_is_present (block3, SIZE));
|
|
for (i = 0; i < SIZE; i += SUBSET)
|
|
{
|
|
bool last = i >= SIZE - SUBSET;
|
|
|
|
assert (acc_is_present (block2, SIZE));
|
|
if (last)
|
|
cb_ev_free_expected = true;
|
|
#if OPENACC_RUNTIME
|
|
acc_delete (&block2[i], SUBSET);
|
|
#else
|
|
# pragma acc exit data delete (block2[i:SUBSET])
|
|
#endif
|
|
assert (!cb_ev_free_expected);
|
|
if (last)
|
|
assert (cb_ev_free_device_ptr == cb_ev_alloc_device_ptr);
|
|
}
|
|
assert (!acc_is_present (block1, SIZE));
|
|
assert (!acc_is_present (block2, SIZE));
|
|
assert (!acc_is_present (block3, SIZE));
|
|
|
|
#if POINTERS
|
|
free (block1);
|
|
free (block2);
|
|
free (block3);
|
|
#endif
|
|
|
|
acc_prof_unregister (acc_ev_alloc, cb_ev_alloc, acc_reg);
|
|
acc_prof_unregister (acc_ev_free, cb_ev_free, acc_reg);
|
|
}
|
|
|
|
|
|
static void
|
|
f3 ()
|
|
{
|
|
cb_ev_alloc_expected = false;
|
|
cb_ev_free_expected = false;
|
|
acc_prof_register (acc_ev_alloc, cb_ev_alloc, acc_reg);
|
|
acc_prof_register (acc_ev_free, cb_ev_free, acc_reg);
|
|
|
|
#if POINTERS
|
|
char *h = (char *) malloc (SIZE);
|
|
#else
|
|
char h[SIZE];
|
|
#endif
|
|
|
|
char *d1;
|
|
cb_ev_alloc_expected = true;
|
|
#if OPENACC_RUNTIME
|
|
d1 = (char *) acc_present_or_create (h, SIZE);
|
|
#else
|
|
# if POINTERS
|
|
# pragma acc enter data present_or_create (h[0:SIZE])
|
|
# else
|
|
# pragma acc enter data present_or_create (h)
|
|
# endif
|
|
d1 = (char *) acc_deviceptr (h);
|
|
#endif
|
|
assert (d1);
|
|
assert (!cb_ev_alloc_expected);
|
|
assert (cb_ev_alloc_bytes == aligned_size (SIZE));
|
|
assert (aligned_address (cb_ev_alloc_device_ptr) == d1);
|
|
assert (acc_is_present (h, SIZE));
|
|
assert (acc_is_present (&h[2], SIZE - 2));
|
|
|
|
char *d2;
|
|
#if OPENACC_RUNTIME
|
|
d2 = (char *) acc_present_or_create (&h[2], SIZE - 2);
|
|
#else
|
|
# pragma acc enter data present_or_create (h[2:SIZE - 2])
|
|
d2 = (char *) acc_deviceptr (&h[2]);
|
|
#endif
|
|
assert (d2);
|
|
assert (d1 == d2 - 2);
|
|
assert (acc_is_present (h, SIZE));
|
|
assert (acc_is_present (&h[2], SIZE - 2));
|
|
|
|
d2 = (char *) acc_deviceptr (&h[2]);
|
|
assert (d1 == d2 - 2);
|
|
|
|
#if OPENACC_RUNTIME
|
|
acc_delete (&h[2], SIZE - 2);
|
|
#else
|
|
# pragma acc exit data delete (h[2:SIZE - 2])
|
|
#endif
|
|
assert (acc_is_present (h, SIZE));
|
|
assert (acc_is_present (&h[2], SIZE - 2));
|
|
|
|
cb_ev_free_expected = true;
|
|
#if OPENACC_RUNTIME
|
|
acc_delete (h, SIZE);
|
|
#else
|
|
# if POINTERS
|
|
# pragma acc exit data delete (h[0:SIZE])
|
|
# else
|
|
# pragma acc exit data delete (h)
|
|
# endif
|
|
#endif
|
|
assert (!cb_ev_free_expected);
|
|
assert (cb_ev_free_device_ptr == cb_ev_alloc_device_ptr);
|
|
|
|
assert (!acc_is_present (h, SIZE));
|
|
assert (!acc_is_present (&h[2], SIZE - 2));
|
|
assert (!acc_is_present (h, 1));
|
|
|
|
# if POINTERS
|
|
free (h);
|
|
#endif
|
|
|
|
acc_prof_unregister (acc_ev_alloc, cb_ev_alloc, acc_reg);
|
|
acc_prof_unregister (acc_ev_free, cb_ev_free, acc_reg);
|
|
}
|
|
|
|
|
|
/* Based on what used to be 'libgomp.oacc-c-c++-common/lib-22.c'. */
|
|
|
|
static void
|
|
f_lib_22 (void)
|
|
{
|
|
cb_ev_alloc_expected = false;
|
|
cb_ev_free_expected = false;
|
|
acc_prof_register (acc_ev_alloc, cb_ev_alloc, acc_reg);
|
|
acc_prof_register (acc_ev_free, cb_ev_free, acc_reg);
|
|
|
|
const int c0 = 0;
|
|
const int c1 = 1;
|
|
|
|
#if POINTERS
|
|
char *h = (char *) malloc (SIZE);
|
|
#else
|
|
char h[SIZE];
|
|
#endif
|
|
|
|
memset (h, c0, SIZE);
|
|
void *d;
|
|
cb_ev_alloc_expected = true;
|
|
#if OPENACC_RUNTIME
|
|
d = acc_copyin (h, SIZE);
|
|
#else
|
|
# if POINTERS
|
|
# pragma acc enter data copyin (h[0:SIZE])
|
|
# else
|
|
# pragma acc enter data copyin (h)
|
|
# endif
|
|
d = acc_deviceptr (h);
|
|
#endif
|
|
assert (d);
|
|
assert (!cb_ev_alloc_expected);
|
|
assert (cb_ev_alloc_bytes == aligned_size (SIZE));
|
|
assert (aligned_address (cb_ev_alloc_device_ptr) == d);
|
|
/* Overwrite the local memory. */
|
|
memset (h, c1, SIZE);
|
|
/* Now 'copyout' not the whole but only a "subset" subarray, missing one
|
|
SUBSET at the beginning, and half a SUBSET at the end... */
|
|
cb_ev_free_expected = true;
|
|
#if OPENACC_RUNTIME
|
|
acc_copyout (h + SUBSET, SIZE - SUBSET - SUBSET / 2);
|
|
#else
|
|
# pragma acc exit data copyout (h[SUBSET:SIZE - SUBSET - SUBSET / 2])
|
|
#endif
|
|
/* ..., yet, expect the device memory object to be 'free'd... */
|
|
assert (!cb_ev_free_expected);
|
|
assert (cb_ev_free_device_ptr == cb_ev_alloc_device_ptr);
|
|
/* ..., and the mapping to be removed... */
|
|
assert (!acc_is_present (h, SIZE));
|
|
assert (!acc_is_present (&h[SUBSET], SIZE - SUBSET - SUBSET / 2));
|
|
assert (!acc_is_present (h, 1));
|
|
/* ..., but the 'copyout'ed device memory to correspond to just the "subset"
|
|
subarray. */
|
|
for (size_t i = 0; i < SIZE; ++i)
|
|
{
|
|
if (i < SUBSET)
|
|
assert (h[i] == c1);
|
|
else if (i < SIZE - SUBSET / 2)
|
|
assert (h[i] == c0);
|
|
else if (i < SIZE)
|
|
assert (h[i] == c1);
|
|
}
|
|
|
|
#if POINTERS
|
|
free (h);
|
|
#endif
|
|
|
|
acc_prof_unregister (acc_ev_alloc, cb_ev_alloc, acc_reg);
|
|
acc_prof_unregister (acc_ev_free, cb_ev_free, acc_reg);
|
|
}
|
|
|
|
|
|
/* Based on what used to be 'libgomp.oacc-c-c++-common/lib-30.c'. */
|
|
|
|
static void
|
|
f_lib_30 (void)
|
|
{
|
|
cb_ev_alloc_expected = false;
|
|
cb_ev_free_expected = false;
|
|
acc_prof_register (acc_ev_alloc, cb_ev_alloc, acc_reg);
|
|
acc_prof_register (acc_ev_free, cb_ev_free, acc_reg);
|
|
|
|
#if POINTERS
|
|
char *h = (char *) malloc (SIZE);
|
|
#else
|
|
char h[SIZE];
|
|
#endif
|
|
memset (h, 0, SIZE);
|
|
|
|
void *d;
|
|
cb_ev_alloc_expected = true;
|
|
#if OPENACC_RUNTIME
|
|
d = acc_create (h, SIZE);
|
|
#else
|
|
# if POINTERS
|
|
# pragma acc enter data create (h[0:SIZE])
|
|
# else
|
|
# pragma acc enter data create (h)
|
|
# endif
|
|
d = acc_deviceptr (h);
|
|
#endif
|
|
assert (d);
|
|
assert (!cb_ev_alloc_expected);
|
|
assert (cb_ev_alloc_bytes == aligned_size (SIZE));
|
|
assert (aligned_address (cb_ev_alloc_device_ptr) == d);
|
|
|
|
/* We 'delete' not the whole but only a "subset" subarray... */
|
|
cb_ev_free_expected = true;
|
|
#if OPENACC_RUNTIME
|
|
acc_delete (h, SIZE - SUBSET);
|
|
#else
|
|
# pragma acc exit data delete (h[0:SIZE - SUBSET])
|
|
#endif
|
|
/* ..., yet, expect the device memory object to be 'free'd... */
|
|
assert (!cb_ev_free_expected);
|
|
assert (cb_ev_free_device_ptr == cb_ev_alloc_device_ptr);
|
|
/* ..., and the mapping to be removed. */
|
|
assert (!acc_is_present (h, SIZE));
|
|
assert (!acc_is_present (h, SIZE - SUBSET));
|
|
assert (!acc_is_present (h, 1));
|
|
|
|
#if POINTERS
|
|
free (h);
|
|
#endif
|
|
|
|
acc_prof_unregister (acc_ev_alloc, cb_ev_alloc, acc_reg);
|
|
acc_prof_unregister (acc_ev_free, cb_ev_free, acc_reg);
|
|
}
|
|
|
|
|
|
int
|
|
main ()
|
|
{
|
|
f1 ();
|
|
f2 ();
|
|
f3 ();
|
|
f_lib_22 ();
|
|
f_lib_30 ();
|
|
|
|
return 0;
|
|
}
|