Adjust formatting of acc_get_property tests
[gcc.git] / libgomp / testsuite / libgomp.oacc-c-c++-common / subset-subarray-mappings-1-r-p.c
1 /* Test "subset" subarray mappings
2 { dg-additional-options "-DOPENACC_RUNTIME" } using OpenACC Runtime Library routines,
3 { dg-additional-options "-DPOINTERS" } using pointers. */
4
5 /* { dg-skip-if "" { *-*-* } { "-DACC_MEM_SHARED=1" } } */
6
7 #if OPENACC_RUNTIME
8 #elif OPENACC_DIRECTIVES
9 #else
10 # error
11 #endif
12
13 #if POINTERS
14 #elif ARRAYS
15 #else
16 # error
17 #endif
18
19
20 #include <openacc.h>
21 #include <acc_prof.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <assert.h>
25 #include <stdint.h>
26 #include <stdbool.h>
27
28
29 static bool cb_ev_alloc_expected;
30 static size_t cb_ev_alloc_bytes;
31 static const void *cb_ev_alloc_device_ptr;
32 static void
33 cb_ev_alloc (acc_prof_info *prof_info, acc_event_info *event_info, acc_api_info *api_info)
34 {
35 assert (cb_ev_alloc_expected);
36 cb_ev_alloc_expected = false;
37
38 cb_ev_alloc_bytes = event_info->data_event.bytes;
39 cb_ev_alloc_device_ptr = event_info->data_event.device_ptr;
40 }
41
42 static bool cb_ev_free_expected;
43 static const void *cb_ev_free_device_ptr;
44 static void
45 cb_ev_free (acc_prof_info *prof_info, acc_event_info *event_info, acc_api_info *api_info)
46 {
47 assert (cb_ev_free_expected);
48 cb_ev_free_expected = false;
49
50 cb_ev_free_device_ptr = event_info->data_event.device_ptr;
51 }
52
53
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. */
57
58 static size_t
59 aligned_size (size_t tgt_size)
60 {
61 size_t tgt_align = sizeof (void *);
62 return tgt_size + tgt_align - 1;
63 }
64
65 static const void *
66 aligned_address (const void *tgt_start)
67 {
68 size_t tgt_align = sizeof (void *);
69 return (void *) (((uintptr_t) tgt_start + tgt_align - 1) & ~(tgt_align - 1));
70 }
71
72
73 #define SIZE 1024
74 #define SUBSET 32
75
76
77 static void
78 f1 (void)
79 {
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);
84
85 #if POINTERS
86 char* myblock = (char *) malloc (SIZE);
87 #else
88 char myblock[SIZE];
89 #endif
90 int i;
91 void *dst;
92 for (i = 0; i < SIZE; i++)
93 myblock[i] = i;
94
95 cb_ev_alloc_expected = true;
96 #if OPENACC_RUNTIME
97 dst = acc_copyin (myblock, SIZE);
98 #else
99 # if POINTERS
100 # pragma acc enter data copyin (myblock[0:SIZE])
101 # else
102 # pragma acc enter data copyin (myblock)
103 # endif
104 dst = acc_deviceptr (myblock);
105 #endif
106 assert (dst);
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)
111 {
112 void *partdst = acc_deviceptr (&myblock[i]);
113 assert ((uintptr_t) partdst == (uintptr_t) dst + i);
114 assert (acc_hostptr (partdst) == &myblock[i]);
115 }
116 for (i = 0; i < SIZE; i += SUBSET)
117 {
118 void *partdst;
119 #if OPENACC_RUNTIME
120 partdst = acc_pcopyin (&myblock[i], SUBSET);
121 #else
122 # pragma acc enter data pcopyin (myblock[i:SUBSET])
123 partdst = acc_deviceptr (&myblock[i]);
124 #endif
125 assert ((uintptr_t) partdst == (uintptr_t) dst + i);
126 }
127 /* Dereference first half. */
128 for (i = 0; i < 512; i += SUBSET)
129 {
130 assert (acc_is_present (&myblock[i], SUBSET));
131 assert (acc_is_present (myblock, SIZE));
132 #if OPENACC_RUNTIME
133 acc_delete (&myblock[i], SUBSET);
134 #else
135 # pragma acc exit data delete (myblock[i:SUBSET])
136 #endif
137 assert (acc_is_present (&myblock[i], SUBSET));
138 assert (acc_is_present (myblock, SIZE));
139 }
140 /* Dereference all. */
141 #if OPENACC_RUNTIME
142 acc_delete (myblock, SIZE);
143 #else
144 # if POINTERS
145 # pragma acc exit data delete (myblock[0:SIZE])
146 # else
147 # pragma acc exit data delete (myblock)
148 # endif
149 #endif
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)
154 {
155 bool last = i >= SIZE - SUBSET;
156
157 assert (acc_is_present (&myblock[i], SUBSET));
158 assert (acc_is_present (myblock, SIZE));
159 if (last)
160 cb_ev_free_expected = true;
161 #if OPENACC_RUNTIME
162 acc_delete (&myblock[i], SUBSET);
163 #else
164 # pragma acc exit data delete (myblock[i:SUBSET])
165 #endif
166 assert (!cb_ev_free_expected);
167 if (last)
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);
171 }
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));
177
178 #if POINTERS
179 free (myblock);
180 #endif
181
182 acc_prof_unregister (acc_ev_alloc, cb_ev_alloc, acc_reg);
183 acc_prof_unregister (acc_ev_free, cb_ev_free, acc_reg);
184 }
185
186
187 static void
188 f2 (void)
189 {
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);
194
195 #if POINTERS
196 char *block1 = (char *) malloc (SIZE);
197 char *block2 = (char *) malloc (SIZE);
198 char *block3 = (char *) malloc (SIZE);
199 #else
200 char block1[SIZE];
201 char block2[SIZE];
202 char block3[SIZE];
203 #endif
204 int i;
205 for (i = 0; i < SIZE; i++)
206 block1[i] = block2[i] = block3[i] = i;
207
208 cb_ev_alloc_expected = true;
209 #if POINTERS
210 # pragma acc data copyin(block1[0:SIZE], block2[0:SIZE], block3[0:SIZE])
211 #else
212 # pragma acc data copyin(block1, block2, block3)
213 #endif
214 {
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
220 reverse order. */
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);
225
226 for (i = 0; i < SIZE; i += SUBSET)
227 {
228 void *block2_part_d;
229 #if OPENACC_RUNTIME
230 block2_part_d = acc_pcopyin (&block2[i], SUBSET);
231 #else
232 # pragma acc enter data pcopyin (block2[i:SUBSET])
233 block2_part_d = acc_deviceptr (&block2[i]);
234 #endif
235 assert ((uintptr_t) block2_part_d == (uintptr_t) block2_d + i);
236 }
237 }
238 /* The mappings have been removed, but the device memory object has not yet
239 been 'free'd. */
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)
244 {
245 bool last = i >= SIZE - SUBSET;
246
247 assert (acc_is_present (block2, SIZE));
248 if (last)
249 cb_ev_free_expected = true;
250 #if OPENACC_RUNTIME
251 acc_delete (&block2[i], SUBSET);
252 #else
253 # pragma acc exit data delete (block2[i:SUBSET])
254 #endif
255 assert (!cb_ev_free_expected);
256 if (last)
257 assert (cb_ev_free_device_ptr == cb_ev_alloc_device_ptr);
258 }
259 assert (!acc_is_present (block1, SIZE));
260 assert (!acc_is_present (block2, SIZE));
261 assert (!acc_is_present (block3, SIZE));
262
263 #if POINTERS
264 free (block1);
265 free (block2);
266 free (block3);
267 #endif
268
269 acc_prof_unregister (acc_ev_alloc, cb_ev_alloc, acc_reg);
270 acc_prof_unregister (acc_ev_free, cb_ev_free, acc_reg);
271 }
272
273
274 static void
275 f3 ()
276 {
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);
281
282 #if POINTERS
283 char *h = (char *) malloc (SIZE);
284 #else
285 char h[SIZE];
286 #endif
287
288 char *d1;
289 cb_ev_alloc_expected = true;
290 #if OPENACC_RUNTIME
291 d1 = (char *) acc_present_or_create (h, SIZE);
292 #else
293 # if POINTERS
294 # pragma acc enter data present_or_create (h[0:SIZE])
295 # else
296 # pragma acc enter data present_or_create (h)
297 # endif
298 d1 = (char *) acc_deviceptr (h);
299 #endif
300 assert (d1);
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));
306
307 char *d2;
308 #if OPENACC_RUNTIME
309 d2 = (char *) acc_present_or_create (&h[2], SIZE - 2);
310 #else
311 # pragma acc enter data present_or_create (h[2:SIZE - 2])
312 d2 = (char *) acc_deviceptr (&h[2]);
313 #endif
314 assert (d2);
315 assert (d1 == d2 - 2);
316 assert (acc_is_present (h, SIZE));
317 assert (acc_is_present (&h[2], SIZE - 2));
318
319 d2 = (char *) acc_deviceptr (&h[2]);
320 assert (d1 == d2 - 2);
321
322 #if OPENACC_RUNTIME
323 acc_delete (&h[2], SIZE - 2);
324 #else
325 # pragma acc exit data delete (h[2:SIZE - 2])
326 #endif
327 assert (acc_is_present (h, SIZE));
328 assert (acc_is_present (&h[2], SIZE - 2));
329
330 cb_ev_free_expected = true;
331 #if OPENACC_RUNTIME
332 acc_delete (h, SIZE);
333 #else
334 # if POINTERS
335 # pragma acc exit data delete (h[0:SIZE])
336 # else
337 # pragma acc exit data delete (h)
338 # endif
339 #endif
340 assert (!cb_ev_free_expected);
341 assert (cb_ev_free_device_ptr == cb_ev_alloc_device_ptr);
342
343 assert (!acc_is_present (h, SIZE));
344 assert (!acc_is_present (&h[2], SIZE - 2));
345 assert (!acc_is_present (h, 1));
346
347 # if POINTERS
348 free (h);
349 #endif
350
351 acc_prof_unregister (acc_ev_alloc, cb_ev_alloc, acc_reg);
352 acc_prof_unregister (acc_ev_free, cb_ev_free, acc_reg);
353 }
354
355
356 /* Based on what used to be 'libgomp.oacc-c-c++-common/lib-22.c'. */
357
358 static void
359 f_lib_22 (void)
360 {
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);
365
366 const int c0 = 0;
367 const int c1 = 1;
368
369 #if POINTERS
370 char *h = (char *) malloc (SIZE);
371 #else
372 char h[SIZE];
373 #endif
374
375 memset (h, c0, SIZE);
376 void *d;
377 cb_ev_alloc_expected = true;
378 #if OPENACC_RUNTIME
379 d = acc_copyin (h, SIZE);
380 #else
381 # if POINTERS
382 # pragma acc enter data copyin (h[0:SIZE])
383 # else
384 # pragma acc enter data copyin (h)
385 # endif
386 d = acc_deviceptr (h);
387 #endif
388 assert (d);
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;
397 #if OPENACC_RUNTIME
398 acc_copyout (h + SUBSET, SIZE - SUBSET - SUBSET / 2);
399 #else
400 # pragma acc exit data copyout (h[SUBSET:SIZE - SUBSET - SUBSET / 2])
401 #endif
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"
410 subarray. */
411 for (size_t i = 0; i < SIZE; ++i)
412 {
413 if (i < SUBSET)
414 assert (h[i] == c1);
415 else if (i < SIZE - SUBSET / 2)
416 assert (h[i] == c0);
417 else if (i < SIZE)
418 assert (h[i] == c1);
419 }
420
421 #if POINTERS
422 free (h);
423 #endif
424
425 acc_prof_unregister (acc_ev_alloc, cb_ev_alloc, acc_reg);
426 acc_prof_unregister (acc_ev_free, cb_ev_free, acc_reg);
427 }
428
429
430 /* Based on what used to be 'libgomp.oacc-c-c++-common/lib-30.c'. */
431
432 static void
433 f_lib_30 (void)
434 {
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);
439
440 #if POINTERS
441 char *h = (char *) malloc (SIZE);
442 #else
443 char h[SIZE];
444 #endif
445 memset (h, 0, SIZE);
446
447 void *d;
448 cb_ev_alloc_expected = true;
449 #if OPENACC_RUNTIME
450 d = acc_create (h, SIZE);
451 #else
452 # if POINTERS
453 # pragma acc enter data create (h[0:SIZE])
454 # else
455 # pragma acc enter data create (h)
456 # endif
457 d = acc_deviceptr (h);
458 #endif
459 assert (d);
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);
463
464 /* We 'delete' not the whole but only a "subset" subarray... */
465 cb_ev_free_expected = true;
466 #if OPENACC_RUNTIME
467 acc_delete (h, SIZE - SUBSET);
468 #else
469 # pragma acc exit data delete (h[0:SIZE - SUBSET])
470 #endif
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));
478
479 #if POINTERS
480 free (h);
481 #endif
482
483 acc_prof_unregister (acc_ev_alloc, cb_ev_alloc, acc_reg);
484 acc_prof_unregister (acc_ev_free, cb_ev_free, acc_reg);
485 }
486
487
488 int
489 main ()
490 {
491 f1 ();
492 f2 ();
493 f3 ();
494 f_lib_22 ();
495 f_lib_30 ();
496
497 return 0;
498 }