1 /* Test "subset" subarray mappings
2 { dg-additional-options "-DOPENACC_RUNTIME" } using OpenACC Runtime Library routines,
3 { dg-additional-options "-DPOINTERS" } using pointers. */
5 /* { dg-skip-if "" { *-*-* } { "-DACC_MEM_SHARED=1" } } */
8 #elif OPENACC_DIRECTIVES
29 static bool cb_ev_alloc_expected
;
30 static size_t cb_ev_alloc_bytes
;
31 static const void *cb_ev_alloc_device_ptr
;
33 cb_ev_alloc (acc_prof_info
*prof_info
, acc_event_info
*event_info
, acc_api_info
*api_info
)
35 assert (cb_ev_alloc_expected
);
36 cb_ev_alloc_expected
= false;
38 cb_ev_alloc_bytes
= event_info
->data_event
.bytes
;
39 cb_ev_alloc_device_ptr
= event_info
->data_event
.device_ptr
;
42 static bool cb_ev_free_expected
;
43 static const void *cb_ev_free_device_ptr
;
45 cb_ev_free (acc_prof_info
*prof_info
, acc_event_info
*event_info
, acc_api_info
*api_info
)
47 assert (cb_ev_free_expected
);
48 cb_ev_free_expected
= false;
50 cb_ev_free_device_ptr
= event_info
->data_event
.device_ptr
;
54 /* Match the alignment processing that
55 'libgomp/target.c:gomp_map_vars_internal' is doing; simplified, not
56 considering special alignment requirements of certain data types. */
59 aligned_size (size_t tgt_size
)
61 size_t tgt_align
= sizeof (void *);
62 return tgt_size
+ tgt_align
- 1;
66 aligned_address (const void *tgt_start
)
68 size_t tgt_align
= sizeof (void *);
69 return (void *) (((uintptr_t) tgt_start
+ tgt_align
- 1) & ~(tgt_align
- 1));
80 cb_ev_alloc_expected
= false;
81 cb_ev_free_expected
= false;
82 acc_prof_register (acc_ev_alloc
, cb_ev_alloc
, acc_reg
);
83 acc_prof_register (acc_ev_free
, cb_ev_free
, acc_reg
);
86 char* myblock
= (char *) malloc (SIZE
);
92 for (i
= 0; i
< SIZE
; i
++)
95 cb_ev_alloc_expected
= true;
97 dst
= acc_copyin (myblock
, SIZE
);
100 # pragma acc enter data copyin (myblock[0:SIZE])
102 # pragma acc enter data copyin (myblock)
104 dst
= acc_deviceptr (myblock
);
107 assert (!cb_ev_alloc_expected
);
108 assert (cb_ev_alloc_bytes
== aligned_size (SIZE
));
109 assert (aligned_address (cb_ev_alloc_device_ptr
) == dst
);
110 for (i
= 0; i
< SIZE
; i
+= SUBSET
)
112 void *partdst
= acc_deviceptr (&myblock
[i
]);
113 assert ((uintptr_t) partdst
== (uintptr_t) dst
+ i
);
114 assert (acc_hostptr (partdst
) == &myblock
[i
]);
116 for (i
= 0; i
< SIZE
; i
+= SUBSET
)
120 partdst
= acc_pcopyin (&myblock
[i
], SUBSET
);
122 # pragma acc enter data pcopyin (myblock[i:SUBSET])
123 partdst
= acc_deviceptr (&myblock
[i
]);
125 assert ((uintptr_t) partdst
== (uintptr_t) dst
+ i
);
127 /* Dereference first half. */
128 for (i
= 0; i
< 512; i
+= SUBSET
)
130 assert (acc_is_present (&myblock
[i
], SUBSET
));
131 assert (acc_is_present (myblock
, SIZE
));
133 acc_delete (&myblock
[i
], SUBSET
);
135 # pragma acc exit data delete (myblock[i:SUBSET])
137 assert (acc_is_present (&myblock
[i
], SUBSET
));
138 assert (acc_is_present (myblock
, SIZE
));
140 /* Dereference all. */
142 acc_delete (myblock
, SIZE
);
145 # pragma acc exit data delete (myblock[0:SIZE])
147 # pragma acc exit data delete (myblock)
150 /* Expect it's still present. */
151 assert (acc_is_present (myblock
, SIZE
));
152 /* Dereference second half. */
153 for (i
= 512; i
< SIZE
; i
+= SUBSET
)
155 bool last
= i
>= SIZE
- SUBSET
;
157 assert (acc_is_present (&myblock
[i
], SUBSET
));
158 assert (acc_is_present (myblock
, SIZE
));
160 cb_ev_free_expected
= true;
162 acc_delete (&myblock
[i
], SUBSET
);
164 # pragma acc exit data delete (myblock[i:SUBSET])
166 assert (!cb_ev_free_expected
);
168 assert (cb_ev_free_device_ptr
== cb_ev_alloc_device_ptr
);
169 assert (acc_is_present (&myblock
[i
], SUBSET
) != last
);
170 assert (acc_is_present (myblock
, SIZE
) != last
);
172 /* Expect it's all gone now. */
173 for (i
= 512; i
< SIZE
; i
+= SUBSET
)
174 assert (!acc_is_present (&myblock
[i
], SUBSET
));
175 assert (!acc_is_present (myblock
, SIZE
));
176 assert (!acc_is_present (myblock
, 1));
182 acc_prof_unregister (acc_ev_alloc
, cb_ev_alloc
, acc_reg
);
183 acc_prof_unregister (acc_ev_free
, cb_ev_free
, acc_reg
);
190 cb_ev_alloc_expected
= false;
191 cb_ev_free_expected
= false;
192 acc_prof_register (acc_ev_alloc
, cb_ev_alloc
, acc_reg
);
193 acc_prof_register (acc_ev_free
, cb_ev_free
, acc_reg
);
196 char *block1
= (char *) malloc (SIZE
);
197 char *block2
= (char *) malloc (SIZE
);
198 char *block3
= (char *) malloc (SIZE
);
205 for (i
= 0; i
< SIZE
; i
++)
206 block1
[i
] = block2
[i
] = block3
[i
] = i
;
208 cb_ev_alloc_expected
= true;
210 # pragma acc data copyin(block1[0:SIZE], block2[0:SIZE], block3[0:SIZE])
212 # pragma acc data copyin(block1, block2, block3)
215 void *block1_d
= acc_deviceptr (block1
);
216 void *block2_d
= acc_deviceptr (block2
);
217 void *block3_d
= acc_deviceptr (block3
);
218 assert (!cb_ev_alloc_expected
);
219 /* 'block1', 'block2', 'block3' get mapped in one device memory object, in
221 assert (cb_ev_alloc_bytes
== aligned_size (3 * SIZE
));
222 assert ((void *) ((uintptr_t) aligned_address (cb_ev_alloc_device_ptr
) + 2 * SIZE
) == block1_d
);
223 assert ((void *) ((uintptr_t) aligned_address (cb_ev_alloc_device_ptr
) + 1 * SIZE
) == block2_d
);
224 assert ((void *) ((uintptr_t) aligned_address (cb_ev_alloc_device_ptr
) + 0 * SIZE
) == block3_d
);
226 for (i
= 0; i
< SIZE
; i
+= SUBSET
)
230 block2_part_d
= acc_pcopyin (&block2
[i
], SUBSET
);
232 # pragma acc enter data pcopyin (block2[i:SUBSET])
233 block2_part_d
= acc_deviceptr (&block2
[i
]);
235 assert ((uintptr_t) block2_part_d
== (uintptr_t) block2_d
+ i
);
238 /* The mappings have been removed, but the device memory object has not yet
240 assert (!acc_is_present (block1
, SIZE
));
241 assert (acc_is_present (block2
, SIZE
));
242 assert (!acc_is_present (block3
, SIZE
));
243 for (i
= 0; i
< SIZE
; i
+= SUBSET
)
245 bool last
= i
>= SIZE
- SUBSET
;
247 assert (acc_is_present (block2
, SIZE
));
249 cb_ev_free_expected
= true;
251 acc_delete (&block2
[i
], SUBSET
);
253 # pragma acc exit data delete (block2[i:SUBSET])
255 assert (!cb_ev_free_expected
);
257 assert (cb_ev_free_device_ptr
== cb_ev_alloc_device_ptr
);
259 assert (!acc_is_present (block1
, SIZE
));
260 assert (!acc_is_present (block2
, SIZE
));
261 assert (!acc_is_present (block3
, SIZE
));
269 acc_prof_unregister (acc_ev_alloc
, cb_ev_alloc
, acc_reg
);
270 acc_prof_unregister (acc_ev_free
, cb_ev_free
, acc_reg
);
277 cb_ev_alloc_expected
= false;
278 cb_ev_free_expected
= false;
279 acc_prof_register (acc_ev_alloc
, cb_ev_alloc
, acc_reg
);
280 acc_prof_register (acc_ev_free
, cb_ev_free
, acc_reg
);
283 char *h
= (char *) malloc (SIZE
);
289 cb_ev_alloc_expected
= true;
291 d1
= (char *) acc_present_or_create (h
, SIZE
);
294 # pragma acc enter data present_or_create (h[0:SIZE])
296 # pragma acc enter data present_or_create (h)
298 d1
= (char *) acc_deviceptr (h
);
301 assert (!cb_ev_alloc_expected
);
302 assert (cb_ev_alloc_bytes
== aligned_size (SIZE
));
303 assert (aligned_address (cb_ev_alloc_device_ptr
) == d1
);
304 assert (acc_is_present (h
, SIZE
));
305 assert (acc_is_present (&h
[2], SIZE
- 2));
309 d2
= (char *) acc_present_or_create (&h
[2], SIZE
- 2);
311 # pragma acc enter data present_or_create (h[2:SIZE - 2])
312 d2
= (char *) acc_deviceptr (&h
[2]);
315 assert (d1
== d2
- 2);
316 assert (acc_is_present (h
, SIZE
));
317 assert (acc_is_present (&h
[2], SIZE
- 2));
319 d2
= (char *) acc_deviceptr (&h
[2]);
320 assert (d1
== d2
- 2);
323 acc_delete (&h
[2], SIZE
- 2);
325 # pragma acc exit data delete (h[2:SIZE - 2])
327 assert (acc_is_present (h
, SIZE
));
328 assert (acc_is_present (&h
[2], SIZE
- 2));
330 cb_ev_free_expected
= true;
332 acc_delete (h
, SIZE
);
335 # pragma acc exit data delete (h[0:SIZE])
337 # pragma acc exit data delete (h)
340 assert (!cb_ev_free_expected
);
341 assert (cb_ev_free_device_ptr
== cb_ev_alloc_device_ptr
);
343 assert (!acc_is_present (h
, SIZE
));
344 assert (!acc_is_present (&h
[2], SIZE
- 2));
345 assert (!acc_is_present (h
, 1));
351 acc_prof_unregister (acc_ev_alloc
, cb_ev_alloc
, acc_reg
);
352 acc_prof_unregister (acc_ev_free
, cb_ev_free
, acc_reg
);
356 /* Based on what used to be 'libgomp.oacc-c-c++-common/lib-22.c'. */
361 cb_ev_alloc_expected
= false;
362 cb_ev_free_expected
= false;
363 acc_prof_register (acc_ev_alloc
, cb_ev_alloc
, acc_reg
);
364 acc_prof_register (acc_ev_free
, cb_ev_free
, acc_reg
);
370 char *h
= (char *) malloc (SIZE
);
375 memset (h
, c0
, SIZE
);
377 cb_ev_alloc_expected
= true;
379 d
= acc_copyin (h
, SIZE
);
382 # pragma acc enter data copyin (h[0:SIZE])
384 # pragma acc enter data copyin (h)
386 d
= acc_deviceptr (h
);
389 assert (!cb_ev_alloc_expected
);
390 assert (cb_ev_alloc_bytes
== aligned_size (SIZE
));
391 assert (aligned_address (cb_ev_alloc_device_ptr
) == d
);
392 /* Overwrite the local memory. */
393 memset (h
, c1
, SIZE
);
394 /* Now 'copyout' not the whole but only a "subset" subarray, missing one
395 SUBSET at the beginning, and half a SUBSET at the end... */
396 cb_ev_free_expected
= true;
398 acc_copyout (h
+ SUBSET
, SIZE
- SUBSET
- SUBSET
/ 2);
400 # pragma acc exit data copyout (h[SUBSET:SIZE - SUBSET - SUBSET / 2])
402 /* ..., yet, expect the device memory object to be 'free'd... */
403 assert (!cb_ev_free_expected
);
404 assert (cb_ev_free_device_ptr
== cb_ev_alloc_device_ptr
);
405 /* ..., and the mapping to be removed... */
406 assert (!acc_is_present (h
, SIZE
));
407 assert (!acc_is_present (&h
[SUBSET
], SIZE
- SUBSET
- SUBSET
/ 2));
408 assert (!acc_is_present (h
, 1));
409 /* ..., but the 'copyout'ed device memory to correspond to just the "subset"
411 for (size_t i
= 0; i
< SIZE
; ++i
)
415 else if (i
< SIZE
- SUBSET
/ 2)
425 acc_prof_unregister (acc_ev_alloc
, cb_ev_alloc
, acc_reg
);
426 acc_prof_unregister (acc_ev_free
, cb_ev_free
, acc_reg
);
430 /* Based on what used to be 'libgomp.oacc-c-c++-common/lib-30.c'. */
435 cb_ev_alloc_expected
= false;
436 cb_ev_free_expected
= false;
437 acc_prof_register (acc_ev_alloc
, cb_ev_alloc
, acc_reg
);
438 acc_prof_register (acc_ev_free
, cb_ev_free
, acc_reg
);
441 char *h
= (char *) malloc (SIZE
);
448 cb_ev_alloc_expected
= true;
450 d
= acc_create (h
, SIZE
);
453 # pragma acc enter data create (h[0:SIZE])
455 # pragma acc enter data create (h)
457 d
= acc_deviceptr (h
);
460 assert (!cb_ev_alloc_expected
);
461 assert (cb_ev_alloc_bytes
== aligned_size (SIZE
));
462 assert (aligned_address (cb_ev_alloc_device_ptr
) == d
);
464 /* We 'delete' not the whole but only a "subset" subarray... */
465 cb_ev_free_expected
= true;
467 acc_delete (h
, SIZE
- SUBSET
);
469 # pragma acc exit data delete (h[0:SIZE - SUBSET])
471 /* ..., yet, expect the device memory object to be 'free'd... */
472 assert (!cb_ev_free_expected
);
473 assert (cb_ev_free_device_ptr
== cb_ev_alloc_device_ptr
);
474 /* ..., and the mapping to be removed. */
475 assert (!acc_is_present (h
, SIZE
));
476 assert (!acc_is_present (h
, SIZE
- SUBSET
));
477 assert (!acc_is_present (h
, 1));
483 acc_prof_unregister (acc_ev_alloc
, cb_ev_alloc
, acc_reg
);
484 acc_prof_unregister (acc_ev_free
, cb_ev_free
, acc_reg
);