[PR92511] More testing for OpenACC "present" subarrays

In particular, "subset subarrays".

	libgomp/
	PR libgomp/92511
	* testsuite/libgomp.oacc-c-c++-common/copyin-devptr-1.c: Remove
	this file...
	* testsuite/libgomp.oacc-c-c++-common/copyin-devptr-2.c: ..., and
	this file...
	* testsuite/libgomp.oacc-c-c++-common/lib-22.c: ..., and this
	file...
	* testsuite/libgomp.oacc-c-c++-common/lib-30.c: ..., and this
	file...
	* testsuite/libgomp.oacc-c-c++-common/subset-subarray-mappings-1-r-p.c:
	... with their content moved into, and extended in this new file.
	* testsuite/libgomp.oacc-c-c++-common/subset-subarray-mappings-1-d-a.c:
	New file.
	* testsuite/libgomp.oacc-c-c++-common/subset-subarray-mappings-1-d-p.c:
	Likewise.
	* testsuite/libgomp.oacc-c-c++-common/subset-subarray-mappings-1-r-a.c:
	Likewise.
	* testsuite/libgomp.oacc-c-c++-common/subset-subarray-mappings-2.c:
	Likewise.

From-SVN: r279122
This commit is contained in:
Thomas Schwinge 2019-12-09 12:40:36 +01:00 committed by Thomas Schwinge
parent 6effebe10b
commit 41f36f22f3
10 changed files with 670 additions and 126 deletions

View File

@ -1,5 +1,25 @@
2019-12-09 Thomas Schwinge <thomas@codesourcery.com>
PR libgomp/92511
* testsuite/libgomp.oacc-c-c++-common/copyin-devptr-1.c: Remove
this file...
* testsuite/libgomp.oacc-c-c++-common/copyin-devptr-2.c: ..., and
this file...
* testsuite/libgomp.oacc-c-c++-common/lib-22.c: ..., and this
file...
* testsuite/libgomp.oacc-c-c++-common/lib-30.c: ..., and this
file...
* testsuite/libgomp.oacc-c-c++-common/subset-subarray-mappings-1-r-p.c:
... with their content moved into, and extended in this new file.
* testsuite/libgomp.oacc-c-c++-common/subset-subarray-mappings-1-d-a.c:
New file.
* testsuite/libgomp.oacc-c-c++-common/subset-subarray-mappings-1-d-p.c:
Likewise.
* testsuite/libgomp.oacc-c-c++-common/subset-subarray-mappings-1-r-a.c:
Likewise.
* testsuite/libgomp.oacc-c-c++-common/subset-subarray-mappings-2.c:
Likewise.
* testsuite/libgomp.oacc-c-c++-common/map-data-1.c: New file.
PR libgomp/92854

View File

@ -1,28 +0,0 @@
/* { dg-skip-if "" { *-*-* } { "-DACC_MEM_SHARED=1" } } */
#include <openacc.h>
#include <stdlib.h>
#include <assert.h>
#include <stdint.h>
int main (int argc, char* argv[])
{
char *myblock = (char *) malloc (1024);
int i;
void *dst;
for (i = 0; i < 1024; i++)
myblock[i] = i;
dst = acc_copyin (myblock, 1024);
for (i = 0; i < 1024; i += 256)
{
void *partdst = acc_pcopyin (&myblock[i], 256);
assert ((uintptr_t) partdst == (uintptr_t) dst + i);
}
for (i = 0; i < 1024; i += 256)
acc_delete (&myblock[i], 256);
assert (acc_is_present (myblock, 1024));
acc_delete (myblock, 1024);
assert (!acc_is_present (myblock, 1024));
free (myblock);
return 0;
}

View File

@ -1,35 +0,0 @@
/* { dg-skip-if "" { *-*-* } { "-DACC_MEM_SHARED=1" } } */
#include <openacc.h>
#include <stdlib.h>
#include <assert.h>
#include <stdint.h>
int main (int argc, char* argv[])
{
char *block1 = (char *) malloc (1024);
char *block2 = (char *) malloc (1024);
char *block3 = (char *) malloc (1024);
int i;
void *dst;
for (i = 0; i < 1024; i++)
block1[i] = block2[i] = block3[i] = i;
#pragma acc data copyin(block1[0:1024]) copyin(block2[0:1024]) \
copyin(block3[0:1024])
{
dst = acc_deviceptr (block2);
for (i = 0; i < 1024; i += 256)
{
void *partdst = acc_pcopyin (&block2[i], 256);
assert ((uintptr_t) partdst == (uintptr_t) dst + i);
}
}
assert (acc_is_present (block2, 1024));
for (i = 0; i < 1024; i += 256)
acc_delete (&block2[i], 256);
assert (!acc_is_present (block2, 1024));
free (block1);
free (block2);
free (block3);
return 0;
}

View File

@ -1,33 +0,0 @@
/* Exercise acc_copyin and acc_copyout on nvidia targets. */
/* { dg-do run { target openacc_nvidia_accel_selected } } */
#include <stdio.h>
#include <stdlib.h>
#include <openacc.h>
int
main (int argc, char **argv)
{
const int N = 256;
int i;
unsigned char *h;
h = (unsigned char *) malloc (N);
for (i = 0; i < N; i++)
{
h[i] = i;
}
(void) acc_copyin (h, N);
fprintf (stderr, "CheCKpOInT\n");
acc_copyout (h + 1, N - 1);
free (h);
return 0;
}
/* { dg-output "CheCKpOInT(\n|\r\n|\r).*" } */

View File

@ -1,30 +0,0 @@
/* Exercise an invalid partial acc_delete on nvidia targets. */
/* { dg-do run { target openacc_nvidia_accel_selected } } */
#include <stdio.h>
#include <stdlib.h>
#include <openacc.h>
int
main (int argc, char **argv)
{
const int N = 256;
unsigned char *h;
void *d;
h = (unsigned char *) malloc (N);
d = acc_create (h, N);
if (!d)
abort ();
fprintf (stderr, "CheCKpOInT\n");
acc_delete (h, N - 2);
free (h);
return 0;
}
/* { dg-output "CheCKpOInT(\n|\r\n|\r).*" } */

View File

@ -0,0 +1,7 @@
/* Test "subset" subarray mappings
{ dg-additional-options "-DOPENACC_DIRECTIVES" } using OpenACC directives,
{ dg-additional-options "-DARRAYS" } using arrays. */
/* { dg-skip-if "" { *-*-* } { "-DACC_MEM_SHARED=1" } } */
#include "subset-subarray-mappings-1-r-p.c"

View File

@ -0,0 +1,7 @@
/* Test "subset" subarray mappings
{ dg-additional-options "-DOPENACC_DIRECTIVES" } using OpenACC directives,
{ dg-additional-options "-DPOINTERS" } using pointers. */
/* { dg-skip-if "" { *-*-* } { "-DACC_MEM_SHARED=1" } } */
#include "subset-subarray-mappings-1-r-p.c"

View File

@ -0,0 +1,7 @@
/* Test "subset" subarray mappings
{ dg-additional-options "-DOPENACC_RUNTIME" } using OpenACC Runtime Library routines,
{ dg-additional-options "-DARRAYS" } using arrays. */
/* { dg-skip-if "" { *-*-* } { "-DACC_MEM_SHARED=1" } } */
#include "subset-subarray-mappings-1-r-p.c"

View File

@ -0,0 +1,514 @@
/* 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 0 //TODO PR92848
if (last)
cb_ev_free_expected = true;
#endif
#if OPENACC_RUNTIME
acc_delete (&myblock[i], SUBSET);
#else
# pragma acc exit data delete (myblock[i:SUBSET])
#endif
#if 0 //TODO PR92848
assert (!cb_ev_free_expected);
if (last)
assert (cb_ev_free_device_ptr == cb_ev_alloc_device_ptr);
#endif
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));
#if 0 //TODO PR92848
cb_ev_free_expected = true;
#endif
#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
#if 0 //TODO PR92848
assert (!cb_ev_free_expected);
assert (cb_ev_free_device_ptr == cb_ev_alloc_device_ptr);
#endif
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... */
#if 0 //TODO PR92848
cb_ev_free_expected = true;
#endif
#if OPENACC_RUNTIME
acc_copyout (h + SUBSET, SIZE - SUBSET - SUBSET / 2);
#else
# pragma acc exit data copyout (h[SUBSET:SIZE - SUBSET - SUBSET / 2])
#endif
#if 0 //TODO PR92848
/* ..., 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);
#endif
/* ..., 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... */
#if 0 //TODO PR92848
cb_ev_free_expected = true;
#endif
#if OPENACC_RUNTIME
acc_delete (h, SIZE - SUBSET);
#else
# pragma acc exit data delete (h[0:SIZE - SUBSET])
#endif
#if 0 //TODO PR92848
/* ..., 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);
#endif
/* ..., 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;
}

View File

@ -0,0 +1,115 @@
/* Test "subset" subarray mappings. */
/* { dg-skip-if "" { *-*-* } { "-DACC_MEM_SHARED=1" } } */
#include <openacc.h>
#include <acc_prof.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <assert.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
int
main ()
{
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);
char *block1 = (char *) malloc (SIZE);
char *block2 = (char *) malloc (SIZE);
char *block3 = (char *) malloc (SIZE);
cb_ev_alloc_expected = true;
#pragma acc data create (block1[0:SIZE], block2[0:SIZE], block3[0:SIZE])
{
void *s_block1_d = acc_deviceptr (&block1[1]);
void *s_block2_d = acc_deviceptr (&block2[20]);
void *s_block3_d = acc_deviceptr (&block3[300]);
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 + 1) == s_block1_d);
assert ((void *) ((uintptr_t) aligned_address (cb_ev_alloc_device_ptr) + 1 * SIZE + 20) == s_block2_d);
assert ((void *) ((uintptr_t) aligned_address (cb_ev_alloc_device_ptr) + 0 * SIZE + 300) == s_block3_d);
void *s_block1_p_d = acc_pcopyin (&block1[1], SIZE - 3);
void *s_block2_p_d = acc_pcopyin (&block2[20], SIZE - 33);
void *s_block3_p_d = acc_pcopyin (&block3[300], SIZE - 333);
assert (s_block1_p_d == s_block1_d);
assert (s_block2_p_d == s_block2_d);
assert (s_block3_p_d == s_block3_d);
acc_delete (block1, SIZE);
acc_delete (block2, SIZE);
acc_delete (block3, SIZE);
assert (acc_is_present (block1, SIZE));
assert (acc_is_present (block2, SIZE));
assert (acc_is_present (block3, SIZE));
cb_ev_free_expected = true;
}
assert (!cb_ev_free_expected);
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));
free (block1);
free (block2);
free (block3);
acc_prof_unregister (acc_ev_alloc, cb_ev_alloc, acc_reg);
acc_prof_unregister (acc_ev_free, cb_ev_free, acc_reg);
return 0;
}