1 /* Verify OpenACC 'firstprivate' mappings.  */
2 
3 /* This file is also sourced from
4    '../../../../libgomp/testsuite/libgomp.oacc-c-c++-common/firstprivate-mappings-1.c'
5    as an execution test.
6 
7    'long double' tests are compiled/used unless DO_LONG_DOUBLE is set to 0.  */
8 
9 /* See also '../../g++.dg/goacc/firstprivate-mappings-1.C'.  */
10 
11 /* { dg-additional-options "-fdump-tree-omplower" } */
12 
13 /* { dg-additional-options "-fext-numeric-literals" { target c++ } } */
14 
15 /* { dg-additional-options "-Wno-psabi" } as apparently we're doing funny
16    things with vector arguments.  */
17 
18 #include <stdbool.h>
19 #include <stdint.h>
20 #include <string.h>
21 
22 
23 #ifdef __SIZEOF_INT128__
24 # define HAVE_INT128 1
25 #else
26 # define HAVE_INT128 0
27 #endif
28 
29 #ifndef DO_LONG_DOUBLE
30 # define DO_LONG_DOUBLE 1
31 #endif
32 
33 
34 /* Simplify scanning for function names in tree dumps.  */
35 #ifdef __cplusplus
36 extern "C" {
37 #endif
38 
39 
40 /* Inside the following OpenACC 'parallel' constructs' regions, we modify the
41    'firstprivate' variables, so that we can check that we don't copy these
42    back.  */
43 
44 
45 static void
p(short * spi)46 p (short *spi)
47 {
48   short *spo;
49 #pragma acc parallel \
50   copyout (spo) \
51   firstprivate (spi)
52   {
53     spo = ++spi;
54   }
55   if (spo != spi + 1)
56     __builtin_abort ();
57 }
58 
59 
60 static void
b(bool bi)61 b (bool bi)
62 {
63   bool bo;
64 #pragma acc parallel \
65   copyout (bo) \
66   firstprivate (bi)
67   {
68     bo = (bi = !bi);
69   }
70   if (bo != !bi)
71     __builtin_abort ();
72 }
73 
74 
75 static void
i(int8_t i8i,uint8_t u8i,int16_t i16i,uint16_t u16i,int32_t i32i,uint32_t u32i,int64_t i64i,uint64_t u64i)76 i (int8_t i8i,
77    uint8_t u8i,
78    int16_t i16i,
79    uint16_t u16i,
80    int32_t i32i,
81    uint32_t u32i,
82    int64_t i64i,
83    uint64_t u64i)
84 {
85   int8_t i8o;
86   uint8_t u8o;
87   int16_t i16o;
88   uint16_t u16o;
89   int32_t i32o;
90   uint32_t u32o;
91   int64_t i64o;
92   uint64_t u64o;
93 #pragma acc parallel \
94   copyout (i8o) \
95   firstprivate (i8i) \
96   copyout (u8o) \
97   firstprivate (u8i) \
98   copyout (i16o) \
99   firstprivate (i16i) \
100   copyout (u16o) \
101   firstprivate (u16i) \
102   copyout (i32o) \
103   firstprivate (i32i) \
104   copyout (u32o) \
105   firstprivate (u32i) \
106   copyout (i64o) \
107   firstprivate (i64i) \
108   copyout (u64o) \
109   firstprivate (u64i)
110   {
111     i8o = --i8i;
112     u8o = ++u8i;
113     i16o = --i16i;
114     u16o = ++u16i;
115     i32o = --i32i;
116     u32o = ++u32i;
117     i64o = --i64i;
118     u64o = ++u64i;
119   }
120   if (i8o != i8i - 1)
121     __builtin_abort ();
122   if (u8o != u8i + 1)
123     __builtin_abort ();
124   if (i16o != i16i - 1)
125     __builtin_abort ();
126   if (u16o != u16i + 1)
127     __builtin_abort ();
128   if (i32o != i32i - 1)
129     __builtin_abort ();
130   if (u32o != u32i + 1)
131     __builtin_abort ();
132   if (i64o != i64i - 1)
133     __builtin_abort ();
134   if (u64o != u64i + 1)
135     __builtin_abort ();
136 }
137 
138 
139 #if HAVE_INT128
140 static void
i128(__int128 i128i,unsigned __int128 u128i)141 i128 (__int128 i128i, unsigned __int128 u128i)
142 {
143   __int128 i128o;
144   unsigned __int128 u128o;
145 # pragma acc parallel \
146   copyout (i128o) \
147   firstprivate (i128i) \
148   copyout(u128o) \
149   firstprivate (u128i)
150   {
151     i128o = --i128i;
152     u128o = ++u128i;
153   }
154   if (i128o != i128i - 1)
155     __builtin_abort ();
156   if (u128o != u128i + 1)
157     __builtin_abort ();
158 }
159 #endif
160 
161 
162 static void
flt_dbl(float flti,double dbli)163 flt_dbl (float flti, double dbli)
164 {
165   float flto;
166   double dblo;
167 #pragma acc parallel \
168   copyout (flto) \
169   firstprivate (flti) \
170   copyout (dblo) \
171   firstprivate (dbli)
172   {
173     flto = --flti;
174     dblo = --dbli;
175   }
176   if (flto != flti - 1)
177     __builtin_abort ();
178   if (dblo != dbli - 1)
179     __builtin_abort ();
180 }
181 
182 
183 static void
ldbl(long double ldbli)184 ldbl (long double ldbli)
185 {
186 #if DO_LONG_DOUBLE
187   long double ldblo;
188 # pragma acc parallel \
189   copyout (ldblo) \
190   firstprivate (ldbli)
191   {
192     ldblo = --ldbli;
193   }
194   if (ldblo != ldbli - 1)
195     __builtin_abort ();
196 #endif
197 }
198 
199 
200 static void
c(_Complex unsigned char cuci,_Complex signed short cssi,_Complex unsigned int cuii,_Complex signed long csli,_Complex float cflti,_Complex double cdbli)201 c (_Complex unsigned char cuci,
202    _Complex signed short cssi,
203    _Complex unsigned int cuii,
204    _Complex signed long csli,
205    _Complex float cflti,
206    _Complex double cdbli)
207 {
208   _Complex unsigned char cuco;
209   _Complex signed short csso;
210   _Complex unsigned int cuio;
211   _Complex signed long cslo;
212   _Complex float cflto;
213   _Complex double cdblo;
214 #pragma acc parallel \
215   copyout (cuco) \
216   firstprivate (cuci) \
217   copyout (csso) \
218   firstprivate (cssi) \
219   copyout (cuio) \
220   firstprivate (cuii) \
221   copyout (cslo) \
222   firstprivate (csli) \
223   copyout (cflto) \
224   firstprivate (cflti) \
225   copyout (cdblo) \
226   firstprivate (cdbli)
227   {
228     cuco = (cuci += (1 + 1j));
229     csso = (cssi -= (1 + 1j));
230     cuio = (cuii += (1 + 1j));
231     cslo = (csli -= (1 + 1j));
232     cflto = (cflti -= (1 + 1j));
233     cdblo = (cdbli -= (1 + 1j));
234   }
235   if (cuco != cuci + (1 + 1j))
236     __builtin_abort ();
237   if (csso != cssi - (1 + 1j))
238     __builtin_abort ();
239   if (cuio != cuii + (1 + 1j))
240     __builtin_abort ();
241   if (cslo != csli - (1 + 1j))
242     __builtin_abort ();
243   if (cflto != cflti - (1 + 1j))
244     __builtin_abort ();
245   if (cdblo != cdbli - (1 + 1j))
246     __builtin_abort ();
247 }
248 
249 
250 static void
cldbl(_Complex long double cldbli)251 cldbl (_Complex long double cldbli)
252 {
253 #if DO_LONG_DOUBLE
254   _Complex long double cldblo;
255 # pragma acc parallel \
256   copyout (cldblo) \
257   firstprivate (cldbli)
258   {
259     cldblo = (cldbli -= (1 + 1j));
260   }
261   if (cldblo != cldbli - (1 + 1j))
262     __builtin_abort ();
263 #endif
264 }
265 
266 
267 #define V_EQ(v1, v2) \
268   ({ \
269     __typeof__ (v1) v_d = (v1) != (v2); \
270     __typeof__ (v_d) v_0 = { 0 }; \
271     memcmp (&v_d, &v_0, sizeof v_d) == 0; \
272   })
273 
274 typedef uint8_t __attribute__ ((vector_size (2 * sizeof (uint8_t)))) v2u8;
275 typedef int16_t __attribute__ ((vector_size (4 * sizeof (int16_t)))) v4i16;
276 typedef uint32_t __attribute__ ((vector_size (8 * sizeof (uint32_t)))) v8u32;
277 typedef int64_t __attribute__ ((vector_size (16 * sizeof (int64_t)))) v16i64;
278 typedef float __attribute__ ((vector_size (1 * sizeof (float)))) v1flt;
279 typedef float __attribute__ ((vector_size (2 * sizeof (float)))) v2flt;
280 typedef float __attribute__ ((vector_size (4 * sizeof (float)))) v4flt;
281 typedef float __attribute__ ((vector_size (8 * sizeof (float)))) v8flt;
282 typedef double __attribute__ ((vector_size (1 * sizeof (double)))) v1dbl;
283 typedef double __attribute__ ((vector_size (2 * sizeof (double)))) v2dbl;
284 typedef double __attribute__ ((vector_size (4 * sizeof (double)))) v4dbl;
285 typedef double __attribute__ ((vector_size (8 * sizeof (double)))) v8dbl;
286 
287 static void
v(v2u8 v2u8i,v4i16 v4i16i,v8u32 v8u32i,v16i64 v16i64i,v1flt v1flti,v2flt v2flti,v4flt v4flti,v8flt v8flti,v1dbl v1dbli,v2dbl v2dbli,v4dbl v4dbli,v8dbl v8dbli)288 v (v2u8 v2u8i, v4i16 v4i16i, v8u32 v8u32i, v16i64 v16i64i,
289    v1flt v1flti, v2flt v2flti, v4flt v4flti, v8flt v8flti,
290    v1dbl v1dbli, v2dbl v2dbli, v4dbl v4dbli, v8dbl v8dbli)
291 {
292   v2u8 v2u8o;
293   v4i16 v4i16o;
294   v8u32 v8u32o;
295   v16i64 v16i64o;
296   v1flt v1flto;
297   v2flt v2flto;
298   v4flt v4flto;
299   v8flt v8flto;
300   v1dbl v1dblo;
301   v2dbl v2dblo;
302   v4dbl v4dblo;
303   v8dbl v8dblo;
304 #pragma acc parallel \
305   copyout (v2u8o) \
306   firstprivate (v2u8i) \
307   copyout (v4i16o) \
308   firstprivate (v4i16i) \
309   copyout (v8u32o) \
310   firstprivate (v8u32i) \
311   copyout (v16i64o) \
312   firstprivate (v16i64i) \
313   copyout (v1flto) \
314   firstprivate (v1flti) \
315   copyout (v2flto) \
316   firstprivate (v2flti) \
317   copyout (v4flto) \
318   firstprivate (v4flti) \
319   copyout (v8flto) \
320   firstprivate (v8flti) \
321   copyout (v1dblo) \
322   firstprivate (v1dbli) \
323   copyout (v2dblo) \
324   firstprivate (v2dbli) \
325   copyout (v4dblo) \
326   firstprivate (v4dbli) \
327   copyout (v8dblo) \
328   firstprivate (v8dbli)
329   {
330     v2u8o = ++v2u8i;
331     v4i16o = --v4i16i;
332     v8u32o = ++v8u32i;
333     v16i64o = --v16i64i;
334     v1flto = --v1flti;
335     v2flto = --v2flti;
336     v4flto = --v4flti;
337     v8flto = --v8flti;
338     v1dblo = --v1dbli;
339     v2dblo = --v2dbli;
340     v4dblo = --v4dbli;
341     v8dblo = --v8dbli;
342   }
343   if (!V_EQ (v2u8o, v2u8i + 1))
344     __builtin_abort ();
345   if (!V_EQ (v4i16o, v4i16i - 1))
346     __builtin_abort ();
347   if (!V_EQ (v8u32o, v8u32i + 1))
348     __builtin_abort ();
349   if (!V_EQ (v16i64o, v16i64i - 1))
350     __builtin_abort ();
351   if (!V_EQ (v1flto, v1flti - 1))
352     __builtin_abort ();
353   if (!V_EQ (v2flto, v2flti - 1))
354     __builtin_abort ();
355   if (!V_EQ (v4flto, v4flti - 1))
356     __builtin_abort ();
357   if (!V_EQ (v8flto, v8flti - 1))
358     __builtin_abort ();
359   if (!V_EQ (v1dblo, v1dbli - 1))
360     __builtin_abort ();
361   if (!V_EQ (v2dblo, v2dbli - 1))
362     __builtin_abort ();
363   if (!V_EQ (v4dblo, v4dbli - 1))
364     __builtin_abort ();
365   if (!V_EQ (v8dblo, v8dbli - 1))
366     __builtin_abort ();
367 }
368 
369 
370 /* "error: could not find an integer type of the same size as 'long double'" */
371 #if HAVE_INT128
372 typedef long double __attribute__ ((vector_size (1 * sizeof (long double)))) v1ldbl;
373 typedef long double __attribute__ ((vector_size (2 * sizeof (long double)))) v2ldbl;
374 typedef long double __attribute__ ((vector_size (4 * sizeof (long double)))) v4ldbl;
375 typedef long double __attribute__ ((vector_size (8 * sizeof (long double)))) v8ldbl;
376 
377 static void
vldbl(v1ldbl v1ldbli,v2ldbl v2ldbli,v4ldbl v4ldbli,v8ldbl v8ldbli)378 vldbl (v1ldbl v1ldbli, v2ldbl v2ldbli, v4ldbl v4ldbli, v8ldbl v8ldbli)
379 {
380 # if DO_LONG_DOUBLE
381   v1ldbl v1ldblo;
382   v2ldbl v2ldblo;
383   v4ldbl v4ldblo;
384   v8ldbl v8ldblo;
385 #  pragma acc parallel \
386   copyout (v1ldblo) \
387   firstprivate (v1ldbli) \
388   copyout (v2ldblo) \
389   firstprivate (v2ldbli) \
390   copyout (v4ldblo) \
391   firstprivate (v4ldbli) \
392   copyout (v8ldblo) \
393   firstprivate (v8ldbli)
394   {
395     v1ldblo = --v1ldbli;
396     v2ldblo = --v2ldbli;
397     v4ldblo = --v4ldbli;
398     v8ldblo = --v8ldbli;
399   }
400   if (!V_EQ (v1ldblo, v1ldbli - 1))
401     __builtin_abort ();
402   if (!V_EQ (v2ldblo, v2ldbli - 1))
403     __builtin_abort ();
404   if (!V_EQ (v4ldblo, v4ldbli - 1))
405     __builtin_abort ();
406   if (!V_EQ (v8ldblo, v8ldbli - 1))
407     __builtin_abort ();
408 # endif
409 }
410 #endif
411 
412 
413 static void
vla(int array_li)414 vla (int array_li)
415 {
416   _Complex double array[array_li];
417   uint32_t array_so;
418 #pragma acc parallel \
419   copyout (array_so)
420   /* The gimplifier has created an implicit 'firstprivate' clause for the array
421      length.
422      { dg-final { scan-tree-dump {(?n)#pragma omp target oacc_parallel map\(from:array_so \[len: 4\]\) firstprivate\(array_li.[0-9]+\)} omplower { target { ! c++ } } } }
423      { dg-final { scan-tree-dump {(?n)#pragma omp target oacc_parallel map\(from:array_so \[len: 4\]\) firstprivate\(} omplower { target { c++ } } } }
424      (C++ computes an intermediate value, so can't scan for 'firstprivate(array_li)'.)  */
425   /* For C, non-LP64, the gimplifier has also created a mapping for the array
426      itself; PR90859.
427      { dg-final { scan-tree-dump {(?n)#pragma omp target oacc_parallel map\(from:array_so \[len: 4\]\) firstprivate\(array_li.[0-9]+\) map\(tofrom:\(\*array.[0-9]+\) \[len: D\.[0-9]+\]\) map\(firstprivate:array \[pointer assign, bias: 0\]\) \[} omplower { target { c && { ! lp64 } } } } } */
428   {
429     array_so = sizeof array;
430   }
431   if (array_so != sizeof array)
432     __builtin_abort ();
433 }
434 
435 
436 #ifdef __cplusplus
437 }
438 #endif
439 
440 
441 int
main(int argc,char * argv[])442 main (int argc, char *argv[])
443 {
444   {
445     short s;
446     short *sp = &s;
447     p (sp);
448   }
449 
450   {
451     bool bi = true;
452     b (bi);
453   }
454 
455   {
456     int8_t i8i = -1;
457     uint8_t u8i = 1;
458     int16_t i16i = -2;
459     uint16_t u16i = 2;
460     int32_t i32i = -3;
461     uint32_t u32i = 3;
462     int64_t i64i = -4;
463     uint64_t u64i = 4;
464     i (i8i, u8i, i16i, u16i, i32i, u32i, i64i, u64i);
465   }
466 
467 #if HAVE_INT128
468   {
469     __int128 i128i = -8;
470     unsigned __int128 u128i = 8;
471     i128 (i128i, u128i);
472   }
473 #endif
474 
475   {
476     float flti = .5;
477     double dbli = .25;
478     flt_dbl (flti, dbli);
479   }
480 
481   {
482     long double ldbli = .125;
483     ldbl (ldbli);
484   }
485 
486   {
487     _Complex unsigned char cuci = 1 + 2j;
488     _Complex signed short cssi = -2 + (-4j);
489     _Complex unsigned int cuii = 3 + 6j;
490     _Complex signed long csli = -4 + (-8j);
491     _Complex float cflti = .5 + 1j;
492     _Complex double cdbli = .25 + .5j;
493     c (cuci, cssi, cuii, csli, cflti, cdbli);
494   }
495 
496   {
497     _Complex long double cldbli = .125 + .25j;
498     cldbl (cldbli);
499   }
500 
501   {
502     v2u8 v2u8i = {2, 3};
503     v4i16 v4i16i = { -1, -2, 5, 4 };
504     v8u32 v8u32i = { 3, 6, 9, 11};
505     v16i64 v16i64i = { 10, 21, -25, 44, 31, -1, 1, 222, -1, -12, 52, -44, -13, 1, -1, -222};
506     v1flt v1flti = { -.5 };
507     v2flt v2flti = { 1.5, -2.5 };
508     v4flt v4flti = { 3.5, -4.5, -5.5, -6.5 };
509     v8flt v8flti = { -7.5, 8.5, 9.5, 10.5, -11.5, -12.5, 13.5, 14.5 };
510     v1dbl v1dbli = { 0.25 };
511     v2dbl v2dbli = { -1.25, -2.25 };
512     v4dbl v4dbli = { 3.25, -4.25, 5.25, 6.25 };
513     v8dbl v8dbli = { 7.25, 8.25, -9.25, -10.25, -11.25, 12.25, 13.25, -14.25 };
514     v (v2u8i, v4i16i, v8u32i, v16i64i,
515        v1flti, v2flti, v4flti, v8flti,
516        v1dbli, v2dbli, v4dbli, v8dbli);
517   }
518 
519 #if HAVE_INT128
520   {
521     v1ldbl v1ldbli = { -0.125 };
522     v2ldbl v2ldbli = { 1.125, -2.125 };
523     v4ldbl v4ldbli = { -3.125, -4.125, 5.125, -6.125 };
524     v8ldbl v8ldbli = { 7.125, -8.125, -9.125, 10.125, 11.125, 12.125, 13.125, 14.125 };
525     vldbl (v1ldbli, v2ldbli, v4ldbli, v8ldbli);
526   }
527 #endif
528 
529   vla (argc);
530 
531   return 0;
532 }
533