1 /* OpenMP directive translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2005-2022 Free Software Foundation, Inc.
3 Contributed by Jakub Jelinek <jakub@redhat.com>
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "options.h"
26 #include "tree.h"
27 #include "gfortran.h"
28 #include "gimple-expr.h"
29 #include "trans.h"
30 #include "stringpool.h"
31 #include "fold-const.h"
32 #include "gimplify.h" /* For create_tmp_var_raw. */
33 #include "trans-stmt.h"
34 #include "trans-types.h"
35 #include "trans-array.h"
36 #include "trans-const.h"
37 #include "arith.h"
38 #include "constructor.h"
39 #include "gomp-constants.h"
40 #include "omp-general.h"
41 #include "omp-low.h"
42 #include "memmodel.h" /* For MEMMODEL_ enums. */
43
44 #undef GCC_DIAG_STYLE
45 #define GCC_DIAG_STYLE __gcc_tdiag__
46 #include "diagnostic-core.h"
47 #undef GCC_DIAG_STYLE
48 #define GCC_DIAG_STYLE __gcc_gfc__
49 #include "attribs.h"
50 #include "function.h"
51
52 int ompws_flags;
53
54 /* True if OpenMP should regard this DECL as being a scalar which has Fortran's
55 allocatable or pointer attribute. */
56
57 bool
gfc_omp_is_allocatable_or_ptr(const_tree decl)58 gfc_omp_is_allocatable_or_ptr (const_tree decl)
59 {
60 return (DECL_P (decl)
61 && (GFC_DECL_GET_SCALAR_POINTER (decl)
62 || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)));
63 }
64
65 /* True if the argument is an optional argument; except that false is also
66 returned for arguments with the value attribute (nonpointers) and for
67 assumed-shape variables (decl is a local variable containing arg->data).
68 Note that for 'procedure(), optional' the value false is used as that's
69 always a pointer and no additional indirection is used.
70 Note that pvoid_type_node is for 'type(c_ptr), value' (and c_funloc). */
71
72 static bool
gfc_omp_is_optional_argument(const_tree decl)73 gfc_omp_is_optional_argument (const_tree decl)
74 {
75 /* Note: VAR_DECL can occur with BIND(C) and array descriptors. */
76 return ((TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == VAR_DECL)
77 && DECL_LANG_SPECIFIC (decl)
78 && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
79 && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
80 && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) != FUNCTION_TYPE
81 && GFC_DECL_OPTIONAL_ARGUMENT (decl));
82 }
83
84 /* Check whether this DECL belongs to a Fortran optional argument.
85 With 'for_present_check' set to false, decls which are optional parameters
86 themselve are returned as tree - or a NULL_TREE otherwise. Those decls are
87 always pointers. With 'for_present_check' set to true, the decl for checking
88 whether an argument is present is returned; for arguments with value
89 attribute this is the hidden argument and of BOOLEAN_TYPE. If the decl is
90 unrelated to optional arguments, NULL_TREE is returned. */
91
92 tree
gfc_omp_check_optional_argument(tree decl,bool for_present_check)93 gfc_omp_check_optional_argument (tree decl, bool for_present_check)
94 {
95 if (!for_present_check)
96 return gfc_omp_is_optional_argument (decl) ? decl : NULL_TREE;
97
98 if (!DECL_LANG_SPECIFIC (decl))
99 return NULL_TREE;
100
101 tree orig_decl = decl;
102
103 /* For assumed-shape arrays, a local decl with arg->data is used. */
104 if (TREE_CODE (decl) != PARM_DECL
105 && (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))
106 || GFC_ARRAY_TYPE_P (TREE_TYPE (decl))))
107 decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
108
109 /* Note: With BIND(C), array descriptors are converted to a VAR_DECL. */
110 if (decl == NULL_TREE
111 || (TREE_CODE (decl) != PARM_DECL && TREE_CODE (decl) != VAR_DECL)
112 || !DECL_LANG_SPECIFIC (decl)
113 || !GFC_DECL_OPTIONAL_ARGUMENT (decl))
114 return NULL_TREE;
115
116 /* Scalars with VALUE attribute which are passed by value use a hidden
117 argument to denote the present status. They are passed as nonpointer type
118 with one exception: 'type(c_ptr), value' as 'void*'. */
119 /* Cf. trans-expr.cc's gfc_conv_expr_present. */
120 if (TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE
121 || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
122 {
123 char name[GFC_MAX_SYMBOL_LEN + 2];
124 tree tree_name;
125
126 name[0] = '_';
127 strcpy (&name[1], IDENTIFIER_POINTER (DECL_NAME (decl)));
128 tree_name = get_identifier (name);
129
130 /* Walk function argument list to find the hidden arg. */
131 decl = DECL_ARGUMENTS (DECL_CONTEXT (decl));
132 for ( ; decl != NULL_TREE; decl = TREE_CHAIN (decl))
133 if (DECL_NAME (decl) == tree_name
134 && DECL_ARTIFICIAL (decl))
135 break;
136
137 gcc_assert (decl);
138 return decl;
139 }
140
141 return fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
142 orig_decl, null_pointer_node);
143 }
144
145
146 /* Returns tree with NULL if it is not an array descriptor and with the tree to
147 access the 'data' component otherwise. With type_only = true, it returns the
148 TREE_TYPE without creating a new tree. */
149
150 tree
gfc_omp_array_data(tree decl,bool type_only)151 gfc_omp_array_data (tree decl, bool type_only)
152 {
153 tree type = TREE_TYPE (decl);
154
155 if (POINTER_TYPE_P (type))
156 type = TREE_TYPE (type);
157
158 if (!GFC_DESCRIPTOR_TYPE_P (type))
159 return NULL_TREE;
160
161 if (type_only)
162 return GFC_TYPE_ARRAY_DATAPTR_TYPE (type);
163
164 if (POINTER_TYPE_P (TREE_TYPE (decl)))
165 decl = build_fold_indirect_ref (decl);
166
167 decl = gfc_conv_descriptor_data_get (decl);
168 STRIP_NOPS (decl);
169 return decl;
170 }
171
172 /* True if OpenMP should privatize what this DECL points to rather
173 than the DECL itself. */
174
175 bool
gfc_omp_privatize_by_reference(const_tree decl)176 gfc_omp_privatize_by_reference (const_tree decl)
177 {
178 tree type = TREE_TYPE (decl);
179
180 if (TREE_CODE (type) == REFERENCE_TYPE
181 && (!DECL_ARTIFICIAL (decl) || TREE_CODE (decl) == PARM_DECL))
182 return true;
183
184 if (TREE_CODE (type) == POINTER_TYPE
185 && gfc_omp_is_optional_argument (decl))
186 return true;
187
188 if (TREE_CODE (type) == POINTER_TYPE)
189 {
190 while (TREE_CODE (decl) == COMPONENT_REF)
191 decl = TREE_OPERAND (decl, 1);
192
193 /* Array POINTER/ALLOCATABLE have aggregate types, all user variables
194 that have POINTER_TYPE type and aren't scalar pointers, scalar
195 allocatables, Cray pointees or C pointers are supposed to be
196 privatized by reference. */
197 if (GFC_DECL_GET_SCALAR_POINTER (decl)
198 || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
199 || GFC_DECL_CRAY_POINTEE (decl)
200 || GFC_DECL_ASSOCIATE_VAR_P (decl)
201 || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
202 return false;
203
204 if (!DECL_ARTIFICIAL (decl)
205 && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
206 return true;
207
208 /* Some arrays are expanded as DECL_ARTIFICIAL pointers
209 by the frontend. */
210 if (DECL_LANG_SPECIFIC (decl)
211 && GFC_DECL_SAVED_DESCRIPTOR (decl))
212 return true;
213 }
214
215 return false;
216 }
217
218 /* OMP_CLAUSE_DEFAULT_UNSPECIFIED unless OpenMP sharing attribute
219 of DECL is predetermined. */
220
221 enum omp_clause_default_kind
gfc_omp_predetermined_sharing(tree decl)222 gfc_omp_predetermined_sharing (tree decl)
223 {
224 /* Associate names preserve the association established during ASSOCIATE.
225 As they are implemented either as pointers to the selector or array
226 descriptor and shouldn't really change in the ASSOCIATE region,
227 this decl can be either shared or firstprivate. If it is a pointer,
228 use firstprivate, as it is cheaper that way, otherwise make it shared. */
229 if (GFC_DECL_ASSOCIATE_VAR_P (decl))
230 {
231 if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
232 return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
233 else
234 return OMP_CLAUSE_DEFAULT_SHARED;
235 }
236
237 if (DECL_ARTIFICIAL (decl)
238 && ! GFC_DECL_RESULT (decl)
239 && ! (DECL_LANG_SPECIFIC (decl)
240 && GFC_DECL_SAVED_DESCRIPTOR (decl)))
241 return OMP_CLAUSE_DEFAULT_SHARED;
242
243 /* Cray pointees shouldn't be listed in any clauses and should be
244 gimplified to dereference of the corresponding Cray pointer.
245 Make them all private, so that they are emitted in the debug
246 information. */
247 if (GFC_DECL_CRAY_POINTEE (decl))
248 return OMP_CLAUSE_DEFAULT_PRIVATE;
249
250 /* Assumed-size arrays are predetermined shared. */
251 if (TREE_CODE (decl) == PARM_DECL
252 && GFC_ARRAY_TYPE_P (TREE_TYPE (decl))
253 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN
254 && GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (decl),
255 GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)) - 1)
256 == NULL)
257 return OMP_CLAUSE_DEFAULT_SHARED;
258
259 /* Dummy procedures aren't considered variables by OpenMP, thus are
260 disallowed in OpenMP clauses. They are represented as PARM_DECLs
261 in the middle-end, so return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE here
262 to avoid complaining about their uses with default(none). */
263 if (TREE_CODE (decl) == PARM_DECL
264 && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
265 && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == FUNCTION_TYPE)
266 return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
267
268 /* COMMON and EQUIVALENCE decls are shared. They
269 are only referenced through DECL_VALUE_EXPR of the variables
270 contained in them. If those are privatized, they will not be
271 gimplified to the COMMON or EQUIVALENCE decls. */
272 if (GFC_DECL_COMMON_OR_EQUIV (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
273 return OMP_CLAUSE_DEFAULT_SHARED;
274
275 if (GFC_DECL_RESULT (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
276 return OMP_CLAUSE_DEFAULT_SHARED;
277
278 /* These are either array or derived parameters, or vtables.
279 In the former cases, the OpenMP standard doesn't consider them to be
280 variables at all (they can't be redefined), but they can nevertheless appear
281 in parallel/task regions and for default(none) purposes treat them as shared.
282 For vtables likely the same handling is desirable. */
283 if (VAR_P (decl) && TREE_READONLY (decl)
284 && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
285 return OMP_CLAUSE_DEFAULT_SHARED;
286
287 return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
288 }
289
290
291 /* OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED unless OpenMP mapping attribute
292 of DECL is predetermined. */
293
294 enum omp_clause_defaultmap_kind
gfc_omp_predetermined_mapping(tree decl)295 gfc_omp_predetermined_mapping (tree decl)
296 {
297 if (DECL_ARTIFICIAL (decl)
298 && ! GFC_DECL_RESULT (decl)
299 && ! (DECL_LANG_SPECIFIC (decl)
300 && GFC_DECL_SAVED_DESCRIPTOR (decl)))
301 return OMP_CLAUSE_DEFAULTMAP_TO;
302
303 /* These are either array or derived parameters, or vtables. */
304 if (VAR_P (decl) && TREE_READONLY (decl)
305 && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
306 return OMP_CLAUSE_DEFAULTMAP_TO;
307
308 return OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
309 }
310
311
312 /* Return decl that should be used when reporting DEFAULT(NONE)
313 diagnostics. */
314
315 tree
gfc_omp_report_decl(tree decl)316 gfc_omp_report_decl (tree decl)
317 {
318 if (DECL_ARTIFICIAL (decl)
319 && DECL_LANG_SPECIFIC (decl)
320 && GFC_DECL_SAVED_DESCRIPTOR (decl))
321 return GFC_DECL_SAVED_DESCRIPTOR (decl);
322
323 return decl;
324 }
325
326 /* Return true if TYPE has any allocatable components. */
327
328 static bool
gfc_has_alloc_comps(tree type,tree decl)329 gfc_has_alloc_comps (tree type, tree decl)
330 {
331 tree field, ftype;
332
333 if (POINTER_TYPE_P (type))
334 {
335 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
336 type = TREE_TYPE (type);
337 else if (GFC_DECL_GET_SCALAR_POINTER (decl))
338 return false;
339 }
340
341 if (GFC_DESCRIPTOR_TYPE_P (type)
342 && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER
343 || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
344 return false;
345
346 if (GFC_DESCRIPTOR_TYPE_P (type) || GFC_ARRAY_TYPE_P (type))
347 type = gfc_get_element_type (type);
348
349 if (TREE_CODE (type) != RECORD_TYPE)
350 return false;
351
352 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
353 {
354 ftype = TREE_TYPE (field);
355 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
356 return true;
357 if (GFC_DESCRIPTOR_TYPE_P (ftype)
358 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
359 return true;
360 if (gfc_has_alloc_comps (ftype, field))
361 return true;
362 }
363 return false;
364 }
365
366 /* Return true if TYPE is polymorphic but not with pointer attribute. */
367
368 static bool
gfc_is_polymorphic_nonptr(tree type)369 gfc_is_polymorphic_nonptr (tree type)
370 {
371 if (POINTER_TYPE_P (type))
372 type = TREE_TYPE (type);
373 return GFC_CLASS_TYPE_P (type);
374 }
375
376 /* Return true if TYPE is unlimited polymorphic but not with pointer attribute;
377 unlimited means also intrinsic types are handled and _len is used. */
378
379 static bool
gfc_is_unlimited_polymorphic_nonptr(tree type)380 gfc_is_unlimited_polymorphic_nonptr (tree type)
381 {
382 if (POINTER_TYPE_P (type))
383 type = TREE_TYPE (type);
384 if (!GFC_CLASS_TYPE_P (type))
385 return false;
386
387 tree field = TYPE_FIELDS (type); /* _data */
388 gcc_assert (field);
389 field = DECL_CHAIN (field); /* _vptr */
390 gcc_assert (field);
391 field = DECL_CHAIN (field);
392 if (!field)
393 return false;
394 gcc_assert (strcmp ("_len", IDENTIFIER_POINTER (DECL_NAME (field))) == 0);
395 return true;
396 }
397
398 /* Return true if the DECL is for an allocatable array or scalar. */
399
400 bool
gfc_omp_allocatable_p(tree decl)401 gfc_omp_allocatable_p (tree decl)
402 {
403 if (!DECL_P (decl))
404 return false;
405
406 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
407 return true;
408
409 tree type = TREE_TYPE (decl);
410 if (gfc_omp_privatize_by_reference (decl))
411 type = TREE_TYPE (type);
412
413 if (GFC_DESCRIPTOR_TYPE_P (type)
414 && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
415 return true;
416
417 return false;
418 }
419
420
421 /* Return true if DECL in private clause needs
422 OMP_CLAUSE_PRIVATE_OUTER_REF on the private clause. */
423 bool
gfc_omp_private_outer_ref(tree decl)424 gfc_omp_private_outer_ref (tree decl)
425 {
426 tree type = TREE_TYPE (decl);
427
428 if (gfc_omp_privatize_by_reference (decl))
429 type = TREE_TYPE (type);
430
431 if (GFC_DESCRIPTOR_TYPE_P (type)
432 && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
433 return true;
434
435 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
436 return true;
437
438 if (gfc_has_alloc_comps (type, decl))
439 return true;
440
441 return false;
442 }
443
444 /* Callback for gfc_omp_unshare_expr. */
445
446 static tree
gfc_omp_unshare_expr_r(tree * tp,int * walk_subtrees,void *)447 gfc_omp_unshare_expr_r (tree *tp, int *walk_subtrees, void *)
448 {
449 tree t = *tp;
450 enum tree_code code = TREE_CODE (t);
451
452 /* Stop at types, decls, constants like copy_tree_r. */
453 if (TREE_CODE_CLASS (code) == tcc_type
454 || TREE_CODE_CLASS (code) == tcc_declaration
455 || TREE_CODE_CLASS (code) == tcc_constant
456 || code == BLOCK)
457 *walk_subtrees = 0;
458 else if (handled_component_p (t)
459 || TREE_CODE (t) == MEM_REF)
460 {
461 *tp = unshare_expr (t);
462 *walk_subtrees = 0;
463 }
464
465 return NULL_TREE;
466 }
467
468 /* Unshare in expr anything that the FE which normally doesn't
469 care much about tree sharing (because during gimplification
470 everything is unshared) could cause problems with tree sharing
471 at omp-low.cc time. */
472
473 static tree
gfc_omp_unshare_expr(tree expr)474 gfc_omp_unshare_expr (tree expr)
475 {
476 walk_tree (&expr, gfc_omp_unshare_expr_r, NULL, NULL);
477 return expr;
478 }
479
480 enum walk_alloc_comps
481 {
482 WALK_ALLOC_COMPS_DTOR,
483 WALK_ALLOC_COMPS_DEFAULT_CTOR,
484 WALK_ALLOC_COMPS_COPY_CTOR
485 };
486
487 /* Handle allocatable components in OpenMP clauses. */
488
489 static tree
gfc_walk_alloc_comps(tree decl,tree dest,tree var,enum walk_alloc_comps kind)490 gfc_walk_alloc_comps (tree decl, tree dest, tree var,
491 enum walk_alloc_comps kind)
492 {
493 stmtblock_t block, tmpblock;
494 tree type = TREE_TYPE (decl), then_b, tem, field;
495 gfc_init_block (&block);
496
497 if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
498 {
499 if (GFC_DESCRIPTOR_TYPE_P (type))
500 {
501 gfc_init_block (&tmpblock);
502 tem = gfc_full_array_size (&tmpblock, decl,
503 GFC_TYPE_ARRAY_RANK (type));
504 then_b = gfc_finish_block (&tmpblock);
505 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (then_b));
506 tem = gfc_omp_unshare_expr (tem);
507 tem = fold_build2_loc (input_location, MINUS_EXPR,
508 gfc_array_index_type, tem,
509 gfc_index_one_node);
510 }
511 else
512 {
513 bool compute_nelts = false;
514 if (!TYPE_DOMAIN (type)
515 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE
516 || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node
517 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node)
518 compute_nelts = true;
519 else if (VAR_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
520 {
521 tree a = DECL_ATTRIBUTES (TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
522 if (lookup_attribute ("omp dummy var", a))
523 compute_nelts = true;
524 }
525 if (compute_nelts)
526 {
527 tem = fold_build2 (EXACT_DIV_EXPR, sizetype,
528 TYPE_SIZE_UNIT (type),
529 TYPE_SIZE_UNIT (TREE_TYPE (type)));
530 tem = size_binop (MINUS_EXPR, tem, size_one_node);
531 }
532 else
533 tem = array_type_nelts (type);
534 tem = fold_convert (gfc_array_index_type, tem);
535 }
536
537 tree nelems = gfc_evaluate_now (tem, &block);
538 tree index = gfc_create_var (gfc_array_index_type, "S");
539
540 gfc_init_block (&tmpblock);
541 tem = gfc_conv_array_data (decl);
542 tree declvar = build_fold_indirect_ref_loc (input_location, tem);
543 tree declvref = gfc_build_array_ref (declvar, index, NULL);
544 tree destvar, destvref = NULL_TREE;
545 if (dest)
546 {
547 tem = gfc_conv_array_data (dest);
548 destvar = build_fold_indirect_ref_loc (input_location, tem);
549 destvref = gfc_build_array_ref (destvar, index, NULL);
550 }
551 gfc_add_expr_to_block (&tmpblock,
552 gfc_walk_alloc_comps (declvref, destvref,
553 var, kind));
554
555 gfc_loopinfo loop;
556 gfc_init_loopinfo (&loop);
557 loop.dimen = 1;
558 loop.from[0] = gfc_index_zero_node;
559 loop.loopvar[0] = index;
560 loop.to[0] = nelems;
561 gfc_trans_scalarizing_loops (&loop, &tmpblock);
562 gfc_add_block_to_block (&block, &loop.pre);
563 return gfc_finish_block (&block);
564 }
565 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (var))
566 {
567 decl = build_fold_indirect_ref_loc (input_location, decl);
568 if (dest)
569 dest = build_fold_indirect_ref_loc (input_location, dest);
570 type = TREE_TYPE (decl);
571 }
572
573 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
574 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
575 {
576 tree ftype = TREE_TYPE (field);
577 tree declf, destf = NULL_TREE;
578 bool has_alloc_comps = gfc_has_alloc_comps (ftype, field);
579 if ((!GFC_DESCRIPTOR_TYPE_P (ftype)
580 || GFC_TYPE_ARRAY_AKIND (ftype) != GFC_ARRAY_ALLOCATABLE)
581 && !GFC_DECL_GET_SCALAR_ALLOCATABLE (field)
582 && !has_alloc_comps)
583 continue;
584 declf = fold_build3_loc (input_location, COMPONENT_REF, ftype,
585 decl, field, NULL_TREE);
586 if (dest)
587 destf = fold_build3_loc (input_location, COMPONENT_REF, ftype,
588 dest, field, NULL_TREE);
589
590 tem = NULL_TREE;
591 switch (kind)
592 {
593 case WALK_ALLOC_COMPS_DTOR:
594 break;
595 case WALK_ALLOC_COMPS_DEFAULT_CTOR:
596 if (GFC_DESCRIPTOR_TYPE_P (ftype)
597 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
598 {
599 gfc_add_modify (&block, unshare_expr (destf),
600 unshare_expr (declf));
601 tem = gfc_duplicate_allocatable_nocopy
602 (destf, declf, ftype,
603 GFC_TYPE_ARRAY_RANK (ftype));
604 }
605 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
606 tem = gfc_duplicate_allocatable_nocopy (destf, declf, ftype, 0);
607 break;
608 case WALK_ALLOC_COMPS_COPY_CTOR:
609 if (GFC_DESCRIPTOR_TYPE_P (ftype)
610 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
611 tem = gfc_duplicate_allocatable (destf, declf, ftype,
612 GFC_TYPE_ARRAY_RANK (ftype),
613 NULL_TREE);
614 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
615 tem = gfc_duplicate_allocatable (destf, declf, ftype, 0,
616 NULL_TREE);
617 break;
618 }
619 if (tem)
620 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
621 if (has_alloc_comps)
622 {
623 gfc_init_block (&tmpblock);
624 gfc_add_expr_to_block (&tmpblock,
625 gfc_walk_alloc_comps (declf, destf,
626 field, kind));
627 then_b = gfc_finish_block (&tmpblock);
628 if (GFC_DESCRIPTOR_TYPE_P (ftype)
629 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
630 tem = gfc_conv_descriptor_data_get (unshare_expr (declf));
631 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
632 tem = unshare_expr (declf);
633 else
634 tem = NULL_TREE;
635 if (tem)
636 {
637 tem = fold_convert (pvoid_type_node, tem);
638 tem = fold_build2_loc (input_location, NE_EXPR,
639 logical_type_node, tem,
640 null_pointer_node);
641 then_b = build3_loc (input_location, COND_EXPR, void_type_node,
642 tem, then_b,
643 build_empty_stmt (input_location));
644 }
645 gfc_add_expr_to_block (&block, then_b);
646 }
647 if (kind == WALK_ALLOC_COMPS_DTOR)
648 {
649 if (GFC_DESCRIPTOR_TYPE_P (ftype)
650 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
651 {
652 tem = gfc_conv_descriptor_data_get (unshare_expr (declf));
653 tem = gfc_deallocate_with_status (tem, NULL_TREE, NULL_TREE,
654 NULL_TREE, NULL_TREE, true,
655 NULL,
656 GFC_CAF_COARRAY_NOCOARRAY);
657 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
658 }
659 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
660 {
661 tem = gfc_call_free (unshare_expr (declf));
662 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
663 }
664 }
665 }
666
667 return gfc_finish_block (&block);
668 }
669
670 /* Return code to initialize DECL with its default constructor, or
671 NULL if there's nothing to do. */
672
673 tree
gfc_omp_clause_default_ctor(tree clause,tree decl,tree outer)674 gfc_omp_clause_default_ctor (tree clause, tree decl, tree outer)
675 {
676 tree type = TREE_TYPE (decl), size, ptr, cond, then_b, else_b;
677 stmtblock_t block, cond_block;
678
679 switch (OMP_CLAUSE_CODE (clause))
680 {
681 case OMP_CLAUSE__LOOPTEMP_:
682 case OMP_CLAUSE__REDUCTEMP_:
683 case OMP_CLAUSE__CONDTEMP_:
684 case OMP_CLAUSE__SCANTEMP_:
685 return NULL;
686 case OMP_CLAUSE_PRIVATE:
687 case OMP_CLAUSE_LASTPRIVATE:
688 case OMP_CLAUSE_LINEAR:
689 case OMP_CLAUSE_REDUCTION:
690 case OMP_CLAUSE_IN_REDUCTION:
691 case OMP_CLAUSE_TASK_REDUCTION:
692 break;
693 default:
694 gcc_unreachable ();
695 }
696
697 if ((! GFC_DESCRIPTOR_TYPE_P (type)
698 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
699 && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
700 || !POINTER_TYPE_P (type)))
701 {
702 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
703 {
704 gcc_assert (outer);
705 gfc_start_block (&block);
706 tree tem = gfc_walk_alloc_comps (outer, decl,
707 OMP_CLAUSE_DECL (clause),
708 WALK_ALLOC_COMPS_DEFAULT_CTOR);
709 gfc_add_expr_to_block (&block, tem);
710 return gfc_finish_block (&block);
711 }
712 return NULL_TREE;
713 }
714
715 gcc_assert (outer != NULL_TREE);
716
717 /* Allocatable arrays and scalars in PRIVATE clauses need to be set to
718 "not currently allocated" allocation status if outer
719 array is "not currently allocated", otherwise should be allocated. */
720 gfc_start_block (&block);
721
722 gfc_init_block (&cond_block);
723
724 if (GFC_DESCRIPTOR_TYPE_P (type))
725 {
726 gfc_add_modify (&cond_block, decl, outer);
727 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
728 size = gfc_conv_descriptor_ubound_get (decl, rank);
729 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
730 size,
731 gfc_conv_descriptor_lbound_get (decl, rank));
732 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
733 size, gfc_index_one_node);
734 if (GFC_TYPE_ARRAY_RANK (type) > 1)
735 size = fold_build2_loc (input_location, MULT_EXPR,
736 gfc_array_index_type, size,
737 gfc_conv_descriptor_stride_get (decl, rank));
738 tree esize = fold_convert (gfc_array_index_type,
739 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
740 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
741 size, esize);
742 size = unshare_expr (size);
743 size = gfc_evaluate_now (fold_convert (size_type_node, size),
744 &cond_block);
745 }
746 else
747 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
748 ptr = gfc_create_var (pvoid_type_node, NULL);
749 gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
750 if (GFC_DESCRIPTOR_TYPE_P (type))
751 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl), ptr);
752 else
753 gfc_add_modify (&cond_block, unshare_expr (decl),
754 fold_convert (TREE_TYPE (decl), ptr));
755 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
756 {
757 tree tem = gfc_walk_alloc_comps (outer, decl,
758 OMP_CLAUSE_DECL (clause),
759 WALK_ALLOC_COMPS_DEFAULT_CTOR);
760 gfc_add_expr_to_block (&cond_block, tem);
761 }
762 then_b = gfc_finish_block (&cond_block);
763
764 /* Reduction clause requires allocated ALLOCATABLE. */
765 if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_REDUCTION
766 && OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_IN_REDUCTION
767 && OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_TASK_REDUCTION)
768 {
769 gfc_init_block (&cond_block);
770 if (GFC_DESCRIPTOR_TYPE_P (type))
771 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl),
772 null_pointer_node);
773 else
774 gfc_add_modify (&cond_block, unshare_expr (decl),
775 build_zero_cst (TREE_TYPE (decl)));
776 else_b = gfc_finish_block (&cond_block);
777
778 tree tem = fold_convert (pvoid_type_node,
779 GFC_DESCRIPTOR_TYPE_P (type)
780 ? gfc_conv_descriptor_data_get (outer) : outer);
781 tem = unshare_expr (tem);
782 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
783 tem, null_pointer_node);
784 gfc_add_expr_to_block (&block,
785 build3_loc (input_location, COND_EXPR,
786 void_type_node, cond, then_b,
787 else_b));
788 /* Avoid -W*uninitialized warnings. */
789 if (DECL_P (decl))
790 suppress_warning (decl, OPT_Wuninitialized);
791 }
792 else
793 gfc_add_expr_to_block (&block, then_b);
794
795 return gfc_finish_block (&block);
796 }
797
798 /* Build and return code for a copy constructor from SRC to DEST. */
799
800 tree
gfc_omp_clause_copy_ctor(tree clause,tree dest,tree src)801 gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
802 {
803 tree type = TREE_TYPE (dest), ptr, size, call;
804 tree decl_type = TREE_TYPE (OMP_CLAUSE_DECL (clause));
805 tree cond, then_b, else_b;
806 stmtblock_t block, cond_block;
807
808 gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE
809 || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
810
811 /* Privatize pointer, only; cf. gfc_omp_predetermined_sharing. */
812 if (DECL_P (OMP_CLAUSE_DECL (clause))
813 && GFC_DECL_ASSOCIATE_VAR_P (OMP_CLAUSE_DECL (clause)))
814 return build2 (MODIFY_EXPR, TREE_TYPE (dest), dest, src);
815
816 if (DECL_ARTIFICIAL (OMP_CLAUSE_DECL (clause))
817 && DECL_LANG_SPECIFIC (OMP_CLAUSE_DECL (clause))
818 && GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause)))
819 decl_type
820 = TREE_TYPE (GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause)));
821
822 if (gfc_is_polymorphic_nonptr (decl_type))
823 {
824 if (POINTER_TYPE_P (decl_type))
825 decl_type = TREE_TYPE (decl_type);
826 decl_type = TREE_TYPE (TYPE_FIELDS (decl_type));
827 if (GFC_DESCRIPTOR_TYPE_P (decl_type) || GFC_ARRAY_TYPE_P (decl_type))
828 fatal_error (input_location,
829 "Sorry, polymorphic arrays not yet supported for "
830 "firstprivate");
831 tree src_len;
832 tree nelems = build_int_cst (size_type_node, 1); /* Scalar. */
833 tree src_data = gfc_class_data_get (unshare_expr (src));
834 tree dest_data = gfc_class_data_get (unshare_expr (dest));
835 bool unlimited = gfc_is_unlimited_polymorphic_nonptr (type);
836
837 gfc_start_block (&block);
838 gfc_add_modify (&block, gfc_class_vptr_get (dest),
839 gfc_class_vptr_get (src));
840 gfc_init_block (&cond_block);
841
842 if (unlimited)
843 {
844 src_len = gfc_class_len_get (src);
845 gfc_add_modify (&cond_block, gfc_class_len_get (unshare_expr (dest)), src_len);
846 }
847
848 /* Use: size = class._vtab._size * (class._len > 0 ? class._len : 1). */
849 size = fold_convert (size_type_node, gfc_class_vtab_size_get (src));
850 if (unlimited)
851 {
852 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
853 unshare_expr (src_len),
854 build_zero_cst (TREE_TYPE (src_len)));
855 cond = build3_loc (input_location, COND_EXPR, size_type_node, cond,
856 fold_convert (size_type_node,
857 unshare_expr (src_len)),
858 build_int_cst (size_type_node, 1));
859 size = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
860 size, cond);
861 }
862
863 /* Malloc memory + call class->_vpt->_copy. */
864 call = builtin_decl_explicit (BUILT_IN_MALLOC);
865 call = build_call_expr_loc (input_location, call, 1, size);
866 gfc_add_modify (&cond_block, dest_data,
867 fold_convert (TREE_TYPE (dest_data), call));
868 gfc_add_expr_to_block (&cond_block,
869 gfc_copy_class_to_class (src, dest, nelems,
870 unlimited));
871
872 gcc_assert (TREE_CODE (dest_data) == COMPONENT_REF);
873 if (!GFC_DECL_GET_SCALAR_ALLOCATABLE (TREE_OPERAND (dest_data, 1)))
874 {
875 gfc_add_block_to_block (&block, &cond_block);
876 }
877 else
878 {
879 /* Create: if (class._data != 0) <cond_block> else class._data = NULL; */
880 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
881 src_data, null_pointer_node);
882 gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR,
883 void_type_node, cond,
884 gfc_finish_block (&cond_block),
885 fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
886 unshare_expr (dest_data), null_pointer_node)));
887 }
888 return gfc_finish_block (&block);
889 }
890
891 if ((! GFC_DESCRIPTOR_TYPE_P (type)
892 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
893 && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
894 || !POINTER_TYPE_P (type)))
895 {
896 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
897 {
898 gfc_start_block (&block);
899 gfc_add_modify (&block, dest, src);
900 tree tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause),
901 WALK_ALLOC_COMPS_COPY_CTOR);
902 gfc_add_expr_to_block (&block, tem);
903 return gfc_finish_block (&block);
904 }
905 else
906 return build2_v (MODIFY_EXPR, dest, src);
907 }
908
909 /* Allocatable arrays in FIRSTPRIVATE clauses need to be allocated
910 and copied from SRC. */
911 gfc_start_block (&block);
912
913 gfc_init_block (&cond_block);
914
915 gfc_add_modify (&cond_block, dest, fold_convert (TREE_TYPE (dest), src));
916 if (GFC_DESCRIPTOR_TYPE_P (type))
917 {
918 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
919 size = gfc_conv_descriptor_ubound_get (dest, rank);
920 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
921 size,
922 gfc_conv_descriptor_lbound_get (dest, rank));
923 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
924 size, gfc_index_one_node);
925 if (GFC_TYPE_ARRAY_RANK (type) > 1)
926 size = fold_build2_loc (input_location, MULT_EXPR,
927 gfc_array_index_type, size,
928 gfc_conv_descriptor_stride_get (dest, rank));
929 tree esize = fold_convert (gfc_array_index_type,
930 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
931 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
932 size, esize);
933 size = unshare_expr (size);
934 size = gfc_evaluate_now (fold_convert (size_type_node, size),
935 &cond_block);
936 }
937 else
938 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
939 ptr = gfc_create_var (pvoid_type_node, NULL);
940 gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
941 if (GFC_DESCRIPTOR_TYPE_P (type))
942 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest), ptr);
943 else
944 gfc_add_modify (&cond_block, unshare_expr (dest),
945 fold_convert (TREE_TYPE (dest), ptr));
946
947 tree srcptr = GFC_DESCRIPTOR_TYPE_P (type)
948 ? gfc_conv_descriptor_data_get (src) : src;
949 srcptr = unshare_expr (srcptr);
950 srcptr = fold_convert (pvoid_type_node, srcptr);
951 call = build_call_expr_loc (input_location,
952 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr,
953 srcptr, size);
954 gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
955 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
956 {
957 tree tem = gfc_walk_alloc_comps (src, dest,
958 OMP_CLAUSE_DECL (clause),
959 WALK_ALLOC_COMPS_COPY_CTOR);
960 gfc_add_expr_to_block (&cond_block, tem);
961 }
962 then_b = gfc_finish_block (&cond_block);
963
964 gfc_init_block (&cond_block);
965 if (GFC_DESCRIPTOR_TYPE_P (type))
966 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest),
967 null_pointer_node);
968 else
969 gfc_add_modify (&cond_block, unshare_expr (dest),
970 build_zero_cst (TREE_TYPE (dest)));
971 else_b = gfc_finish_block (&cond_block);
972
973 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
974 unshare_expr (srcptr), null_pointer_node);
975 gfc_add_expr_to_block (&block,
976 build3_loc (input_location, COND_EXPR,
977 void_type_node, cond, then_b, else_b));
978 /* Avoid -W*uninitialized warnings. */
979 if (DECL_P (dest))
980 suppress_warning (dest, OPT_Wuninitialized);
981
982 return gfc_finish_block (&block);
983 }
984
985 /* Similarly, except use an intrinsic or pointer assignment operator
986 instead. */
987
988 tree
gfc_omp_clause_assign_op(tree clause,tree dest,tree src)989 gfc_omp_clause_assign_op (tree clause, tree dest, tree src)
990 {
991 tree type = TREE_TYPE (dest), ptr, size, call, nonalloc;
992 tree cond, then_b, else_b;
993 stmtblock_t block, cond_block, cond_block2, inner_block;
994
995 if ((! GFC_DESCRIPTOR_TYPE_P (type)
996 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
997 && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
998 || !POINTER_TYPE_P (type)))
999 {
1000 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
1001 {
1002 gfc_start_block (&block);
1003 /* First dealloc any allocatable components in DEST. */
1004 tree tem = gfc_walk_alloc_comps (dest, NULL_TREE,
1005 OMP_CLAUSE_DECL (clause),
1006 WALK_ALLOC_COMPS_DTOR);
1007 gfc_add_expr_to_block (&block, tem);
1008 /* Then copy over toplevel data. */
1009 gfc_add_modify (&block, dest, src);
1010 /* Finally allocate any allocatable components and copy. */
1011 tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause),
1012 WALK_ALLOC_COMPS_COPY_CTOR);
1013 gfc_add_expr_to_block (&block, tem);
1014 return gfc_finish_block (&block);
1015 }
1016 else
1017 return build2_v (MODIFY_EXPR, dest, src);
1018 }
1019
1020 gfc_start_block (&block);
1021
1022 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
1023 {
1024 then_b = gfc_walk_alloc_comps (dest, NULL_TREE, OMP_CLAUSE_DECL (clause),
1025 WALK_ALLOC_COMPS_DTOR);
1026 tree tem = fold_convert (pvoid_type_node,
1027 GFC_DESCRIPTOR_TYPE_P (type)
1028 ? gfc_conv_descriptor_data_get (dest) : dest);
1029 tem = unshare_expr (tem);
1030 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1031 tem, null_pointer_node);
1032 tem = build3_loc (input_location, COND_EXPR, void_type_node, cond,
1033 then_b, build_empty_stmt (input_location));
1034 gfc_add_expr_to_block (&block, tem);
1035 }
1036
1037 gfc_init_block (&cond_block);
1038
1039 if (GFC_DESCRIPTOR_TYPE_P (type))
1040 {
1041 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
1042 size = gfc_conv_descriptor_ubound_get (src, rank);
1043 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
1044 size,
1045 gfc_conv_descriptor_lbound_get (src, rank));
1046 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1047 size, gfc_index_one_node);
1048 if (GFC_TYPE_ARRAY_RANK (type) > 1)
1049 size = fold_build2_loc (input_location, MULT_EXPR,
1050 gfc_array_index_type, size,
1051 gfc_conv_descriptor_stride_get (src, rank));
1052 tree esize = fold_convert (gfc_array_index_type,
1053 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
1054 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1055 size, esize);
1056 size = unshare_expr (size);
1057 size = gfc_evaluate_now (fold_convert (size_type_node, size),
1058 &cond_block);
1059 }
1060 else
1061 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
1062 ptr = gfc_create_var (pvoid_type_node, NULL);
1063
1064 tree destptr = GFC_DESCRIPTOR_TYPE_P (type)
1065 ? gfc_conv_descriptor_data_get (dest) : dest;
1066 destptr = unshare_expr (destptr);
1067 destptr = fold_convert (pvoid_type_node, destptr);
1068 gfc_add_modify (&cond_block, ptr, destptr);
1069
1070 nonalloc = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
1071 destptr, null_pointer_node);
1072 cond = nonalloc;
1073 if (GFC_DESCRIPTOR_TYPE_P (type))
1074 {
1075 int i;
1076 for (i = 0; i < GFC_TYPE_ARRAY_RANK (type); i++)
1077 {
1078 tree rank = gfc_rank_cst[i];
1079 tree tem = gfc_conv_descriptor_ubound_get (src, rank);
1080 tem = fold_build2_loc (input_location, MINUS_EXPR,
1081 gfc_array_index_type, tem,
1082 gfc_conv_descriptor_lbound_get (src, rank));
1083 tem = fold_build2_loc (input_location, PLUS_EXPR,
1084 gfc_array_index_type, tem,
1085 gfc_conv_descriptor_lbound_get (dest, rank));
1086 tem = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1087 tem, gfc_conv_descriptor_ubound_get (dest,
1088 rank));
1089 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1090 logical_type_node, cond, tem);
1091 }
1092 }
1093
1094 gfc_init_block (&cond_block2);
1095
1096 if (GFC_DESCRIPTOR_TYPE_P (type))
1097 {
1098 gfc_init_block (&inner_block);
1099 gfc_allocate_using_malloc (&inner_block, ptr, size, NULL_TREE);
1100 then_b = gfc_finish_block (&inner_block);
1101
1102 gfc_init_block (&inner_block);
1103 gfc_add_modify (&inner_block, ptr,
1104 gfc_call_realloc (&inner_block, ptr, size));
1105 else_b = gfc_finish_block (&inner_block);
1106
1107 gfc_add_expr_to_block (&cond_block2,
1108 build3_loc (input_location, COND_EXPR,
1109 void_type_node,
1110 unshare_expr (nonalloc),
1111 then_b, else_b));
1112 gfc_add_modify (&cond_block2, dest, src);
1113 gfc_conv_descriptor_data_set (&cond_block2, unshare_expr (dest), ptr);
1114 }
1115 else
1116 {
1117 gfc_allocate_using_malloc (&cond_block2, ptr, size, NULL_TREE);
1118 gfc_add_modify (&cond_block2, unshare_expr (dest),
1119 fold_convert (type, ptr));
1120 }
1121 then_b = gfc_finish_block (&cond_block2);
1122 else_b = build_empty_stmt (input_location);
1123
1124 gfc_add_expr_to_block (&cond_block,
1125 build3_loc (input_location, COND_EXPR,
1126 void_type_node, unshare_expr (cond),
1127 then_b, else_b));
1128
1129 tree srcptr = GFC_DESCRIPTOR_TYPE_P (type)
1130 ? gfc_conv_descriptor_data_get (src) : src;
1131 srcptr = unshare_expr (srcptr);
1132 srcptr = fold_convert (pvoid_type_node, srcptr);
1133 call = build_call_expr_loc (input_location,
1134 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr,
1135 srcptr, size);
1136 gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
1137 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
1138 {
1139 tree tem = gfc_walk_alloc_comps (src, dest,
1140 OMP_CLAUSE_DECL (clause),
1141 WALK_ALLOC_COMPS_COPY_CTOR);
1142 gfc_add_expr_to_block (&cond_block, tem);
1143 }
1144 then_b = gfc_finish_block (&cond_block);
1145
1146 if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_COPYIN)
1147 {
1148 gfc_init_block (&cond_block);
1149 if (GFC_DESCRIPTOR_TYPE_P (type))
1150 {
1151 tree tmp = gfc_conv_descriptor_data_get (unshare_expr (dest));
1152 tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE,
1153 NULL_TREE, NULL_TREE, true, NULL,
1154 GFC_CAF_COARRAY_NOCOARRAY);
1155 gfc_add_expr_to_block (&cond_block, tmp);
1156 }
1157 else
1158 {
1159 destptr = gfc_evaluate_now (destptr, &cond_block);
1160 gfc_add_expr_to_block (&cond_block, gfc_call_free (destptr));
1161 gfc_add_modify (&cond_block, unshare_expr (dest),
1162 build_zero_cst (TREE_TYPE (dest)));
1163 }
1164 else_b = gfc_finish_block (&cond_block);
1165
1166 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1167 unshare_expr (srcptr), null_pointer_node);
1168 gfc_add_expr_to_block (&block,
1169 build3_loc (input_location, COND_EXPR,
1170 void_type_node, cond,
1171 then_b, else_b));
1172 }
1173 else
1174 gfc_add_expr_to_block (&block, then_b);
1175
1176 return gfc_finish_block (&block);
1177 }
1178
1179 static void
gfc_omp_linear_clause_add_loop(stmtblock_t * block,tree dest,tree src,tree add,tree nelems)1180 gfc_omp_linear_clause_add_loop (stmtblock_t *block, tree dest, tree src,
1181 tree add, tree nelems)
1182 {
1183 stmtblock_t tmpblock;
1184 tree desta, srca, index = gfc_create_var (gfc_array_index_type, "S");
1185 nelems = gfc_evaluate_now (nelems, block);
1186
1187 gfc_init_block (&tmpblock);
1188 if (TREE_CODE (TREE_TYPE (dest)) == ARRAY_TYPE)
1189 {
1190 desta = gfc_build_array_ref (dest, index, NULL);
1191 srca = gfc_build_array_ref (src, index, NULL);
1192 }
1193 else
1194 {
1195 gcc_assert (POINTER_TYPE_P (TREE_TYPE (dest)));
1196 tree idx = fold_build2 (MULT_EXPR, sizetype,
1197 fold_convert (sizetype, index),
1198 TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (dest))));
1199 desta = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR,
1200 TREE_TYPE (dest), dest,
1201 idx));
1202 srca = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR,
1203 TREE_TYPE (src), src,
1204 idx));
1205 }
1206 gfc_add_modify (&tmpblock, desta,
1207 fold_build2 (PLUS_EXPR, TREE_TYPE (desta),
1208 srca, add));
1209
1210 gfc_loopinfo loop;
1211 gfc_init_loopinfo (&loop);
1212 loop.dimen = 1;
1213 loop.from[0] = gfc_index_zero_node;
1214 loop.loopvar[0] = index;
1215 loop.to[0] = nelems;
1216 gfc_trans_scalarizing_loops (&loop, &tmpblock);
1217 gfc_add_block_to_block (block, &loop.pre);
1218 }
1219
1220 /* Build and return code for a constructor of DEST that initializes
1221 it to SRC plus ADD (ADD is scalar integer). */
1222
1223 tree
gfc_omp_clause_linear_ctor(tree clause,tree dest,tree src,tree add)1224 gfc_omp_clause_linear_ctor (tree clause, tree dest, tree src, tree add)
1225 {
1226 tree type = TREE_TYPE (dest), ptr, size, nelems = NULL_TREE;
1227 stmtblock_t block;
1228
1229 gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
1230
1231 gfc_start_block (&block);
1232 add = gfc_evaluate_now (add, &block);
1233
1234 if ((! GFC_DESCRIPTOR_TYPE_P (type)
1235 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
1236 && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
1237 || !POINTER_TYPE_P (type)))
1238 {
1239 bool compute_nelts = false;
1240 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1241 if (!TYPE_DOMAIN (type)
1242 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE
1243 || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node
1244 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node)
1245 compute_nelts = true;
1246 else if (VAR_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
1247 {
1248 tree a = DECL_ATTRIBUTES (TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
1249 if (lookup_attribute ("omp dummy var", a))
1250 compute_nelts = true;
1251 }
1252 if (compute_nelts)
1253 {
1254 nelems = fold_build2 (EXACT_DIV_EXPR, sizetype,
1255 TYPE_SIZE_UNIT (type),
1256 TYPE_SIZE_UNIT (TREE_TYPE (type)));
1257 nelems = size_binop (MINUS_EXPR, nelems, size_one_node);
1258 }
1259 else
1260 nelems = array_type_nelts (type);
1261 nelems = fold_convert (gfc_array_index_type, nelems);
1262
1263 gfc_omp_linear_clause_add_loop (&block, dest, src, add, nelems);
1264 return gfc_finish_block (&block);
1265 }
1266
1267 /* Allocatable arrays in LINEAR clauses need to be allocated
1268 and copied from SRC. */
1269 gfc_add_modify (&block, dest, src);
1270 if (GFC_DESCRIPTOR_TYPE_P (type))
1271 {
1272 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
1273 size = gfc_conv_descriptor_ubound_get (dest, rank);
1274 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
1275 size,
1276 gfc_conv_descriptor_lbound_get (dest, rank));
1277 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1278 size, gfc_index_one_node);
1279 if (GFC_TYPE_ARRAY_RANK (type) > 1)
1280 size = fold_build2_loc (input_location, MULT_EXPR,
1281 gfc_array_index_type, size,
1282 gfc_conv_descriptor_stride_get (dest, rank));
1283 tree esize = fold_convert (gfc_array_index_type,
1284 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
1285 nelems = gfc_evaluate_now (unshare_expr (size), &block);
1286 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1287 nelems, unshare_expr (esize));
1288 size = gfc_evaluate_now (fold_convert (size_type_node, size),
1289 &block);
1290 nelems = fold_build2_loc (input_location, MINUS_EXPR,
1291 gfc_array_index_type, nelems,
1292 gfc_index_one_node);
1293 }
1294 else
1295 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
1296 ptr = gfc_create_var (pvoid_type_node, NULL);
1297 gfc_allocate_using_malloc (&block, ptr, size, NULL_TREE);
1298 if (GFC_DESCRIPTOR_TYPE_P (type))
1299 {
1300 gfc_conv_descriptor_data_set (&block, unshare_expr (dest), ptr);
1301 tree etype = gfc_get_element_type (type);
1302 ptr = fold_convert (build_pointer_type (etype), ptr);
1303 tree srcptr = gfc_conv_descriptor_data_get (unshare_expr (src));
1304 srcptr = fold_convert (build_pointer_type (etype), srcptr);
1305 gfc_omp_linear_clause_add_loop (&block, ptr, srcptr, add, nelems);
1306 }
1307 else
1308 {
1309 gfc_add_modify (&block, unshare_expr (dest),
1310 fold_convert (TREE_TYPE (dest), ptr));
1311 ptr = fold_convert (TREE_TYPE (dest), ptr);
1312 tree dstm = build_fold_indirect_ref (ptr);
1313 tree srcm = build_fold_indirect_ref (unshare_expr (src));
1314 gfc_add_modify (&block, dstm,
1315 fold_build2 (PLUS_EXPR, TREE_TYPE (add), srcm, add));
1316 }
1317 return gfc_finish_block (&block);
1318 }
1319
1320 /* Build and return code destructing DECL. Return NULL if nothing
1321 to be done. */
1322
1323 tree
gfc_omp_clause_dtor(tree clause,tree decl)1324 gfc_omp_clause_dtor (tree clause, tree decl)
1325 {
1326 tree type = TREE_TYPE (decl), tem;
1327 tree decl_type = TREE_TYPE (OMP_CLAUSE_DECL (clause));
1328
1329 /* Only pointer was privatized; cf. gfc_omp_clause_copy_ctor. */
1330 if (DECL_P (OMP_CLAUSE_DECL (clause))
1331 && GFC_DECL_ASSOCIATE_VAR_P (OMP_CLAUSE_DECL (clause)))
1332 return NULL_TREE;
1333
1334 if (DECL_ARTIFICIAL (OMP_CLAUSE_DECL (clause))
1335 && DECL_LANG_SPECIFIC (OMP_CLAUSE_DECL (clause))
1336 && GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause)))
1337 decl_type
1338 = TREE_TYPE (GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause)));
1339 if (gfc_is_polymorphic_nonptr (decl_type))
1340 {
1341 if (POINTER_TYPE_P (decl_type))
1342 decl_type = TREE_TYPE (decl_type);
1343 decl_type = TREE_TYPE (TYPE_FIELDS (decl_type));
1344 if (GFC_DESCRIPTOR_TYPE_P (decl_type) || GFC_ARRAY_TYPE_P (decl_type))
1345 fatal_error (input_location,
1346 "Sorry, polymorphic arrays not yet supported for "
1347 "firstprivate");
1348 stmtblock_t block, cond_block;
1349 gfc_start_block (&block);
1350 gfc_init_block (&cond_block);
1351 tree final = gfc_class_vtab_final_get (decl);
1352 tree size = fold_convert (size_type_node, gfc_class_vtab_size_get (decl));
1353 gfc_se se;
1354 gfc_init_se (&se, NULL);
1355 symbol_attribute attr = {};
1356 tree data = gfc_class_data_get (decl);
1357 tree desc = gfc_conv_scalar_to_descriptor (&se, data, attr);
1358
1359 /* Call class->_vpt->_finalize + free. */
1360 tree call = build_fold_indirect_ref (final);
1361 call = build_call_expr_loc (input_location, call, 3,
1362 gfc_build_addr_expr (NULL, desc),
1363 size, boolean_false_node);
1364 gfc_add_block_to_block (&cond_block, &se.pre);
1365 gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
1366 gfc_add_block_to_block (&cond_block, &se.post);
1367 /* Create: if (_vtab && _final) <cond_block> */
1368 tree cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1369 gfc_class_vptr_get (decl),
1370 null_pointer_node);
1371 tree cond2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1372 final, null_pointer_node);
1373 cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
1374 boolean_type_node, cond, cond2);
1375 gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR,
1376 void_type_node, cond,
1377 gfc_finish_block (&cond_block), NULL_TREE));
1378 call = builtin_decl_explicit (BUILT_IN_FREE);
1379 call = build_call_expr_loc (input_location, call, 1, data);
1380 gfc_add_expr_to_block (&block, fold_convert (void_type_node, call));
1381 return gfc_finish_block (&block);
1382 }
1383
1384 if ((! GFC_DESCRIPTOR_TYPE_P (type)
1385 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
1386 && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
1387 || !POINTER_TYPE_P (type)))
1388 {
1389 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
1390 return gfc_walk_alloc_comps (decl, NULL_TREE,
1391 OMP_CLAUSE_DECL (clause),
1392 WALK_ALLOC_COMPS_DTOR);
1393 return NULL_TREE;
1394 }
1395
1396 if (GFC_DESCRIPTOR_TYPE_P (type))
1397 {
1398 /* Allocatable arrays in FIRSTPRIVATE/LASTPRIVATE etc. clauses need
1399 to be deallocated if they were allocated. */
1400 tem = gfc_conv_descriptor_data_get (decl);
1401 tem = gfc_deallocate_with_status (tem, NULL_TREE, NULL_TREE, NULL_TREE,
1402 NULL_TREE, true, NULL,
1403 GFC_CAF_COARRAY_NOCOARRAY);
1404 }
1405 else
1406 tem = gfc_call_free (decl);
1407 tem = gfc_omp_unshare_expr (tem);
1408
1409 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
1410 {
1411 stmtblock_t block;
1412 tree then_b;
1413
1414 gfc_init_block (&block);
1415 gfc_add_expr_to_block (&block,
1416 gfc_walk_alloc_comps (decl, NULL_TREE,
1417 OMP_CLAUSE_DECL (clause),
1418 WALK_ALLOC_COMPS_DTOR));
1419 gfc_add_expr_to_block (&block, tem);
1420 then_b = gfc_finish_block (&block);
1421
1422 tem = fold_convert (pvoid_type_node,
1423 GFC_DESCRIPTOR_TYPE_P (type)
1424 ? gfc_conv_descriptor_data_get (decl) : decl);
1425 tem = unshare_expr (tem);
1426 tree cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1427 tem, null_pointer_node);
1428 tem = build3_loc (input_location, COND_EXPR, void_type_node, cond,
1429 then_b, build_empty_stmt (input_location));
1430 }
1431 return tem;
1432 }
1433
1434 /* Build a conditional expression in BLOCK. If COND_VAL is not
1435 null, then the block THEN_B is executed, otherwise ELSE_VAL
1436 is assigned to VAL. */
1437
1438 static void
gfc_build_cond_assign(stmtblock_t * block,tree val,tree cond_val,tree then_b,tree else_val)1439 gfc_build_cond_assign (stmtblock_t *block, tree val, tree cond_val,
1440 tree then_b, tree else_val)
1441 {
1442 stmtblock_t cond_block;
1443 tree else_b = NULL_TREE;
1444 tree val_ty = TREE_TYPE (val);
1445
1446 if (else_val)
1447 {
1448 gfc_init_block (&cond_block);
1449 gfc_add_modify (&cond_block, val, fold_convert (val_ty, else_val));
1450 else_b = gfc_finish_block (&cond_block);
1451 }
1452 gfc_add_expr_to_block (block,
1453 build3_loc (input_location, COND_EXPR, void_type_node,
1454 cond_val, then_b, else_b));
1455 }
1456
1457 /* Build a conditional expression in BLOCK, returning a temporary
1458 variable containing the result. If COND_VAL is not null, then
1459 THEN_VAL will be assigned to the variable, otherwise ELSE_VAL
1460 is assigned.
1461 */
1462
1463 static tree
gfc_build_cond_assign_expr(stmtblock_t * block,tree cond_val,tree then_val,tree else_val)1464 gfc_build_cond_assign_expr (stmtblock_t *block, tree cond_val,
1465 tree then_val, tree else_val)
1466 {
1467 tree val;
1468 tree val_ty = TREE_TYPE (then_val);
1469 stmtblock_t cond_block;
1470
1471 val = create_tmp_var (val_ty);
1472
1473 gfc_init_block (&cond_block);
1474 gfc_add_modify (&cond_block, val, then_val);
1475 tree then_b = gfc_finish_block (&cond_block);
1476
1477 gfc_build_cond_assign (block, val, cond_val, then_b, else_val);
1478
1479 return val;
1480 }
1481
1482 void
gfc_omp_finish_clause(tree c,gimple_seq * pre_p,bool openacc)1483 gfc_omp_finish_clause (tree c, gimple_seq *pre_p, bool openacc)
1484 {
1485 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
1486 return;
1487
1488 tree decl = OMP_CLAUSE_DECL (c);
1489
1490 /* Assumed-size arrays can't be mapped implicitly, they have to be
1491 mapped explicitly using array sections. */
1492 if (TREE_CODE (decl) == PARM_DECL
1493 && GFC_ARRAY_TYPE_P (TREE_TYPE (decl))
1494 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN
1495 && GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (decl),
1496 GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)) - 1)
1497 == NULL)
1498 {
1499 error_at (OMP_CLAUSE_LOCATION (c),
1500 "implicit mapping of assumed size array %qD", decl);
1501 return;
1502 }
1503
1504 tree c2 = NULL_TREE, c3 = NULL_TREE, c4 = NULL_TREE;
1505 tree present = gfc_omp_check_optional_argument (decl, true);
1506 if (POINTER_TYPE_P (TREE_TYPE (decl)))
1507 {
1508 if (!gfc_omp_privatize_by_reference (decl)
1509 && !GFC_DECL_GET_SCALAR_POINTER (decl)
1510 && !GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
1511 && !GFC_DECL_CRAY_POINTEE (decl)
1512 && !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
1513 return;
1514 tree orig_decl = decl;
1515
1516 c4 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
1517 OMP_CLAUSE_SET_MAP_KIND (c4, GOMP_MAP_POINTER);
1518 OMP_CLAUSE_DECL (c4) = decl;
1519 OMP_CLAUSE_SIZE (c4) = size_int (0);
1520 decl = build_fold_indirect_ref (decl);
1521 if (present
1522 && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
1523 || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
1524 {
1525 c2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
1526 OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER);
1527 OMP_CLAUSE_DECL (c2) = decl;
1528 OMP_CLAUSE_SIZE (c2) = size_int (0);
1529
1530 stmtblock_t block;
1531 gfc_start_block (&block);
1532 tree ptr = decl;
1533 ptr = gfc_build_cond_assign_expr (&block, present, decl,
1534 null_pointer_node);
1535 gimplify_and_add (gfc_finish_block (&block), pre_p);
1536 ptr = build_fold_indirect_ref (ptr);
1537 OMP_CLAUSE_DECL (c) = ptr;
1538 OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
1539 }
1540 else
1541 {
1542 OMP_CLAUSE_DECL (c) = decl;
1543 OMP_CLAUSE_SIZE (c) = NULL_TREE;
1544 }
1545 if (TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE
1546 && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
1547 || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
1548 {
1549 c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
1550 OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_POINTER);
1551 OMP_CLAUSE_DECL (c3) = unshare_expr (decl);
1552 OMP_CLAUSE_SIZE (c3) = size_int (0);
1553 decl = build_fold_indirect_ref (decl);
1554 OMP_CLAUSE_DECL (c) = decl;
1555 }
1556 }
1557 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
1558 {
1559 stmtblock_t block;
1560 gfc_start_block (&block);
1561 tree type = TREE_TYPE (decl);
1562 tree ptr = gfc_conv_descriptor_data_get (decl);
1563
1564 /* OpenMP: automatically map pointer targets with the pointer;
1565 hence, always update the descriptor/pointer itself.
1566 NOTE: This also remaps the pointer for allocatable arrays with
1567 'target' attribute which also don't have the 'restrict' qualifier. */
1568 bool always_modifier = false;
1569
1570 if (!openacc
1571 && !(TYPE_QUALS (TREE_TYPE (ptr)) & TYPE_QUAL_RESTRICT))
1572 always_modifier = true;
1573
1574 if (present)
1575 ptr = gfc_build_cond_assign_expr (&block, present, ptr,
1576 null_pointer_node);
1577 gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
1578 ptr = build_fold_indirect_ref (ptr);
1579 OMP_CLAUSE_DECL (c) = ptr;
1580 c2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
1581 OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_TO_PSET);
1582 if (present)
1583 {
1584 ptr = create_tmp_var (TREE_TYPE (TREE_OPERAND (decl, 0)));
1585 gfc_add_modify (&block, ptr, TREE_OPERAND (decl, 0));
1586
1587 OMP_CLAUSE_DECL (c2) = build_fold_indirect_ref (ptr);
1588 }
1589 else
1590 OMP_CLAUSE_DECL (c2) = decl;
1591 OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (type);
1592 c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
1593 OMP_CLAUSE_SET_MAP_KIND (c3, always_modifier ? GOMP_MAP_ALWAYS_POINTER
1594 : GOMP_MAP_POINTER);
1595 if (present)
1596 {
1597 ptr = gfc_conv_descriptor_data_get (decl);
1598 ptr = gfc_build_addr_expr (NULL, ptr);
1599 ptr = gfc_build_cond_assign_expr (&block, present,
1600 ptr, null_pointer_node);
1601 ptr = build_fold_indirect_ref (ptr);
1602 OMP_CLAUSE_DECL (c3) = ptr;
1603 }
1604 else
1605 OMP_CLAUSE_DECL (c3) = gfc_conv_descriptor_data_get (decl);
1606 OMP_CLAUSE_SIZE (c3) = size_int (0);
1607 tree size = create_tmp_var (gfc_array_index_type);
1608 tree elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
1609 elemsz = fold_convert (gfc_array_index_type, elemsz);
1610 if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
1611 || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER
1612 || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT)
1613 {
1614 stmtblock_t cond_block;
1615 tree tem, then_b, else_b, zero, cond;
1616
1617 gfc_init_block (&cond_block);
1618 tem = gfc_full_array_size (&cond_block, decl,
1619 GFC_TYPE_ARRAY_RANK (type));
1620 gfc_add_modify (&cond_block, size, tem);
1621 gfc_add_modify (&cond_block, size,
1622 fold_build2 (MULT_EXPR, gfc_array_index_type,
1623 size, elemsz));
1624 then_b = gfc_finish_block (&cond_block);
1625 gfc_init_block (&cond_block);
1626 zero = build_int_cst (gfc_array_index_type, 0);
1627 gfc_add_modify (&cond_block, size, zero);
1628 else_b = gfc_finish_block (&cond_block);
1629 tem = gfc_conv_descriptor_data_get (decl);
1630 tem = fold_convert (pvoid_type_node, tem);
1631 cond = fold_build2_loc (input_location, NE_EXPR,
1632 boolean_type_node, tem, null_pointer_node);
1633 if (present)
1634 {
1635 cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
1636 boolean_type_node, present, cond);
1637 }
1638 gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR,
1639 void_type_node, cond,
1640 then_b, else_b));
1641 }
1642 else if (present)
1643 {
1644 stmtblock_t cond_block;
1645 tree then_b;
1646
1647 gfc_init_block (&cond_block);
1648 gfc_add_modify (&cond_block, size,
1649 gfc_full_array_size (&cond_block, decl,
1650 GFC_TYPE_ARRAY_RANK (type)));
1651 gfc_add_modify (&cond_block, size,
1652 fold_build2 (MULT_EXPR, gfc_array_index_type,
1653 size, elemsz));
1654 then_b = gfc_finish_block (&cond_block);
1655
1656 gfc_build_cond_assign (&block, size, present, then_b,
1657 build_int_cst (gfc_array_index_type, 0));
1658 }
1659 else
1660 {
1661 gfc_add_modify (&block, size,
1662 gfc_full_array_size (&block, decl,
1663 GFC_TYPE_ARRAY_RANK (type)));
1664 gfc_add_modify (&block, size,
1665 fold_build2 (MULT_EXPR, gfc_array_index_type,
1666 size, elemsz));
1667 }
1668 OMP_CLAUSE_SIZE (c) = size;
1669 tree stmt = gfc_finish_block (&block);
1670 gimplify_and_add (stmt, pre_p);
1671 }
1672 tree last = c;
1673 if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
1674 OMP_CLAUSE_SIZE (c)
1675 = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
1676 : TYPE_SIZE_UNIT (TREE_TYPE (decl));
1677 if (gimplify_expr (&OMP_CLAUSE_SIZE (c), pre_p,
1678 NULL, is_gimple_val, fb_rvalue) == GS_ERROR)
1679 OMP_CLAUSE_SIZE (c) = size_int (0);
1680 if (c2)
1681 {
1682 OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (last);
1683 OMP_CLAUSE_CHAIN (last) = c2;
1684 last = c2;
1685 }
1686 if (c3)
1687 {
1688 OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (last);
1689 OMP_CLAUSE_CHAIN (last) = c3;
1690 last = c3;
1691 }
1692 if (c4)
1693 {
1694 OMP_CLAUSE_CHAIN (c4) = OMP_CLAUSE_CHAIN (last);
1695 OMP_CLAUSE_CHAIN (last) = c4;
1696 }
1697 }
1698
1699
1700 /* Return true if DECL is a scalar variable (for the purpose of
1701 implicit firstprivatization/mapping). Only if 'ptr_alloc_ok.'
1702 is true, allocatables and pointers are permitted. */
1703
1704 bool
gfc_omp_scalar_p(tree decl,bool ptr_alloc_ok)1705 gfc_omp_scalar_p (tree decl, bool ptr_alloc_ok)
1706 {
1707 tree type = TREE_TYPE (decl);
1708 if (TREE_CODE (type) == REFERENCE_TYPE)
1709 type = TREE_TYPE (type);
1710 if (TREE_CODE (type) == POINTER_TYPE)
1711 {
1712 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
1713 || GFC_DECL_GET_SCALAR_POINTER (decl))
1714 {
1715 if (!ptr_alloc_ok)
1716 return false;
1717 type = TREE_TYPE (type);
1718 }
1719 if (GFC_ARRAY_TYPE_P (type)
1720 || GFC_CLASS_TYPE_P (type))
1721 return false;
1722 }
1723 if ((TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == INTEGER_TYPE)
1724 && TYPE_STRING_FLAG (type))
1725 return false;
1726 if (INTEGRAL_TYPE_P (type)
1727 || SCALAR_FLOAT_TYPE_P (type)
1728 || COMPLEX_FLOAT_TYPE_P (type))
1729 return true;
1730 return false;
1731 }
1732
1733
1734 /* Return true if DECL is a scalar with target attribute but does not have the
1735 allocatable (or pointer) attribute (for the purpose of implicit mapping). */
1736
1737 bool
gfc_omp_scalar_target_p(tree decl)1738 gfc_omp_scalar_target_p (tree decl)
1739 {
1740 return (DECL_P (decl) && GFC_DECL_GET_SCALAR_TARGET (decl)
1741 && gfc_omp_scalar_p (decl, false));
1742 }
1743
1744
1745 /* Return true if DECL's DECL_VALUE_EXPR (if any) should be
1746 disregarded in OpenMP construct, because it is going to be
1747 remapped during OpenMP lowering. SHARED is true if DECL
1748 is going to be shared, false if it is going to be privatized. */
1749
1750 bool
gfc_omp_disregard_value_expr(tree decl,bool shared)1751 gfc_omp_disregard_value_expr (tree decl, bool shared)
1752 {
1753 if (GFC_DECL_COMMON_OR_EQUIV (decl)
1754 && DECL_HAS_VALUE_EXPR_P (decl))
1755 {
1756 tree value = DECL_VALUE_EXPR (decl);
1757
1758 if (TREE_CODE (value) == COMPONENT_REF
1759 && VAR_P (TREE_OPERAND (value, 0))
1760 && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
1761 {
1762 /* If variable in COMMON or EQUIVALENCE is privatized, return
1763 true, as just that variable is supposed to be privatized,
1764 not the whole COMMON or whole EQUIVALENCE.
1765 For shared variables in COMMON or EQUIVALENCE, let them be
1766 gimplified to DECL_VALUE_EXPR, so that for multiple shared vars
1767 from the same COMMON or EQUIVALENCE just one sharing of the
1768 whole COMMON or EQUIVALENCE is enough. */
1769 return ! shared;
1770 }
1771 }
1772
1773 if (GFC_DECL_RESULT (decl) && DECL_HAS_VALUE_EXPR_P (decl))
1774 return ! shared;
1775
1776 return false;
1777 }
1778
1779 /* Return true if DECL that is shared iff SHARED is true should
1780 be put into OMP_CLAUSE_PRIVATE with OMP_CLAUSE_PRIVATE_DEBUG
1781 flag set. */
1782
1783 bool
gfc_omp_private_debug_clause(tree decl,bool shared)1784 gfc_omp_private_debug_clause (tree decl, bool shared)
1785 {
1786 if (GFC_DECL_CRAY_POINTEE (decl))
1787 return true;
1788
1789 if (GFC_DECL_COMMON_OR_EQUIV (decl)
1790 && DECL_HAS_VALUE_EXPR_P (decl))
1791 {
1792 tree value = DECL_VALUE_EXPR (decl);
1793
1794 if (TREE_CODE (value) == COMPONENT_REF
1795 && VAR_P (TREE_OPERAND (value, 0))
1796 && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
1797 return shared;
1798 }
1799
1800 return false;
1801 }
1802
1803 /* Register language specific type size variables as potentially OpenMP
1804 firstprivate variables. */
1805
1806 void
gfc_omp_firstprivatize_type_sizes(struct gimplify_omp_ctx * ctx,tree type)1807 gfc_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
1808 {
1809 if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
1810 {
1811 int r;
1812
1813 gcc_assert (TYPE_LANG_SPECIFIC (type) != NULL);
1814 for (r = 0; r < GFC_TYPE_ARRAY_RANK (type); r++)
1815 {
1816 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_LBOUND (type, r));
1817 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_UBOUND (type, r));
1818 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_STRIDE (type, r));
1819 }
1820 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_SIZE (type));
1821 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_OFFSET (type));
1822 }
1823 }
1824
1825
1826 static inline tree
gfc_trans_add_clause(tree node,tree tail)1827 gfc_trans_add_clause (tree node, tree tail)
1828 {
1829 OMP_CLAUSE_CHAIN (node) = tail;
1830 return node;
1831 }
1832
1833 static tree
gfc_trans_omp_variable(gfc_symbol * sym,bool declare_simd)1834 gfc_trans_omp_variable (gfc_symbol *sym, bool declare_simd)
1835 {
1836 if (declare_simd)
1837 {
1838 int cnt = 0;
1839 gfc_symbol *proc_sym;
1840 gfc_formal_arglist *f;
1841
1842 gcc_assert (sym->attr.dummy);
1843 proc_sym = sym->ns->proc_name;
1844 if (proc_sym->attr.entry_master)
1845 ++cnt;
1846 if (gfc_return_by_reference (proc_sym))
1847 {
1848 ++cnt;
1849 if (proc_sym->ts.type == BT_CHARACTER)
1850 ++cnt;
1851 }
1852 for (f = gfc_sym_get_dummy_args (proc_sym); f; f = f->next)
1853 if (f->sym == sym)
1854 break;
1855 else if (f->sym)
1856 ++cnt;
1857 gcc_assert (f);
1858 return build_int_cst (integer_type_node, cnt);
1859 }
1860
1861 tree t = gfc_get_symbol_decl (sym);
1862 tree parent_decl;
1863 int parent_flag;
1864 bool return_value;
1865 bool alternate_entry;
1866 bool entry_master;
1867
1868 return_value = sym->attr.function && sym->result == sym;
1869 alternate_entry = sym->attr.function && sym->attr.entry
1870 && sym->result == sym;
1871 entry_master = sym->attr.result
1872 && sym->ns->proc_name->attr.entry_master
1873 && !gfc_return_by_reference (sym->ns->proc_name);
1874 parent_decl = current_function_decl
1875 ? DECL_CONTEXT (current_function_decl) : NULL_TREE;
1876
1877 if ((t == parent_decl && return_value)
1878 || (sym->ns && sym->ns->proc_name
1879 && sym->ns->proc_name->backend_decl == parent_decl
1880 && (alternate_entry || entry_master)))
1881 parent_flag = 1;
1882 else
1883 parent_flag = 0;
1884
1885 /* Special case for assigning the return value of a function.
1886 Self recursive functions must have an explicit return value. */
1887 if (return_value && (t == current_function_decl || parent_flag))
1888 t = gfc_get_fake_result_decl (sym, parent_flag);
1889
1890 /* Similarly for alternate entry points. */
1891 else if (alternate_entry
1892 && (sym->ns->proc_name->backend_decl == current_function_decl
1893 || parent_flag))
1894 {
1895 gfc_entry_list *el = NULL;
1896
1897 for (el = sym->ns->entries; el; el = el->next)
1898 if (sym == el->sym)
1899 {
1900 t = gfc_get_fake_result_decl (sym, parent_flag);
1901 break;
1902 }
1903 }
1904
1905 else if (entry_master
1906 && (sym->ns->proc_name->backend_decl == current_function_decl
1907 || parent_flag))
1908 t = gfc_get_fake_result_decl (sym, parent_flag);
1909
1910 return t;
1911 }
1912
1913 static tree
gfc_trans_omp_variable_list(enum omp_clause_code code,gfc_omp_namelist * namelist,tree list,bool declare_simd)1914 gfc_trans_omp_variable_list (enum omp_clause_code code,
1915 gfc_omp_namelist *namelist, tree list,
1916 bool declare_simd)
1917 {
1918 for (; namelist != NULL; namelist = namelist->next)
1919 if (namelist->sym->attr.referenced || declare_simd)
1920 {
1921 tree t = gfc_trans_omp_variable (namelist->sym, declare_simd);
1922 if (t != error_mark_node)
1923 {
1924 tree node;
1925 /* For HAS_DEVICE_ADDR of an array descriptor, firstprivatize the
1926 descriptor such that the bounds are available; its data component
1927 is unmodified; it is handled as device address inside target. */
1928 if (code == OMP_CLAUSE_HAS_DEVICE_ADDR
1929 && (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (t))
1930 || (POINTER_TYPE_P (TREE_TYPE (t))
1931 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (t))))))
1932 node = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE);
1933 else
1934 node = build_omp_clause (input_location, code);
1935 OMP_CLAUSE_DECL (node) = t;
1936 list = gfc_trans_add_clause (node, list);
1937
1938 if (code == OMP_CLAUSE_LASTPRIVATE
1939 && namelist->u.lastprivate_conditional)
1940 OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (node) = 1;
1941 }
1942 }
1943 return list;
1944 }
1945
1946 struct omp_udr_find_orig_data
1947 {
1948 gfc_omp_udr *omp_udr;
1949 bool omp_orig_seen;
1950 };
1951
1952 static int
omp_udr_find_orig(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * data)1953 omp_udr_find_orig (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
1954 void *data)
1955 {
1956 struct omp_udr_find_orig_data *cd = (struct omp_udr_find_orig_data *) data;
1957 if ((*e)->expr_type == EXPR_VARIABLE
1958 && (*e)->symtree->n.sym == cd->omp_udr->omp_orig)
1959 cd->omp_orig_seen = true;
1960
1961 return 0;
1962 }
1963
1964 static void
gfc_trans_omp_array_reduction_or_udr(tree c,gfc_omp_namelist * n,locus where)1965 gfc_trans_omp_array_reduction_or_udr (tree c, gfc_omp_namelist *n, locus where)
1966 {
1967 gfc_symbol *sym = n->sym;
1968 gfc_symtree *root1 = NULL, *root2 = NULL, *root3 = NULL, *root4 = NULL;
1969 gfc_symtree *symtree1, *symtree2, *symtree3, *symtree4 = NULL;
1970 gfc_symbol init_val_sym, outer_sym, intrinsic_sym;
1971 gfc_symbol omp_var_copy[4];
1972 gfc_expr *e1, *e2, *e3, *e4;
1973 gfc_ref *ref;
1974 tree decl, backend_decl, stmt, type, outer_decl;
1975 locus old_loc = gfc_current_locus;
1976 const char *iname;
1977 bool t;
1978 gfc_omp_udr *udr = n->u2.udr ? n->u2.udr->udr : NULL;
1979
1980 decl = OMP_CLAUSE_DECL (c);
1981 gfc_current_locus = where;
1982 type = TREE_TYPE (decl);
1983 outer_decl = create_tmp_var_raw (type);
1984 if (TREE_CODE (decl) == PARM_DECL
1985 && TREE_CODE (type) == REFERENCE_TYPE
1986 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type))
1987 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (type)) == GFC_ARRAY_ALLOCATABLE)
1988 {
1989 decl = build_fold_indirect_ref (decl);
1990 type = TREE_TYPE (type);
1991 }
1992
1993 /* Create a fake symbol for init value. */
1994 memset (&init_val_sym, 0, sizeof (init_val_sym));
1995 init_val_sym.ns = sym->ns;
1996 init_val_sym.name = sym->name;
1997 init_val_sym.ts = sym->ts;
1998 init_val_sym.attr.referenced = 1;
1999 init_val_sym.declared_at = where;
2000 init_val_sym.attr.flavor = FL_VARIABLE;
2001 if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK)
2002 backend_decl = omp_reduction_init (c, gfc_sym_type (&init_val_sym));
2003 else if (udr->initializer_ns)
2004 backend_decl = NULL;
2005 else
2006 switch (sym->ts.type)
2007 {
2008 case BT_LOGICAL:
2009 case BT_INTEGER:
2010 case BT_REAL:
2011 case BT_COMPLEX:
2012 backend_decl = build_zero_cst (gfc_sym_type (&init_val_sym));
2013 break;
2014 default:
2015 backend_decl = NULL_TREE;
2016 break;
2017 }
2018 init_val_sym.backend_decl = backend_decl;
2019
2020 /* Create a fake symbol for the outer array reference. */
2021 outer_sym = *sym;
2022 if (sym->as)
2023 outer_sym.as = gfc_copy_array_spec (sym->as);
2024 outer_sym.attr.dummy = 0;
2025 outer_sym.attr.result = 0;
2026 outer_sym.attr.flavor = FL_VARIABLE;
2027 outer_sym.backend_decl = outer_decl;
2028 if (decl != OMP_CLAUSE_DECL (c))
2029 outer_sym.backend_decl = build_fold_indirect_ref (outer_decl);
2030
2031 /* Create fake symtrees for it. */
2032 symtree1 = gfc_new_symtree (&root1, sym->name);
2033 symtree1->n.sym = sym;
2034 gcc_assert (symtree1 == root1);
2035
2036 symtree2 = gfc_new_symtree (&root2, sym->name);
2037 symtree2->n.sym = &init_val_sym;
2038 gcc_assert (symtree2 == root2);
2039
2040 symtree3 = gfc_new_symtree (&root3, sym->name);
2041 symtree3->n.sym = &outer_sym;
2042 gcc_assert (symtree3 == root3);
2043
2044 memset (omp_var_copy, 0, sizeof omp_var_copy);
2045 if (udr)
2046 {
2047 omp_var_copy[0] = *udr->omp_out;
2048 omp_var_copy[1] = *udr->omp_in;
2049 *udr->omp_out = outer_sym;
2050 *udr->omp_in = *sym;
2051 if (udr->initializer_ns)
2052 {
2053 omp_var_copy[2] = *udr->omp_priv;
2054 omp_var_copy[3] = *udr->omp_orig;
2055 *udr->omp_priv = *sym;
2056 *udr->omp_orig = outer_sym;
2057 }
2058 }
2059
2060 /* Create expressions. */
2061 e1 = gfc_get_expr ();
2062 e1->expr_type = EXPR_VARIABLE;
2063 e1->where = where;
2064 e1->symtree = symtree1;
2065 e1->ts = sym->ts;
2066 if (sym->attr.dimension)
2067 {
2068 e1->ref = ref = gfc_get_ref ();
2069 ref->type = REF_ARRAY;
2070 ref->u.ar.where = where;
2071 ref->u.ar.as = sym->as;
2072 ref->u.ar.type = AR_FULL;
2073 ref->u.ar.dimen = 0;
2074 }
2075 t = gfc_resolve_expr (e1);
2076 gcc_assert (t);
2077
2078 e2 = NULL;
2079 if (backend_decl != NULL_TREE)
2080 {
2081 e2 = gfc_get_expr ();
2082 e2->expr_type = EXPR_VARIABLE;
2083 e2->where = where;
2084 e2->symtree = symtree2;
2085 e2->ts = sym->ts;
2086 t = gfc_resolve_expr (e2);
2087 gcc_assert (t);
2088 }
2089 else if (udr->initializer_ns == NULL)
2090 {
2091 gcc_assert (sym->ts.type == BT_DERIVED);
2092 e2 = gfc_default_initializer (&sym->ts);
2093 gcc_assert (e2);
2094 t = gfc_resolve_expr (e2);
2095 gcc_assert (t);
2096 }
2097 else if (n->u2.udr->initializer->op == EXEC_ASSIGN)
2098 {
2099 e2 = gfc_copy_expr (n->u2.udr->initializer->expr2);
2100 t = gfc_resolve_expr (e2);
2101 gcc_assert (t);
2102 }
2103 if (udr && udr->initializer_ns)
2104 {
2105 struct omp_udr_find_orig_data cd;
2106 cd.omp_udr = udr;
2107 cd.omp_orig_seen = false;
2108 gfc_code_walker (&n->u2.udr->initializer,
2109 gfc_dummy_code_callback, omp_udr_find_orig, &cd);
2110 if (cd.omp_orig_seen)
2111 OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c) = 1;
2112 }
2113
2114 e3 = gfc_copy_expr (e1);
2115 e3->symtree = symtree3;
2116 t = gfc_resolve_expr (e3);
2117 gcc_assert (t);
2118
2119 iname = NULL;
2120 e4 = NULL;
2121 switch (OMP_CLAUSE_REDUCTION_CODE (c))
2122 {
2123 case PLUS_EXPR:
2124 case MINUS_EXPR:
2125 e4 = gfc_add (e3, e1);
2126 break;
2127 case MULT_EXPR:
2128 e4 = gfc_multiply (e3, e1);
2129 break;
2130 case TRUTH_ANDIF_EXPR:
2131 e4 = gfc_and (e3, e1);
2132 break;
2133 case TRUTH_ORIF_EXPR:
2134 e4 = gfc_or (e3, e1);
2135 break;
2136 case EQ_EXPR:
2137 e4 = gfc_eqv (e3, e1);
2138 break;
2139 case NE_EXPR:
2140 e4 = gfc_neqv (e3, e1);
2141 break;
2142 case MIN_EXPR:
2143 iname = "min";
2144 break;
2145 case MAX_EXPR:
2146 iname = "max";
2147 break;
2148 case BIT_AND_EXPR:
2149 iname = "iand";
2150 break;
2151 case BIT_IOR_EXPR:
2152 iname = "ior";
2153 break;
2154 case BIT_XOR_EXPR:
2155 iname = "ieor";
2156 break;
2157 case ERROR_MARK:
2158 if (n->u2.udr->combiner->op == EXEC_ASSIGN)
2159 {
2160 gfc_free_expr (e3);
2161 e3 = gfc_copy_expr (n->u2.udr->combiner->expr1);
2162 e4 = gfc_copy_expr (n->u2.udr->combiner->expr2);
2163 t = gfc_resolve_expr (e3);
2164 gcc_assert (t);
2165 t = gfc_resolve_expr (e4);
2166 gcc_assert (t);
2167 }
2168 break;
2169 default:
2170 gcc_unreachable ();
2171 }
2172 if (iname != NULL)
2173 {
2174 memset (&intrinsic_sym, 0, sizeof (intrinsic_sym));
2175 intrinsic_sym.ns = sym->ns;
2176 intrinsic_sym.name = iname;
2177 intrinsic_sym.ts = sym->ts;
2178 intrinsic_sym.attr.referenced = 1;
2179 intrinsic_sym.attr.intrinsic = 1;
2180 intrinsic_sym.attr.function = 1;
2181 intrinsic_sym.attr.implicit_type = 1;
2182 intrinsic_sym.result = &intrinsic_sym;
2183 intrinsic_sym.declared_at = where;
2184
2185 symtree4 = gfc_new_symtree (&root4, iname);
2186 symtree4->n.sym = &intrinsic_sym;
2187 gcc_assert (symtree4 == root4);
2188
2189 e4 = gfc_get_expr ();
2190 e4->expr_type = EXPR_FUNCTION;
2191 e4->where = where;
2192 e4->symtree = symtree4;
2193 e4->value.function.actual = gfc_get_actual_arglist ();
2194 e4->value.function.actual->expr = e3;
2195 e4->value.function.actual->next = gfc_get_actual_arglist ();
2196 e4->value.function.actual->next->expr = e1;
2197 }
2198 if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK)
2199 {
2200 /* e1 and e3 have been stored as arguments of e4, avoid sharing. */
2201 e1 = gfc_copy_expr (e1);
2202 e3 = gfc_copy_expr (e3);
2203 t = gfc_resolve_expr (e4);
2204 gcc_assert (t);
2205 }
2206
2207 /* Create the init statement list. */
2208 pushlevel ();
2209 if (e2)
2210 stmt = gfc_trans_assignment (e1, e2, false, false);
2211 else
2212 stmt = gfc_trans_call (n->u2.udr->initializer, false,
2213 NULL_TREE, NULL_TREE, false);
2214 if (TREE_CODE (stmt) != BIND_EXPR)
2215 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
2216 else
2217 poplevel (0, 0);
2218 OMP_CLAUSE_REDUCTION_INIT (c) = stmt;
2219
2220 /* Create the merge statement list. */
2221 pushlevel ();
2222 if (e4)
2223 stmt = gfc_trans_assignment (e3, e4, false, true);
2224 else
2225 stmt = gfc_trans_call (n->u2.udr->combiner, false,
2226 NULL_TREE, NULL_TREE, false);
2227 if (TREE_CODE (stmt) != BIND_EXPR)
2228 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
2229 else
2230 poplevel (0, 0);
2231 OMP_CLAUSE_REDUCTION_MERGE (c) = stmt;
2232
2233 /* And stick the placeholder VAR_DECL into the clause as well. */
2234 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = outer_decl;
2235
2236 gfc_current_locus = old_loc;
2237
2238 gfc_free_expr (e1);
2239 if (e2)
2240 gfc_free_expr (e2);
2241 gfc_free_expr (e3);
2242 if (e4)
2243 gfc_free_expr (e4);
2244 free (symtree1);
2245 free (symtree2);
2246 free (symtree3);
2247 free (symtree4);
2248 if (outer_sym.as)
2249 gfc_free_array_spec (outer_sym.as);
2250
2251 if (udr)
2252 {
2253 *udr->omp_out = omp_var_copy[0];
2254 *udr->omp_in = omp_var_copy[1];
2255 if (udr->initializer_ns)
2256 {
2257 *udr->omp_priv = omp_var_copy[2];
2258 *udr->omp_orig = omp_var_copy[3];
2259 }
2260 }
2261 }
2262
2263 static tree
gfc_trans_omp_reduction_list(int kind,gfc_omp_namelist * namelist,tree list,locus where,bool mark_addressable)2264 gfc_trans_omp_reduction_list (int kind, gfc_omp_namelist *namelist, tree list,
2265 locus where, bool mark_addressable)
2266 {
2267 omp_clause_code clause = OMP_CLAUSE_REDUCTION;
2268 switch (kind)
2269 {
2270 case OMP_LIST_REDUCTION:
2271 case OMP_LIST_REDUCTION_INSCAN:
2272 case OMP_LIST_REDUCTION_TASK:
2273 break;
2274 case OMP_LIST_IN_REDUCTION:
2275 clause = OMP_CLAUSE_IN_REDUCTION;
2276 break;
2277 case OMP_LIST_TASK_REDUCTION:
2278 clause = OMP_CLAUSE_TASK_REDUCTION;
2279 break;
2280 default:
2281 gcc_unreachable ();
2282 }
2283 for (; namelist != NULL; namelist = namelist->next)
2284 if (namelist->sym->attr.referenced)
2285 {
2286 tree t = gfc_trans_omp_variable (namelist->sym, false);
2287 if (t != error_mark_node)
2288 {
2289 tree node = build_omp_clause (gfc_get_location (&namelist->where),
2290 clause);
2291 OMP_CLAUSE_DECL (node) = t;
2292 if (mark_addressable)
2293 TREE_ADDRESSABLE (t) = 1;
2294 if (kind == OMP_LIST_REDUCTION_INSCAN)
2295 OMP_CLAUSE_REDUCTION_INSCAN (node) = 1;
2296 if (kind == OMP_LIST_REDUCTION_TASK)
2297 OMP_CLAUSE_REDUCTION_TASK (node) = 1;
2298 switch (namelist->u.reduction_op)
2299 {
2300 case OMP_REDUCTION_PLUS:
2301 OMP_CLAUSE_REDUCTION_CODE (node) = PLUS_EXPR;
2302 break;
2303 case OMP_REDUCTION_MINUS:
2304 OMP_CLAUSE_REDUCTION_CODE (node) = MINUS_EXPR;
2305 break;
2306 case OMP_REDUCTION_TIMES:
2307 OMP_CLAUSE_REDUCTION_CODE (node) = MULT_EXPR;
2308 break;
2309 case OMP_REDUCTION_AND:
2310 OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ANDIF_EXPR;
2311 break;
2312 case OMP_REDUCTION_OR:
2313 OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ORIF_EXPR;
2314 break;
2315 case OMP_REDUCTION_EQV:
2316 OMP_CLAUSE_REDUCTION_CODE (node) = EQ_EXPR;
2317 break;
2318 case OMP_REDUCTION_NEQV:
2319 OMP_CLAUSE_REDUCTION_CODE (node) = NE_EXPR;
2320 break;
2321 case OMP_REDUCTION_MAX:
2322 OMP_CLAUSE_REDUCTION_CODE (node) = MAX_EXPR;
2323 break;
2324 case OMP_REDUCTION_MIN:
2325 OMP_CLAUSE_REDUCTION_CODE (node) = MIN_EXPR;
2326 break;
2327 case OMP_REDUCTION_IAND:
2328 OMP_CLAUSE_REDUCTION_CODE (node) = BIT_AND_EXPR;
2329 break;
2330 case OMP_REDUCTION_IOR:
2331 OMP_CLAUSE_REDUCTION_CODE (node) = BIT_IOR_EXPR;
2332 break;
2333 case OMP_REDUCTION_IEOR:
2334 OMP_CLAUSE_REDUCTION_CODE (node) = BIT_XOR_EXPR;
2335 break;
2336 case OMP_REDUCTION_USER:
2337 OMP_CLAUSE_REDUCTION_CODE (node) = ERROR_MARK;
2338 break;
2339 default:
2340 gcc_unreachable ();
2341 }
2342 if (namelist->sym->attr.dimension
2343 || namelist->u.reduction_op == OMP_REDUCTION_USER
2344 || namelist->sym->attr.allocatable)
2345 gfc_trans_omp_array_reduction_or_udr (node, namelist, where);
2346 list = gfc_trans_add_clause (node, list);
2347 }
2348 }
2349 return list;
2350 }
2351
2352 static inline tree
gfc_convert_expr_to_tree(stmtblock_t * block,gfc_expr * expr)2353 gfc_convert_expr_to_tree (stmtblock_t *block, gfc_expr *expr)
2354 {
2355 gfc_se se;
2356 tree result;
2357
2358 gfc_init_se (&se, NULL );
2359 gfc_conv_expr (&se, expr);
2360 gfc_add_block_to_block (block, &se.pre);
2361 result = gfc_evaluate_now (se.expr, block);
2362 gfc_add_block_to_block (block, &se.post);
2363
2364 return result;
2365 }
2366
2367 static vec<tree, va_heap, vl_embed> *doacross_steps;
2368
2369
2370 /* Translate an array section or array element. */
2371
2372 static void
gfc_trans_omp_array_section(stmtblock_t * block,gfc_omp_namelist * n,tree decl,bool element,gomp_map_kind ptr_kind,tree & node,tree & node2,tree & node3,tree & node4)2373 gfc_trans_omp_array_section (stmtblock_t *block, gfc_omp_namelist *n,
2374 tree decl, bool element, gomp_map_kind ptr_kind,
2375 tree &node, tree &node2, tree &node3, tree &node4)
2376 {
2377 gfc_se se;
2378 tree ptr, ptr2;
2379 tree elemsz = NULL_TREE;
2380
2381 gfc_init_se (&se, NULL);
2382
2383 if (element)
2384 {
2385 gfc_conv_expr_reference (&se, n->expr);
2386 gfc_add_block_to_block (block, &se.pre);
2387 ptr = se.expr;
2388 OMP_CLAUSE_SIZE (node) = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ptr)));
2389 elemsz = OMP_CLAUSE_SIZE (node);
2390 }
2391 else
2392 {
2393 gfc_conv_expr_descriptor (&se, n->expr);
2394 ptr = gfc_conv_array_data (se.expr);
2395 tree type = TREE_TYPE (se.expr);
2396 gfc_add_block_to_block (block, &se.pre);
2397 OMP_CLAUSE_SIZE (node) = gfc_full_array_size (block, se.expr,
2398 GFC_TYPE_ARRAY_RANK (type));
2399 elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
2400 elemsz = fold_convert (gfc_array_index_type, elemsz);
2401 OMP_CLAUSE_SIZE (node) = fold_build2 (MULT_EXPR, gfc_array_index_type,
2402 OMP_CLAUSE_SIZE (node), elemsz);
2403 }
2404 gcc_assert (se.post.head == NULL_TREE);
2405 gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
2406 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
2407 ptr = fold_convert (ptrdiff_type_node, ptr);
2408
2409 if (POINTER_TYPE_P (TREE_TYPE (decl))
2410 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
2411 && ptr_kind == GOMP_MAP_POINTER)
2412 {
2413 node4 = build_omp_clause (input_location,
2414 OMP_CLAUSE_MAP);
2415 OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER);
2416 OMP_CLAUSE_DECL (node4) = decl;
2417 OMP_CLAUSE_SIZE (node4) = size_int (0);
2418 decl = build_fold_indirect_ref (decl);
2419 }
2420 else if (ptr_kind == GOMP_MAP_ALWAYS_POINTER
2421 && n->expr->ts.type == BT_CHARACTER
2422 && n->expr->ts.deferred)
2423 {
2424 gomp_map_kind map_kind;
2425 if (GOMP_MAP_COPY_TO_P (OMP_CLAUSE_MAP_KIND (node)))
2426 map_kind = GOMP_MAP_TO;
2427 else if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_RELEASE
2428 || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DELETE)
2429 map_kind = OMP_CLAUSE_MAP_KIND (node);
2430 else
2431 map_kind = GOMP_MAP_ALLOC;
2432 gcc_assert (se.string_length);
2433 node4 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
2434 OMP_CLAUSE_SET_MAP_KIND (node4, map_kind);
2435 OMP_CLAUSE_DECL (node4) = se.string_length;
2436 OMP_CLAUSE_SIZE (node4) = TYPE_SIZE_UNIT (gfc_charlen_type_node);
2437 }
2438 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
2439 {
2440 tree desc_node;
2441 tree type = TREE_TYPE (decl);
2442 ptr2 = gfc_conv_descriptor_data_get (decl);
2443 desc_node = build_omp_clause (input_location, OMP_CLAUSE_MAP);
2444 OMP_CLAUSE_DECL (desc_node) = decl;
2445 OMP_CLAUSE_SIZE (desc_node) = TYPE_SIZE_UNIT (type);
2446 if (ptr_kind == GOMP_MAP_ALWAYS_POINTER)
2447 {
2448 OMP_CLAUSE_SET_MAP_KIND (desc_node, GOMP_MAP_TO);
2449 node2 = node;
2450 node = desc_node; /* Needs to come first. */
2451 }
2452 else
2453 {
2454 OMP_CLAUSE_SET_MAP_KIND (desc_node, GOMP_MAP_TO_PSET);
2455 node2 = desc_node;
2456 }
2457 node3 = build_omp_clause (input_location,
2458 OMP_CLAUSE_MAP);
2459 OMP_CLAUSE_SET_MAP_KIND (node3, ptr_kind);
2460 OMP_CLAUSE_DECL (node3)
2461 = gfc_conv_descriptor_data_get (decl);
2462 /* This purposely does not include GOMP_MAP_ALWAYS_POINTER. The extra
2463 cast prevents gimplify.cc from recognising it as being part of the
2464 struct – and adding an 'alloc: for the 'desc.data' pointer, which
2465 would break as the 'desc' (the descriptor) is also mapped
2466 (see node4 above). */
2467 if (ptr_kind == GOMP_MAP_ATTACH_DETACH)
2468 STRIP_NOPS (OMP_CLAUSE_DECL (node3));
2469 }
2470 else
2471 {
2472 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2473 {
2474 tree offset;
2475 ptr2 = build_fold_addr_expr (decl);
2476 offset = fold_build2 (MINUS_EXPR, ptrdiff_type_node, ptr,
2477 fold_convert (ptrdiff_type_node, ptr2));
2478 offset = build2 (TRUNC_DIV_EXPR, ptrdiff_type_node,
2479 offset, fold_convert (ptrdiff_type_node, elemsz));
2480 offset = build4_loc (input_location, ARRAY_REF,
2481 TREE_TYPE (TREE_TYPE (decl)),
2482 decl, offset, NULL_TREE, NULL_TREE);
2483 OMP_CLAUSE_DECL (node) = offset;
2484
2485 if (ptr_kind == GOMP_MAP_ALWAYS_POINTER)
2486 return;
2487 }
2488 else
2489 {
2490 gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl)));
2491 ptr2 = decl;
2492 }
2493 node3 = build_omp_clause (input_location,
2494 OMP_CLAUSE_MAP);
2495 OMP_CLAUSE_SET_MAP_KIND (node3, ptr_kind);
2496 OMP_CLAUSE_DECL (node3) = decl;
2497 }
2498 ptr2 = fold_convert (ptrdiff_type_node, ptr2);
2499 OMP_CLAUSE_SIZE (node3) = fold_build2 (MINUS_EXPR, ptrdiff_type_node,
2500 ptr, ptr2);
2501 }
2502
2503 static tree
handle_iterator(gfc_namespace * ns,stmtblock_t * iter_block,tree block)2504 handle_iterator (gfc_namespace *ns, stmtblock_t *iter_block, tree block)
2505 {
2506 tree list = NULL_TREE;
2507 for (gfc_symbol *sym = ns->omp_affinity_iterators; sym; sym = sym->tlink)
2508 {
2509 gfc_constructor *c;
2510 gfc_se se;
2511
2512 tree last = make_tree_vec (6);
2513 tree iter_var = gfc_get_symbol_decl (sym);
2514 tree type = TREE_TYPE (iter_var);
2515 TREE_VEC_ELT (last, 0) = iter_var;
2516 DECL_CHAIN (iter_var) = BLOCK_VARS (block);
2517 BLOCK_VARS (block) = iter_var;
2518
2519 /* begin */
2520 c = gfc_constructor_first (sym->value->value.constructor);
2521 gfc_init_se (&se, NULL);
2522 gfc_conv_expr (&se, c->expr);
2523 gfc_add_block_to_block (iter_block, &se.pre);
2524 gfc_add_block_to_block (iter_block, &se.post);
2525 TREE_VEC_ELT (last, 1) = fold_convert (type,
2526 gfc_evaluate_now (se.expr,
2527 iter_block));
2528 /* end */
2529 c = gfc_constructor_next (c);
2530 gfc_init_se (&se, NULL);
2531 gfc_conv_expr (&se, c->expr);
2532 gfc_add_block_to_block (iter_block, &se.pre);
2533 gfc_add_block_to_block (iter_block, &se.post);
2534 TREE_VEC_ELT (last, 2) = fold_convert (type,
2535 gfc_evaluate_now (se.expr,
2536 iter_block));
2537 /* step */
2538 c = gfc_constructor_next (c);
2539 tree step;
2540 if (c)
2541 {
2542 gfc_init_se (&se, NULL);
2543 gfc_conv_expr (&se, c->expr);
2544 gfc_add_block_to_block (iter_block, &se.pre);
2545 gfc_add_block_to_block (iter_block, &se.post);
2546 gfc_conv_expr (&se, c->expr);
2547 step = fold_convert (type,
2548 gfc_evaluate_now (se.expr,
2549 iter_block));
2550 }
2551 else
2552 step = build_int_cst (type, 1);
2553 TREE_VEC_ELT (last, 3) = step;
2554 /* orig_step */
2555 TREE_VEC_ELT (last, 4) = save_expr (step);
2556 TREE_CHAIN (last) = list;
2557 list = last;
2558 }
2559 return list;
2560 }
2561
2562 static tree
gfc_trans_omp_clauses(stmtblock_t * block,gfc_omp_clauses * clauses,locus where,bool declare_simd=false,bool openacc=false)2563 gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
2564 locus where, bool declare_simd = false,
2565 bool openacc = false)
2566 {
2567 tree omp_clauses = NULL_TREE, prev_clauses, chunk_size, c;
2568 tree iterator = NULL_TREE;
2569 tree tree_block = NULL_TREE;
2570 stmtblock_t iter_block;
2571 int list, ifc;
2572 enum omp_clause_code clause_code;
2573 gfc_omp_namelist *prev = NULL;
2574 gfc_se se;
2575
2576 if (clauses == NULL)
2577 return NULL_TREE;
2578
2579 for (list = 0; list < OMP_LIST_NUM; list++)
2580 {
2581 gfc_omp_namelist *n = clauses->lists[list];
2582
2583 if (n == NULL)
2584 continue;
2585 switch (list)
2586 {
2587 case OMP_LIST_REDUCTION:
2588 case OMP_LIST_REDUCTION_INSCAN:
2589 case OMP_LIST_REDUCTION_TASK:
2590 case OMP_LIST_IN_REDUCTION:
2591 case OMP_LIST_TASK_REDUCTION:
2592 /* An OpenACC async clause indicates the need to set reduction
2593 arguments addressable, to allow asynchronous copy-out. */
2594 omp_clauses = gfc_trans_omp_reduction_list (list, n, omp_clauses,
2595 where, clauses->async);
2596 break;
2597 case OMP_LIST_PRIVATE:
2598 clause_code = OMP_CLAUSE_PRIVATE;
2599 goto add_clause;
2600 case OMP_LIST_SHARED:
2601 clause_code = OMP_CLAUSE_SHARED;
2602 goto add_clause;
2603 case OMP_LIST_FIRSTPRIVATE:
2604 clause_code = OMP_CLAUSE_FIRSTPRIVATE;
2605 goto add_clause;
2606 case OMP_LIST_LASTPRIVATE:
2607 clause_code = OMP_CLAUSE_LASTPRIVATE;
2608 goto add_clause;
2609 case OMP_LIST_COPYIN:
2610 clause_code = OMP_CLAUSE_COPYIN;
2611 goto add_clause;
2612 case OMP_LIST_COPYPRIVATE:
2613 clause_code = OMP_CLAUSE_COPYPRIVATE;
2614 goto add_clause;
2615 case OMP_LIST_UNIFORM:
2616 clause_code = OMP_CLAUSE_UNIFORM;
2617 goto add_clause;
2618 case OMP_LIST_USE_DEVICE:
2619 case OMP_LIST_USE_DEVICE_PTR:
2620 clause_code = OMP_CLAUSE_USE_DEVICE_PTR;
2621 goto add_clause;
2622 case OMP_LIST_USE_DEVICE_ADDR:
2623 clause_code = OMP_CLAUSE_USE_DEVICE_ADDR;
2624 goto add_clause;
2625 case OMP_LIST_IS_DEVICE_PTR:
2626 clause_code = OMP_CLAUSE_IS_DEVICE_PTR;
2627 goto add_clause;
2628 case OMP_LIST_HAS_DEVICE_ADDR:
2629 clause_code = OMP_CLAUSE_HAS_DEVICE_ADDR;
2630 goto add_clause;
2631 case OMP_LIST_NONTEMPORAL:
2632 clause_code = OMP_CLAUSE_NONTEMPORAL;
2633 goto add_clause;
2634 case OMP_LIST_SCAN_IN:
2635 clause_code = OMP_CLAUSE_INCLUSIVE;
2636 goto add_clause;
2637 case OMP_LIST_SCAN_EX:
2638 clause_code = OMP_CLAUSE_EXCLUSIVE;
2639 goto add_clause;
2640
2641 add_clause:
2642 omp_clauses
2643 = gfc_trans_omp_variable_list (clause_code, n, omp_clauses,
2644 declare_simd);
2645 break;
2646 case OMP_LIST_ALIGNED:
2647 for (; n != NULL; n = n->next)
2648 if (n->sym->attr.referenced || declare_simd)
2649 {
2650 tree t = gfc_trans_omp_variable (n->sym, declare_simd);
2651 if (t != error_mark_node)
2652 {
2653 tree node = build_omp_clause (input_location,
2654 OMP_CLAUSE_ALIGNED);
2655 OMP_CLAUSE_DECL (node) = t;
2656 if (n->expr)
2657 {
2658 tree alignment_var;
2659
2660 if (declare_simd)
2661 alignment_var = gfc_conv_constant_to_tree (n->expr);
2662 else
2663 {
2664 gfc_init_se (&se, NULL);
2665 gfc_conv_expr (&se, n->expr);
2666 gfc_add_block_to_block (block, &se.pre);
2667 alignment_var = gfc_evaluate_now (se.expr, block);
2668 gfc_add_block_to_block (block, &se.post);
2669 }
2670 OMP_CLAUSE_ALIGNED_ALIGNMENT (node) = alignment_var;
2671 }
2672 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2673 }
2674 }
2675 break;
2676 case OMP_LIST_ALLOCATE:
2677 for (; n != NULL; n = n->next)
2678 if (n->sym->attr.referenced)
2679 {
2680 tree t = gfc_trans_omp_variable (n->sym, false);
2681 if (t != error_mark_node)
2682 {
2683 tree node = build_omp_clause (input_location,
2684 OMP_CLAUSE_ALLOCATE);
2685 OMP_CLAUSE_DECL (node) = t;
2686 if (n->expr)
2687 {
2688 tree allocator_;
2689 gfc_init_se (&se, NULL);
2690 gfc_conv_expr (&se, n->expr);
2691 allocator_ = gfc_evaluate_now (se.expr, block);
2692 OMP_CLAUSE_ALLOCATE_ALLOCATOR (node) = allocator_;
2693 }
2694 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2695 }
2696 }
2697 break;
2698 case OMP_LIST_LINEAR:
2699 {
2700 gfc_expr *last_step_expr = NULL;
2701 tree last_step = NULL_TREE;
2702 bool last_step_parm = false;
2703
2704 for (; n != NULL; n = n->next)
2705 {
2706 if (n->expr)
2707 {
2708 last_step_expr = n->expr;
2709 last_step = NULL_TREE;
2710 last_step_parm = false;
2711 }
2712 if (n->sym->attr.referenced || declare_simd)
2713 {
2714 tree t = gfc_trans_omp_variable (n->sym, declare_simd);
2715 if (t != error_mark_node)
2716 {
2717 tree node = build_omp_clause (input_location,
2718 OMP_CLAUSE_LINEAR);
2719 OMP_CLAUSE_DECL (node) = t;
2720 omp_clause_linear_kind kind;
2721 switch (n->u.linear_op)
2722 {
2723 case OMP_LINEAR_DEFAULT:
2724 kind = OMP_CLAUSE_LINEAR_DEFAULT;
2725 break;
2726 case OMP_LINEAR_REF:
2727 kind = OMP_CLAUSE_LINEAR_REF;
2728 break;
2729 case OMP_LINEAR_VAL:
2730 kind = OMP_CLAUSE_LINEAR_VAL;
2731 break;
2732 case OMP_LINEAR_UVAL:
2733 kind = OMP_CLAUSE_LINEAR_UVAL;
2734 break;
2735 default:
2736 gcc_unreachable ();
2737 }
2738 OMP_CLAUSE_LINEAR_KIND (node) = kind;
2739 if (last_step_expr && last_step == NULL_TREE)
2740 {
2741 if (!declare_simd)
2742 {
2743 gfc_init_se (&se, NULL);
2744 gfc_conv_expr (&se, last_step_expr);
2745 gfc_add_block_to_block (block, &se.pre);
2746 last_step = gfc_evaluate_now (se.expr, block);
2747 gfc_add_block_to_block (block, &se.post);
2748 }
2749 else if (last_step_expr->expr_type == EXPR_VARIABLE)
2750 {
2751 gfc_symbol *s = last_step_expr->symtree->n.sym;
2752 last_step = gfc_trans_omp_variable (s, true);
2753 last_step_parm = true;
2754 }
2755 else
2756 last_step
2757 = gfc_conv_constant_to_tree (last_step_expr);
2758 }
2759 if (last_step_parm)
2760 {
2761 OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (node) = 1;
2762 OMP_CLAUSE_LINEAR_STEP (node) = last_step;
2763 }
2764 else
2765 {
2766 if (kind == OMP_CLAUSE_LINEAR_REF)
2767 {
2768 tree type;
2769 if (n->sym->attr.flavor == FL_PROCEDURE)
2770 {
2771 type = gfc_get_function_type (n->sym);
2772 type = build_pointer_type (type);
2773 }
2774 else
2775 type = gfc_sym_type (n->sym);
2776 if (POINTER_TYPE_P (type))
2777 type = TREE_TYPE (type);
2778 /* Otherwise to be determined what exactly
2779 should be done. */
2780 tree t = fold_convert (sizetype, last_step);
2781 t = size_binop (MULT_EXPR, t,
2782 TYPE_SIZE_UNIT (type));
2783 OMP_CLAUSE_LINEAR_STEP (node) = t;
2784 }
2785 else
2786 {
2787 tree type
2788 = gfc_typenode_for_spec (&n->sym->ts);
2789 OMP_CLAUSE_LINEAR_STEP (node)
2790 = fold_convert (type, last_step);
2791 }
2792 }
2793 if (n->sym->attr.dimension || n->sym->attr.allocatable)
2794 OMP_CLAUSE_LINEAR_ARRAY (node) = 1;
2795 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2796 }
2797 }
2798 }
2799 }
2800 break;
2801 case OMP_LIST_AFFINITY:
2802 case OMP_LIST_DEPEND:
2803 iterator = NULL_TREE;
2804 prev = NULL;
2805 prev_clauses = omp_clauses;
2806 for (; n != NULL; n = n->next)
2807 {
2808 if (iterator && prev->u2.ns != n->u2.ns)
2809 {
2810 BLOCK_SUBBLOCKS (tree_block) = gfc_finish_block (&iter_block);
2811 TREE_VEC_ELT (iterator, 5) = tree_block;
2812 for (tree c = omp_clauses; c != prev_clauses;
2813 c = OMP_CLAUSE_CHAIN (c))
2814 OMP_CLAUSE_DECL (c) = build_tree_list (iterator,
2815 OMP_CLAUSE_DECL (c));
2816 prev_clauses = omp_clauses;
2817 iterator = NULL_TREE;
2818 }
2819 if (n->u2.ns && (!prev || prev->u2.ns != n->u2.ns))
2820 {
2821 gfc_init_block (&iter_block);
2822 tree_block = make_node (BLOCK);
2823 TREE_USED (tree_block) = 1;
2824 BLOCK_VARS (tree_block) = NULL_TREE;
2825 iterator = handle_iterator (n->u2.ns, block,
2826 tree_block);
2827 }
2828 if (!iterator)
2829 gfc_init_block (&iter_block);
2830 prev = n;
2831 if (list == OMP_LIST_DEPEND
2832 && n->u.depend_op == OMP_DEPEND_SINK_FIRST)
2833 {
2834 tree vec = NULL_TREE;
2835 unsigned int i;
2836 for (i = 0; ; i++)
2837 {
2838 tree addend = integer_zero_node, t;
2839 bool neg = false;
2840 if (n->expr)
2841 {
2842 addend = gfc_conv_constant_to_tree (n->expr);
2843 if (TREE_CODE (addend) == INTEGER_CST
2844 && tree_int_cst_sgn (addend) == -1)
2845 {
2846 neg = true;
2847 addend = const_unop (NEGATE_EXPR,
2848 TREE_TYPE (addend), addend);
2849 }
2850 }
2851 t = gfc_trans_omp_variable (n->sym, false);
2852 if (t != error_mark_node)
2853 {
2854 if (i < vec_safe_length (doacross_steps)
2855 && !integer_zerop (addend)
2856 && (*doacross_steps)[i])
2857 {
2858 tree step = (*doacross_steps)[i];
2859 addend = fold_convert (TREE_TYPE (step), addend);
2860 addend = build2 (TRUNC_DIV_EXPR,
2861 TREE_TYPE (step), addend, step);
2862 }
2863 vec = tree_cons (addend, t, vec);
2864 if (neg)
2865 OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1;
2866 }
2867 if (n->next == NULL
2868 || n->next->u.depend_op != OMP_DEPEND_SINK)
2869 break;
2870 n = n->next;
2871 }
2872 if (vec == NULL_TREE)
2873 continue;
2874
2875 tree node = build_omp_clause (input_location,
2876 OMP_CLAUSE_DEPEND);
2877 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_SINK;
2878 OMP_CLAUSE_DECL (node) = nreverse (vec);
2879 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2880 continue;
2881 }
2882
2883 if (!n->sym->attr.referenced)
2884 continue;
2885
2886 tree node = build_omp_clause (input_location,
2887 list == OMP_LIST_DEPEND
2888 ? OMP_CLAUSE_DEPEND
2889 : OMP_CLAUSE_AFFINITY);
2890 if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
2891 {
2892 tree decl = gfc_trans_omp_variable (n->sym, false);
2893 if (gfc_omp_privatize_by_reference (decl))
2894 decl = build_fold_indirect_ref (decl);
2895 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
2896 {
2897 decl = gfc_conv_descriptor_data_get (decl);
2898 gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl)));
2899 decl = build_fold_indirect_ref (decl);
2900 }
2901 else if (n->sym->attr.allocatable || n->sym->attr.pointer)
2902 decl = build_fold_indirect_ref (decl);
2903 else if (DECL_P (decl))
2904 TREE_ADDRESSABLE (decl) = 1;
2905 OMP_CLAUSE_DECL (node) = decl;
2906 }
2907 else
2908 {
2909 tree ptr;
2910 gfc_init_se (&se, NULL);
2911 if (n->expr->ref->u.ar.type == AR_ELEMENT)
2912 {
2913 gfc_conv_expr_reference (&se, n->expr);
2914 ptr = se.expr;
2915 }
2916 else
2917 {
2918 gfc_conv_expr_descriptor (&se, n->expr);
2919 ptr = gfc_conv_array_data (se.expr);
2920 }
2921 gfc_add_block_to_block (&iter_block, &se.pre);
2922 gfc_add_block_to_block (&iter_block, &se.post);
2923 gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
2924 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
2925 }
2926 if (list == OMP_LIST_DEPEND)
2927 switch (n->u.depend_op)
2928 {
2929 case OMP_DEPEND_IN:
2930 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_IN;
2931 break;
2932 case OMP_DEPEND_OUT:
2933 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_OUT;
2934 break;
2935 case OMP_DEPEND_INOUT:
2936 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_INOUT;
2937 break;
2938 case OMP_DEPEND_MUTEXINOUTSET:
2939 OMP_CLAUSE_DEPEND_KIND (node)
2940 = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
2941 break;
2942 case OMP_DEPEND_DEPOBJ:
2943 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_DEPOBJ;
2944 break;
2945 default:
2946 gcc_unreachable ();
2947 }
2948 if (!iterator)
2949 gfc_add_block_to_block (block, &iter_block);
2950 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2951 }
2952 if (iterator)
2953 {
2954 BLOCK_SUBBLOCKS (tree_block) = gfc_finish_block (&iter_block);
2955 TREE_VEC_ELT (iterator, 5) = tree_block;
2956 for (tree c = omp_clauses; c != prev_clauses;
2957 c = OMP_CLAUSE_CHAIN (c))
2958 OMP_CLAUSE_DECL (c) = build_tree_list (iterator,
2959 OMP_CLAUSE_DECL (c));
2960 }
2961 break;
2962 case OMP_LIST_MAP:
2963 for (; n != NULL; n = n->next)
2964 {
2965 if (!n->sym->attr.referenced)
2966 continue;
2967
2968 bool always_modifier = false;
2969 tree node = build_omp_clause (input_location, OMP_CLAUSE_MAP);
2970 tree node2 = NULL_TREE;
2971 tree node3 = NULL_TREE;
2972 tree node4 = NULL_TREE;
2973
2974 /* OpenMP: automatically map pointer targets with the pointer;
2975 hence, always update the descriptor/pointer itself. */
2976 if (!openacc
2977 && ((n->expr == NULL && n->sym->attr.pointer)
2978 || (n->expr && gfc_expr_attr (n->expr).pointer)))
2979 always_modifier = true;
2980
2981 switch (n->u.map_op)
2982 {
2983 case OMP_MAP_ALLOC:
2984 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALLOC);
2985 break;
2986 case OMP_MAP_IF_PRESENT:
2987 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_IF_PRESENT);
2988 break;
2989 case OMP_MAP_ATTACH:
2990 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ATTACH);
2991 break;
2992 case OMP_MAP_TO:
2993 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TO);
2994 break;
2995 case OMP_MAP_FROM:
2996 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FROM);
2997 break;
2998 case OMP_MAP_TOFROM:
2999 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TOFROM);
3000 break;
3001 case OMP_MAP_ALWAYS_TO:
3002 always_modifier = true;
3003 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TO);
3004 break;
3005 case OMP_MAP_ALWAYS_FROM:
3006 always_modifier = true;
3007 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_FROM);
3008 break;
3009 case OMP_MAP_ALWAYS_TOFROM:
3010 always_modifier = true;
3011 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TOFROM);
3012 break;
3013 case OMP_MAP_RELEASE:
3014 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_RELEASE);
3015 break;
3016 case OMP_MAP_DELETE:
3017 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_DELETE);
3018 break;
3019 case OMP_MAP_DETACH:
3020 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_DETACH);
3021 break;
3022 case OMP_MAP_FORCE_ALLOC:
3023 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_ALLOC);
3024 break;
3025 case OMP_MAP_FORCE_TO:
3026 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TO);
3027 break;
3028 case OMP_MAP_FORCE_FROM:
3029 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_FROM);
3030 break;
3031 case OMP_MAP_FORCE_TOFROM:
3032 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TOFROM);
3033 break;
3034 case OMP_MAP_FORCE_PRESENT:
3035 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_PRESENT);
3036 break;
3037 case OMP_MAP_FORCE_DEVICEPTR:
3038 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_DEVICEPTR);
3039 break;
3040 default:
3041 gcc_unreachable ();
3042 }
3043
3044 tree decl = gfc_trans_omp_variable (n->sym, false);
3045 if (DECL_P (decl))
3046 TREE_ADDRESSABLE (decl) = 1;
3047
3048 gfc_ref *lastref = NULL;
3049
3050 if (n->expr)
3051 for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
3052 if (ref->type == REF_COMPONENT || ref->type == REF_ARRAY)
3053 lastref = ref;
3054
3055 bool allocatable = false, pointer = false;
3056
3057 if (lastref && lastref->type == REF_COMPONENT)
3058 {
3059 gfc_component *c = lastref->u.c.component;
3060
3061 if (c->ts.type == BT_CLASS)
3062 {
3063 pointer = CLASS_DATA (c)->attr.class_pointer;
3064 allocatable = CLASS_DATA (c)->attr.allocatable;
3065 }
3066 else
3067 {
3068 pointer = c->attr.pointer;
3069 allocatable = c->attr.allocatable;
3070 }
3071 }
3072
3073 if (n->expr == NULL
3074 || (n->expr->ref->type == REF_ARRAY
3075 && n->expr->ref->u.ar.type == AR_FULL))
3076 {
3077 tree present = gfc_omp_check_optional_argument (decl, true);
3078 if (openacc && n->sym->ts.type == BT_CLASS)
3079 {
3080 tree type = TREE_TYPE (decl);
3081 if (n->sym->attr.optional)
3082 sorry ("optional class parameter");
3083 if (POINTER_TYPE_P (type))
3084 {
3085 node4 = build_omp_clause (input_location,
3086 OMP_CLAUSE_MAP);
3087 OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER);
3088 OMP_CLAUSE_DECL (node4) = decl;
3089 OMP_CLAUSE_SIZE (node4) = size_int (0);
3090 decl = build_fold_indirect_ref (decl);
3091 }
3092 tree ptr = gfc_class_data_get (decl);
3093 ptr = build_fold_indirect_ref (ptr);
3094 OMP_CLAUSE_DECL (node) = ptr;
3095 OMP_CLAUSE_SIZE (node) = gfc_class_vtab_size_get (decl);
3096 node2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
3097 OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
3098 OMP_CLAUSE_DECL (node2) = decl;
3099 OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
3100 node3 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
3101 OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_ATTACH_DETACH);
3102 OMP_CLAUSE_DECL (node3) = gfc_class_data_get (decl);
3103 OMP_CLAUSE_SIZE (node3) = size_int (0);
3104 goto finalize_map_clause;
3105 }
3106 else if (POINTER_TYPE_P (TREE_TYPE (decl))
3107 && (gfc_omp_privatize_by_reference (decl)
3108 || GFC_DECL_GET_SCALAR_POINTER (decl)
3109 || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
3110 || GFC_DECL_CRAY_POINTEE (decl)
3111 || GFC_DESCRIPTOR_TYPE_P
3112 (TREE_TYPE (TREE_TYPE (decl)))
3113 || (n->sym->ts.type == BT_DERIVED
3114 && (n->sym->ts.u.derived->ts.f90_type
3115 != BT_VOID))))
3116 {
3117 tree orig_decl = decl;
3118
3119 /* For nonallocatable, nonpointer arrays, a temporary
3120 variable is generated, but this one is only defined if
3121 the variable is present; hence, we now set it to NULL
3122 to avoid accessing undefined variables. We cannot use
3123 a temporary variable here as otherwise the replacement
3124 of the variables in omp-low.cc will not work. */
3125 if (present && GFC_ARRAY_TYPE_P (TREE_TYPE (decl)))
3126 {
3127 tree tmp = fold_build2_loc (input_location,
3128 MODIFY_EXPR,
3129 void_type_node, decl,
3130 null_pointer_node);
3131 tree cond = fold_build1_loc (input_location,
3132 TRUTH_NOT_EXPR,
3133 boolean_type_node,
3134 present);
3135 gfc_add_expr_to_block (block,
3136 build3_loc (input_location,
3137 COND_EXPR,
3138 void_type_node,
3139 cond, tmp,
3140 NULL_TREE));
3141 }
3142 node4 = build_omp_clause (input_location,
3143 OMP_CLAUSE_MAP);
3144 OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER);
3145 OMP_CLAUSE_DECL (node4) = decl;
3146 OMP_CLAUSE_SIZE (node4) = size_int (0);
3147 decl = build_fold_indirect_ref (decl);
3148 if ((TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE
3149 || gfc_omp_is_optional_argument (orig_decl))
3150 && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
3151 || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
3152 {
3153 node3 = build_omp_clause (input_location,
3154 OMP_CLAUSE_MAP);
3155 OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_POINTER);
3156 OMP_CLAUSE_DECL (node3) = decl;
3157 OMP_CLAUSE_SIZE (node3) = size_int (0);
3158 decl = build_fold_indirect_ref (decl);
3159 }
3160 }
3161 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
3162 {
3163 tree type = TREE_TYPE (decl);
3164 tree ptr = gfc_conv_descriptor_data_get (decl);
3165 if (present)
3166 ptr = gfc_build_cond_assign_expr (block, present, ptr,
3167 null_pointer_node);
3168 gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
3169 ptr = build_fold_indirect_ref (ptr);
3170 OMP_CLAUSE_DECL (node) = ptr;
3171 node2 = build_omp_clause (input_location,
3172 OMP_CLAUSE_MAP);
3173 OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
3174 OMP_CLAUSE_DECL (node2) = decl;
3175 OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
3176 node3 = build_omp_clause (input_location,
3177 OMP_CLAUSE_MAP);
3178 if (present)
3179 {
3180 ptr = gfc_conv_descriptor_data_get (decl);
3181 ptr = gfc_build_addr_expr (NULL, ptr);
3182 ptr = gfc_build_cond_assign_expr (block, present, ptr,
3183 null_pointer_node);
3184 ptr = build_fold_indirect_ref (ptr);
3185 OMP_CLAUSE_DECL (node3) = ptr;
3186 }
3187 else
3188 OMP_CLAUSE_DECL (node3)
3189 = gfc_conv_descriptor_data_get (decl);
3190 OMP_CLAUSE_SIZE (node3) = size_int (0);
3191 if (n->u.map_op == OMP_MAP_ATTACH)
3192 {
3193 /* Standalone attach clauses used with arrays with
3194 descriptors must copy the descriptor to the target,
3195 else they won't have anything to perform the
3196 attachment onto (see OpenACC 2.6, "2.6.3. Data
3197 Structures with Pointers"). */
3198 OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_ATTACH);
3199 /* We don't want to map PTR at all in this case, so
3200 delete its node and shuffle the others down. */
3201 node = node2;
3202 node2 = node3;
3203 node3 = NULL;
3204 goto finalize_map_clause;
3205 }
3206 else if (n->u.map_op == OMP_MAP_DETACH)
3207 {
3208 OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_DETACH);
3209 /* Similarly to above, we don't want to unmap PTR
3210 here. */
3211 node = node2;
3212 node2 = node3;
3213 node3 = NULL;
3214 goto finalize_map_clause;
3215 }
3216 else
3217 OMP_CLAUSE_SET_MAP_KIND (node3,
3218 always_modifier
3219 ? GOMP_MAP_ALWAYS_POINTER
3220 : GOMP_MAP_POINTER);
3221
3222 /* We have to check for n->sym->attr.dimension because
3223 of scalar coarrays. */
3224 if ((n->sym->attr.pointer || n->sym->attr.allocatable)
3225 && n->sym->attr.dimension)
3226 {
3227 stmtblock_t cond_block;
3228 tree size
3229 = gfc_create_var (gfc_array_index_type, NULL);
3230 tree tem, then_b, else_b, zero, cond;
3231
3232 gfc_init_block (&cond_block);
3233 tem
3234 = gfc_full_array_size (&cond_block, decl,
3235 GFC_TYPE_ARRAY_RANK (type));
3236 gfc_add_modify (&cond_block, size, tem);
3237 then_b = gfc_finish_block (&cond_block);
3238 gfc_init_block (&cond_block);
3239 zero = build_int_cst (gfc_array_index_type, 0);
3240 gfc_add_modify (&cond_block, size, zero);
3241 else_b = gfc_finish_block (&cond_block);
3242 tem = gfc_conv_descriptor_data_get (decl);
3243 tem = fold_convert (pvoid_type_node, tem);
3244 cond = fold_build2_loc (input_location, NE_EXPR,
3245 boolean_type_node,
3246 tem, null_pointer_node);
3247 if (present)
3248 cond = fold_build2_loc (input_location,
3249 TRUTH_ANDIF_EXPR,
3250 boolean_type_node,
3251 present, cond);
3252 gfc_add_expr_to_block (block,
3253 build3_loc (input_location,
3254 COND_EXPR,
3255 void_type_node,
3256 cond, then_b,
3257 else_b));
3258 OMP_CLAUSE_SIZE (node) = size;
3259 }
3260 else if (n->sym->attr.dimension)
3261 {
3262 stmtblock_t cond_block;
3263 gfc_init_block (&cond_block);
3264 tree size = gfc_full_array_size (&cond_block, decl,
3265 GFC_TYPE_ARRAY_RANK (type));
3266 if (present)
3267 {
3268 tree var = gfc_create_var (gfc_array_index_type,
3269 NULL);
3270 gfc_add_modify (&cond_block, var, size);
3271 tree cond_body = gfc_finish_block (&cond_block);
3272 tree cond = build3_loc (input_location, COND_EXPR,
3273 void_type_node, present,
3274 cond_body, NULL_TREE);
3275 gfc_add_expr_to_block (block, cond);
3276 OMP_CLAUSE_SIZE (node) = var;
3277 }
3278 else
3279 {
3280 gfc_add_block_to_block (block, &cond_block);
3281 OMP_CLAUSE_SIZE (node) = size;
3282 }
3283 }
3284 if (n->sym->attr.dimension)
3285 {
3286 tree elemsz
3287 = TYPE_SIZE_UNIT (gfc_get_element_type (type));
3288 elemsz = fold_convert (gfc_array_index_type, elemsz);
3289 OMP_CLAUSE_SIZE (node)
3290 = fold_build2 (MULT_EXPR, gfc_array_index_type,
3291 OMP_CLAUSE_SIZE (node), elemsz);
3292 }
3293 }
3294 else if (present
3295 && TREE_CODE (decl) == INDIRECT_REF
3296 && (TREE_CODE (TREE_OPERAND (decl, 0))
3297 == INDIRECT_REF))
3298 {
3299 /* A single indirectref is handled by the middle end. */
3300 gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
3301 decl = TREE_OPERAND (decl, 0);
3302 decl = gfc_build_cond_assign_expr (block, present, decl,
3303 null_pointer_node);
3304 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (decl);
3305 }
3306 else
3307 OMP_CLAUSE_DECL (node) = decl;
3308 }
3309 else if (n->expr
3310 && n->expr->expr_type == EXPR_VARIABLE
3311 && n->expr->ref->type == REF_ARRAY
3312 && !n->expr->ref->next)
3313 {
3314 /* An array element or array section which is not part of a
3315 derived type, etc. */
3316 bool element = n->expr->ref->u.ar.type == AR_ELEMENT;
3317 gfc_trans_omp_array_section (block, n, decl, element,
3318 GOMP_MAP_POINTER, node, node2,
3319 node3, node4);
3320 }
3321 else if (n->expr
3322 && n->expr->expr_type == EXPR_VARIABLE
3323 && (n->expr->ref->type == REF_COMPONENT
3324 || n->expr->ref->type == REF_ARRAY)
3325 && lastref
3326 && lastref->type == REF_COMPONENT
3327 && lastref->u.c.component->ts.type != BT_CLASS
3328 && lastref->u.c.component->ts.type != BT_DERIVED
3329 && !lastref->u.c.component->attr.dimension)
3330 {
3331 /* Derived type access with last component being a scalar. */
3332 gfc_init_se (&se, NULL);
3333
3334 gfc_conv_expr (&se, n->expr);
3335 gfc_add_block_to_block (block, &se.pre);
3336 /* For BT_CHARACTER a pointer is returned. */
3337 OMP_CLAUSE_DECL (node)
3338 = POINTER_TYPE_P (TREE_TYPE (se.expr))
3339 ? build_fold_indirect_ref (se.expr) : se.expr;
3340 gfc_add_block_to_block (block, &se.post);
3341 if (pointer || allocatable)
3342 {
3343 node2 = build_omp_clause (input_location,
3344 OMP_CLAUSE_MAP);
3345 gomp_map_kind kind
3346 = (openacc ? GOMP_MAP_ATTACH_DETACH
3347 : GOMP_MAP_ALWAYS_POINTER);
3348 OMP_CLAUSE_SET_MAP_KIND (node2, kind);
3349 OMP_CLAUSE_DECL (node2)
3350 = POINTER_TYPE_P (TREE_TYPE (se.expr))
3351 ? se.expr
3352 : gfc_build_addr_expr (NULL, se.expr);
3353 OMP_CLAUSE_SIZE (node2) = size_int (0);
3354 if (!openacc
3355 && n->expr->ts.type == BT_CHARACTER
3356 && n->expr->ts.deferred)
3357 {
3358 gcc_assert (se.string_length);
3359 tree tmp
3360 = gfc_get_char_type (n->expr->ts.kind);
3361 OMP_CLAUSE_SIZE (node)
3362 = fold_build2 (MULT_EXPR, size_type_node,
3363 fold_convert (size_type_node,
3364 se.string_length),
3365 TYPE_SIZE_UNIT (tmp));
3366 node3 = build_omp_clause (input_location,
3367 OMP_CLAUSE_MAP);
3368 OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_TO);
3369 OMP_CLAUSE_DECL (node3) = se.string_length;
3370 OMP_CLAUSE_SIZE (node3)
3371 = TYPE_SIZE_UNIT (gfc_charlen_type_node);
3372 }
3373 }
3374 }
3375 else if (n->expr
3376 && n->expr->expr_type == EXPR_VARIABLE
3377 && (n->expr->ref->type == REF_COMPONENT
3378 || n->expr->ref->type == REF_ARRAY))
3379 {
3380 gfc_init_se (&se, NULL);
3381 se.expr = gfc_maybe_dereference_var (n->sym, decl);
3382
3383 for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
3384 {
3385 if (ref->type == REF_COMPONENT)
3386 {
3387 if (ref->u.c.sym->attr.extension)
3388 conv_parent_component_references (&se, ref);
3389
3390 gfc_conv_component_ref (&se, ref);
3391 }
3392 else if (ref->type == REF_ARRAY)
3393 {
3394 if (ref->u.ar.type == AR_ELEMENT && ref->next)
3395 gfc_conv_array_ref (&se, &ref->u.ar, n->expr,
3396 &n->expr->where);
3397 else
3398 gcc_assert (!ref->next);
3399 }
3400 else
3401 sorry ("unhandled expression type");
3402 }
3403
3404 tree inner = se.expr;
3405
3406 /* Last component is a derived type or class pointer. */
3407 if (lastref->type == REF_COMPONENT
3408 && (lastref->u.c.component->ts.type == BT_DERIVED
3409 || lastref->u.c.component->ts.type == BT_CLASS))
3410 {
3411 if (pointer || (openacc && allocatable))
3412 {
3413 tree data, size;
3414
3415 if (lastref->u.c.component->ts.type == BT_CLASS)
3416 {
3417 data = gfc_class_data_get (inner);
3418 gcc_assert (POINTER_TYPE_P (TREE_TYPE (data)));
3419 data = build_fold_indirect_ref (data);
3420 size = gfc_class_vtab_size_get (inner);
3421 }
3422 else /* BT_DERIVED. */
3423 {
3424 data = inner;
3425 size = TYPE_SIZE_UNIT (TREE_TYPE (inner));
3426 }
3427
3428 OMP_CLAUSE_DECL (node) = data;
3429 OMP_CLAUSE_SIZE (node) = size;
3430 node2 = build_omp_clause (input_location,
3431 OMP_CLAUSE_MAP);
3432 OMP_CLAUSE_SET_MAP_KIND (node2,
3433 openacc
3434 ? GOMP_MAP_ATTACH_DETACH
3435 : GOMP_MAP_ALWAYS_POINTER);
3436 OMP_CLAUSE_DECL (node2) = build_fold_addr_expr (data);
3437 OMP_CLAUSE_SIZE (node2) = size_int (0);
3438 }
3439 else
3440 {
3441 OMP_CLAUSE_DECL (node) = inner;
3442 OMP_CLAUSE_SIZE (node)
3443 = TYPE_SIZE_UNIT (TREE_TYPE (inner));
3444 }
3445 }
3446 else if (lastref->type == REF_ARRAY
3447 && lastref->u.ar.type == AR_FULL)
3448 {
3449 /* Just pass the (auto-dereferenced) decl through for
3450 bare attach and detach clauses. */
3451 if (n->u.map_op == OMP_MAP_ATTACH
3452 || n->u.map_op == OMP_MAP_DETACH)
3453 {
3454 OMP_CLAUSE_DECL (node) = inner;
3455 OMP_CLAUSE_SIZE (node) = size_zero_node;
3456 goto finalize_map_clause;
3457 }
3458
3459 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (inner)))
3460 {
3461 gomp_map_kind map_kind;
3462 tree desc_node;
3463 tree type = TREE_TYPE (inner);
3464 tree ptr = gfc_conv_descriptor_data_get (inner);
3465 ptr = build_fold_indirect_ref (ptr);
3466 OMP_CLAUSE_DECL (node) = ptr;
3467 int rank = GFC_TYPE_ARRAY_RANK (type);
3468 OMP_CLAUSE_SIZE (node)
3469 = gfc_full_array_size (block, inner, rank);
3470 tree elemsz
3471 = TYPE_SIZE_UNIT (gfc_get_element_type (type));
3472 if (GOMP_MAP_COPY_TO_P (OMP_CLAUSE_MAP_KIND (node)))
3473 map_kind = GOMP_MAP_TO;
3474 else if (n->u.map_op == OMP_MAP_RELEASE
3475 || n->u.map_op == OMP_MAP_DELETE)
3476 map_kind = OMP_CLAUSE_MAP_KIND (node);
3477 else
3478 map_kind = GOMP_MAP_ALLOC;
3479 if (!openacc
3480 && n->expr->ts.type == BT_CHARACTER
3481 && n->expr->ts.deferred)
3482 {
3483 gcc_assert (se.string_length);
3484 tree len = fold_convert (size_type_node,
3485 se.string_length);
3486 elemsz = gfc_get_char_type (n->expr->ts.kind);
3487 elemsz = TYPE_SIZE_UNIT (elemsz);
3488 elemsz = fold_build2 (MULT_EXPR, size_type_node,
3489 len, elemsz);
3490 node4 = build_omp_clause (input_location,
3491 OMP_CLAUSE_MAP);
3492 OMP_CLAUSE_SET_MAP_KIND (node4, map_kind);
3493 OMP_CLAUSE_DECL (node4) = se.string_length;
3494 OMP_CLAUSE_SIZE (node4)
3495 = TYPE_SIZE_UNIT (gfc_charlen_type_node);
3496 }
3497 elemsz = fold_convert (gfc_array_index_type, elemsz);
3498 OMP_CLAUSE_SIZE (node)
3499 = fold_build2 (MULT_EXPR, gfc_array_index_type,
3500 OMP_CLAUSE_SIZE (node), elemsz);
3501 desc_node = build_omp_clause (input_location,
3502 OMP_CLAUSE_MAP);
3503 if (openacc)
3504 OMP_CLAUSE_SET_MAP_KIND (desc_node,
3505 GOMP_MAP_TO_PSET);
3506 else
3507 OMP_CLAUSE_SET_MAP_KIND (desc_node, map_kind);
3508 OMP_CLAUSE_DECL (desc_node) = inner;
3509 OMP_CLAUSE_SIZE (desc_node) = TYPE_SIZE_UNIT (type);
3510 if (openacc)
3511 node2 = desc_node;
3512 else
3513 {
3514 node2 = node;
3515 node = desc_node; /* Put first. */
3516 }
3517 node3 = build_omp_clause (input_location,
3518 OMP_CLAUSE_MAP);
3519 OMP_CLAUSE_SET_MAP_KIND (node3,
3520 openacc
3521 ? GOMP_MAP_ATTACH_DETACH
3522 : GOMP_MAP_ALWAYS_POINTER);
3523 OMP_CLAUSE_DECL (node3)
3524 = gfc_conv_descriptor_data_get (inner);
3525 /* Similar to gfc_trans_omp_array_section (details
3526 there), we add/keep the cast for OpenMP to prevent
3527 that an 'alloc:' gets added for node3 ('desc.data')
3528 as that is part of the whole descriptor (node3).
3529 TODO: Remove once the ME handles this properly. */
3530 if (!openacc)
3531 OMP_CLAUSE_DECL (node3)
3532 = fold_convert (TREE_TYPE (TREE_OPERAND(ptr, 0)),
3533 OMP_CLAUSE_DECL (node3));
3534 else
3535 STRIP_NOPS (OMP_CLAUSE_DECL (node3));
3536 OMP_CLAUSE_SIZE (node3) = size_int (0);
3537 }
3538 else
3539 OMP_CLAUSE_DECL (node) = inner;
3540 }
3541 else if (lastref->type == REF_ARRAY)
3542 {
3543 /* An array element or section. */
3544 bool element = lastref->u.ar.type == AR_ELEMENT;
3545 gomp_map_kind kind = (openacc ? GOMP_MAP_ATTACH_DETACH
3546 : GOMP_MAP_ALWAYS_POINTER);
3547 gfc_trans_omp_array_section (block, n, inner, element,
3548 kind, node, node2, node3,
3549 node4);
3550 }
3551 else
3552 gcc_unreachable ();
3553 }
3554 else
3555 sorry ("unhandled expression");
3556
3557 finalize_map_clause:
3558
3559 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
3560 if (node2)
3561 omp_clauses = gfc_trans_add_clause (node2, omp_clauses);
3562 if (node3)
3563 omp_clauses = gfc_trans_add_clause (node3, omp_clauses);
3564 if (node4)
3565 omp_clauses = gfc_trans_add_clause (node4, omp_clauses);
3566 }
3567 break;
3568 case OMP_LIST_TO:
3569 case OMP_LIST_FROM:
3570 case OMP_LIST_CACHE:
3571 for (; n != NULL; n = n->next)
3572 {
3573 if (!n->sym->attr.referenced)
3574 continue;
3575
3576 switch (list)
3577 {
3578 case OMP_LIST_TO:
3579 clause_code = OMP_CLAUSE_TO;
3580 break;
3581 case OMP_LIST_FROM:
3582 clause_code = OMP_CLAUSE_FROM;
3583 break;
3584 case OMP_LIST_CACHE:
3585 clause_code = OMP_CLAUSE__CACHE_;
3586 break;
3587 default:
3588 gcc_unreachable ();
3589 }
3590 tree node = build_omp_clause (input_location, clause_code);
3591 if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
3592 {
3593 tree decl = gfc_trans_omp_variable (n->sym, false);
3594 if (gfc_omp_privatize_by_reference (decl))
3595 {
3596 if (gfc_omp_is_allocatable_or_ptr (decl))
3597 decl = build_fold_indirect_ref (decl);
3598 decl = build_fold_indirect_ref (decl);
3599 }
3600 else if (DECL_P (decl))
3601 TREE_ADDRESSABLE (decl) = 1;
3602 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
3603 {
3604 tree type = TREE_TYPE (decl);
3605 tree ptr = gfc_conv_descriptor_data_get (decl);
3606 gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
3607 ptr = build_fold_indirect_ref (ptr);
3608 OMP_CLAUSE_DECL (node) = ptr;
3609 OMP_CLAUSE_SIZE (node)
3610 = gfc_full_array_size (block, decl,
3611 GFC_TYPE_ARRAY_RANK (type));
3612 tree elemsz
3613 = TYPE_SIZE_UNIT (gfc_get_element_type (type));
3614 elemsz = fold_convert (gfc_array_index_type, elemsz);
3615 OMP_CLAUSE_SIZE (node)
3616 = fold_build2 (MULT_EXPR, gfc_array_index_type,
3617 OMP_CLAUSE_SIZE (node), elemsz);
3618 }
3619 else
3620 {
3621 OMP_CLAUSE_DECL (node) = decl;
3622 if (gfc_omp_is_allocatable_or_ptr (decl))
3623 OMP_CLAUSE_SIZE (node)
3624 = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)));
3625 }
3626 }
3627 else
3628 {
3629 tree ptr;
3630 gfc_init_se (&se, NULL);
3631 if (n->expr->ref->u.ar.type == AR_ELEMENT)
3632 {
3633 gfc_conv_expr_reference (&se, n->expr);
3634 ptr = se.expr;
3635 gfc_add_block_to_block (block, &se.pre);
3636 OMP_CLAUSE_SIZE (node)
3637 = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
3638 }
3639 else
3640 {
3641 gfc_conv_expr_descriptor (&se, n->expr);
3642 ptr = gfc_conv_array_data (se.expr);
3643 tree type = TREE_TYPE (se.expr);
3644 gfc_add_block_to_block (block, &se.pre);
3645 OMP_CLAUSE_SIZE (node)
3646 = gfc_full_array_size (block, se.expr,
3647 GFC_TYPE_ARRAY_RANK (type));
3648 tree elemsz
3649 = TYPE_SIZE_UNIT (gfc_get_element_type (type));
3650 elemsz = fold_convert (gfc_array_index_type, elemsz);
3651 OMP_CLAUSE_SIZE (node)
3652 = fold_build2 (MULT_EXPR, gfc_array_index_type,
3653 OMP_CLAUSE_SIZE (node), elemsz);
3654 }
3655 gfc_add_block_to_block (block, &se.post);
3656 gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
3657 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
3658 }
3659 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
3660 }
3661 break;
3662 default:
3663 break;
3664 }
3665 }
3666
3667 if (clauses->if_expr)
3668 {
3669 tree if_var;
3670
3671 gfc_init_se (&se, NULL);
3672 gfc_conv_expr (&se, clauses->if_expr);
3673 gfc_add_block_to_block (block, &se.pre);
3674 if_var = gfc_evaluate_now (se.expr, block);
3675 gfc_add_block_to_block (block, &se.post);
3676
3677 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF);
3678 OMP_CLAUSE_IF_MODIFIER (c) = ERROR_MARK;
3679 OMP_CLAUSE_IF_EXPR (c) = if_var;
3680 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3681 }
3682 for (ifc = 0; ifc < OMP_IF_LAST; ifc++)
3683 if (clauses->if_exprs[ifc])
3684 {
3685 tree if_var;
3686
3687 gfc_init_se (&se, NULL);
3688 gfc_conv_expr (&se, clauses->if_exprs[ifc]);
3689 gfc_add_block_to_block (block, &se.pre);
3690 if_var = gfc_evaluate_now (se.expr, block);
3691 gfc_add_block_to_block (block, &se.post);
3692
3693 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF);
3694 switch (ifc)
3695 {
3696 case OMP_IF_CANCEL:
3697 OMP_CLAUSE_IF_MODIFIER (c) = VOID_CST;
3698 break;
3699 case OMP_IF_PARALLEL:
3700 OMP_CLAUSE_IF_MODIFIER (c) = OMP_PARALLEL;
3701 break;
3702 case OMP_IF_SIMD:
3703 OMP_CLAUSE_IF_MODIFIER (c) = OMP_SIMD;
3704 break;
3705 case OMP_IF_TASK:
3706 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TASK;
3707 break;
3708 case OMP_IF_TASKLOOP:
3709 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TASKLOOP;
3710 break;
3711 case OMP_IF_TARGET:
3712 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET;
3713 break;
3714 case OMP_IF_TARGET_DATA:
3715 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_DATA;
3716 break;
3717 case OMP_IF_TARGET_UPDATE:
3718 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_UPDATE;
3719 break;
3720 case OMP_IF_TARGET_ENTER_DATA:
3721 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_ENTER_DATA;
3722 break;
3723 case OMP_IF_TARGET_EXIT_DATA:
3724 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_EXIT_DATA;
3725 break;
3726 default:
3727 gcc_unreachable ();
3728 }
3729 OMP_CLAUSE_IF_EXPR (c) = if_var;
3730 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3731 }
3732
3733 if (clauses->final_expr)
3734 {
3735 tree final_var;
3736
3737 gfc_init_se (&se, NULL);
3738 gfc_conv_expr (&se, clauses->final_expr);
3739 gfc_add_block_to_block (block, &se.pre);
3740 final_var = gfc_evaluate_now (se.expr, block);
3741 gfc_add_block_to_block (block, &se.post);
3742
3743 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FINAL);
3744 OMP_CLAUSE_FINAL_EXPR (c) = final_var;
3745 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3746 }
3747
3748 if (clauses->num_threads)
3749 {
3750 tree num_threads;
3751
3752 gfc_init_se (&se, NULL);
3753 gfc_conv_expr (&se, clauses->num_threads);
3754 gfc_add_block_to_block (block, &se.pre);
3755 num_threads = gfc_evaluate_now (se.expr, block);
3756 gfc_add_block_to_block (block, &se.post);
3757
3758 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_THREADS);
3759 OMP_CLAUSE_NUM_THREADS_EXPR (c) = num_threads;
3760 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3761 }
3762
3763 chunk_size = NULL_TREE;
3764 if (clauses->chunk_size)
3765 {
3766 gfc_init_se (&se, NULL);
3767 gfc_conv_expr (&se, clauses->chunk_size);
3768 gfc_add_block_to_block (block, &se.pre);
3769 chunk_size = gfc_evaluate_now (se.expr, block);
3770 gfc_add_block_to_block (block, &se.post);
3771 }
3772
3773 if (clauses->sched_kind != OMP_SCHED_NONE)
3774 {
3775 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SCHEDULE);
3776 OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
3777 switch (clauses->sched_kind)
3778 {
3779 case OMP_SCHED_STATIC:
3780 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
3781 break;
3782 case OMP_SCHED_DYNAMIC:
3783 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
3784 break;
3785 case OMP_SCHED_GUIDED:
3786 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
3787 break;
3788 case OMP_SCHED_RUNTIME:
3789 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
3790 break;
3791 case OMP_SCHED_AUTO:
3792 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
3793 break;
3794 default:
3795 gcc_unreachable ();
3796 }
3797 if (clauses->sched_monotonic)
3798 OMP_CLAUSE_SCHEDULE_KIND (c)
3799 = (omp_clause_schedule_kind) (OMP_CLAUSE_SCHEDULE_KIND (c)
3800 | OMP_CLAUSE_SCHEDULE_MONOTONIC);
3801 else if (clauses->sched_nonmonotonic)
3802 OMP_CLAUSE_SCHEDULE_KIND (c)
3803 = (omp_clause_schedule_kind) (OMP_CLAUSE_SCHEDULE_KIND (c)
3804 | OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
3805 if (clauses->sched_simd)
3806 OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
3807 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3808 }
3809
3810 if (clauses->default_sharing != OMP_DEFAULT_UNKNOWN)
3811 {
3812 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEFAULT);
3813 switch (clauses->default_sharing)
3814 {
3815 case OMP_DEFAULT_NONE:
3816 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_NONE;
3817 break;
3818 case OMP_DEFAULT_SHARED:
3819 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_SHARED;
3820 break;
3821 case OMP_DEFAULT_PRIVATE:
3822 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRIVATE;
3823 break;
3824 case OMP_DEFAULT_FIRSTPRIVATE:
3825 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
3826 break;
3827 case OMP_DEFAULT_PRESENT:
3828 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRESENT;
3829 break;
3830 default:
3831 gcc_unreachable ();
3832 }
3833 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3834 }
3835
3836 if (clauses->nowait)
3837 {
3838 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOWAIT);
3839 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3840 }
3841
3842 if (clauses->ordered)
3843 {
3844 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ORDERED);
3845 OMP_CLAUSE_ORDERED_EXPR (c)
3846 = clauses->orderedc ? build_int_cst (integer_type_node,
3847 clauses->orderedc) : NULL_TREE;
3848 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3849 }
3850
3851 if (clauses->order_concurrent)
3852 {
3853 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ORDER);
3854 OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = clauses->order_unconstrained;
3855 OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = clauses->order_reproducible;
3856 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3857 }
3858
3859 if (clauses->untied)
3860 {
3861 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_UNTIED);
3862 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3863 }
3864
3865 if (clauses->mergeable)
3866 {
3867 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_MERGEABLE);
3868 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3869 }
3870
3871 if (clauses->collapse)
3872 {
3873 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_COLLAPSE);
3874 OMP_CLAUSE_COLLAPSE_EXPR (c)
3875 = build_int_cst (integer_type_node, clauses->collapse);
3876 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3877 }
3878
3879 if (clauses->inbranch)
3880 {
3881 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_INBRANCH);
3882 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3883 }
3884
3885 if (clauses->notinbranch)
3886 {
3887 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOTINBRANCH);
3888 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3889 }
3890
3891 switch (clauses->cancel)
3892 {
3893 case OMP_CANCEL_UNKNOWN:
3894 break;
3895 case OMP_CANCEL_PARALLEL:
3896 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PARALLEL);
3897 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3898 break;
3899 case OMP_CANCEL_SECTIONS:
3900 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SECTIONS);
3901 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3902 break;
3903 case OMP_CANCEL_DO:
3904 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FOR);
3905 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3906 break;
3907 case OMP_CANCEL_TASKGROUP:
3908 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_TASKGROUP);
3909 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3910 break;
3911 }
3912
3913 if (clauses->proc_bind != OMP_PROC_BIND_UNKNOWN)
3914 {
3915 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PROC_BIND);
3916 switch (clauses->proc_bind)
3917 {
3918 case OMP_PROC_BIND_PRIMARY:
3919 OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_PRIMARY;
3920 break;
3921 case OMP_PROC_BIND_MASTER:
3922 OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_MASTER;
3923 break;
3924 case OMP_PROC_BIND_SPREAD:
3925 OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_SPREAD;
3926 break;
3927 case OMP_PROC_BIND_CLOSE:
3928 OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_CLOSE;
3929 break;
3930 default:
3931 gcc_unreachable ();
3932 }
3933 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3934 }
3935
3936 if (clauses->safelen_expr)
3937 {
3938 tree safelen_var;
3939
3940 gfc_init_se (&se, NULL);
3941 gfc_conv_expr (&se, clauses->safelen_expr);
3942 gfc_add_block_to_block (block, &se.pre);
3943 safelen_var = gfc_evaluate_now (se.expr, block);
3944 gfc_add_block_to_block (block, &se.post);
3945
3946 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SAFELEN);
3947 OMP_CLAUSE_SAFELEN_EXPR (c) = safelen_var;
3948 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3949 }
3950
3951 if (clauses->simdlen_expr)
3952 {
3953 if (declare_simd)
3954 {
3955 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMDLEN);
3956 OMP_CLAUSE_SIMDLEN_EXPR (c)
3957 = gfc_conv_constant_to_tree (clauses->simdlen_expr);
3958 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3959 }
3960 else
3961 {
3962 tree simdlen_var;
3963
3964 gfc_init_se (&se, NULL);
3965 gfc_conv_expr (&se, clauses->simdlen_expr);
3966 gfc_add_block_to_block (block, &se.pre);
3967 simdlen_var = gfc_evaluate_now (se.expr, block);
3968 gfc_add_block_to_block (block, &se.post);
3969
3970 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMDLEN);
3971 OMP_CLAUSE_SIMDLEN_EXPR (c) = simdlen_var;
3972 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3973 }
3974 }
3975
3976 if (clauses->num_teams_upper)
3977 {
3978 tree num_teams_lower = NULL_TREE, num_teams_upper;
3979
3980 gfc_init_se (&se, NULL);
3981 gfc_conv_expr (&se, clauses->num_teams_upper);
3982 gfc_add_block_to_block (block, &se.pre);
3983 num_teams_upper = gfc_evaluate_now (se.expr, block);
3984 gfc_add_block_to_block (block, &se.post);
3985
3986 if (clauses->num_teams_lower)
3987 {
3988 gfc_init_se (&se, NULL);
3989 gfc_conv_expr (&se, clauses->num_teams_lower);
3990 gfc_add_block_to_block (block, &se.pre);
3991 num_teams_lower = gfc_evaluate_now (se.expr, block);
3992 gfc_add_block_to_block (block, &se.post);
3993 }
3994 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_TEAMS);
3995 OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = num_teams_lower;
3996 OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = num_teams_upper;
3997 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3998 }
3999
4000 if (clauses->device)
4001 {
4002 tree device;
4003
4004 gfc_init_se (&se, NULL);
4005 gfc_conv_expr (&se, clauses->device);
4006 gfc_add_block_to_block (block, &se.pre);
4007 device = gfc_evaluate_now (se.expr, block);
4008 gfc_add_block_to_block (block, &se.post);
4009
4010 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEVICE);
4011 OMP_CLAUSE_DEVICE_ID (c) = device;
4012
4013 if (clauses->ancestor)
4014 OMP_CLAUSE_DEVICE_ANCESTOR (c) = 1;
4015
4016 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4017 }
4018
4019 if (clauses->thread_limit)
4020 {
4021 tree thread_limit;
4022
4023 gfc_init_se (&se, NULL);
4024 gfc_conv_expr (&se, clauses->thread_limit);
4025 gfc_add_block_to_block (block, &se.pre);
4026 thread_limit = gfc_evaluate_now (se.expr, block);
4027 gfc_add_block_to_block (block, &se.post);
4028
4029 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_THREAD_LIMIT);
4030 OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = thread_limit;
4031 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4032 }
4033
4034 chunk_size = NULL_TREE;
4035 if (clauses->dist_chunk_size)
4036 {
4037 gfc_init_se (&se, NULL);
4038 gfc_conv_expr (&se, clauses->dist_chunk_size);
4039 gfc_add_block_to_block (block, &se.pre);
4040 chunk_size = gfc_evaluate_now (se.expr, block);
4041 gfc_add_block_to_block (block, &se.post);
4042 }
4043
4044 if (clauses->dist_sched_kind != OMP_SCHED_NONE)
4045 {
4046 c = build_omp_clause (gfc_get_location (&where),
4047 OMP_CLAUSE_DIST_SCHEDULE);
4048 OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
4049 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4050 }
4051
4052 if (clauses->grainsize)
4053 {
4054 tree grainsize;
4055
4056 gfc_init_se (&se, NULL);
4057 gfc_conv_expr (&se, clauses->grainsize);
4058 gfc_add_block_to_block (block, &se.pre);
4059 grainsize = gfc_evaluate_now (se.expr, block);
4060 gfc_add_block_to_block (block, &se.post);
4061
4062 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_GRAINSIZE);
4063 OMP_CLAUSE_GRAINSIZE_EXPR (c) = grainsize;
4064 if (clauses->grainsize_strict)
4065 OMP_CLAUSE_GRAINSIZE_STRICT (c) = 1;
4066 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4067 }
4068
4069 if (clauses->num_tasks)
4070 {
4071 tree num_tasks;
4072
4073 gfc_init_se (&se, NULL);
4074 gfc_conv_expr (&se, clauses->num_tasks);
4075 gfc_add_block_to_block (block, &se.pre);
4076 num_tasks = gfc_evaluate_now (se.expr, block);
4077 gfc_add_block_to_block (block, &se.post);
4078
4079 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_TASKS);
4080 OMP_CLAUSE_NUM_TASKS_EXPR (c) = num_tasks;
4081 if (clauses->num_tasks_strict)
4082 OMP_CLAUSE_NUM_TASKS_STRICT (c) = 1;
4083 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4084 }
4085
4086 if (clauses->priority)
4087 {
4088 tree priority;
4089
4090 gfc_init_se (&se, NULL);
4091 gfc_conv_expr (&se, clauses->priority);
4092 gfc_add_block_to_block (block, &se.pre);
4093 priority = gfc_evaluate_now (se.expr, block);
4094 gfc_add_block_to_block (block, &se.post);
4095
4096 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PRIORITY);
4097 OMP_CLAUSE_PRIORITY_EXPR (c) = priority;
4098 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4099 }
4100
4101 if (clauses->detach)
4102 {
4103 tree detach;
4104
4105 gfc_init_se (&se, NULL);
4106 gfc_conv_expr (&se, clauses->detach);
4107 gfc_add_block_to_block (block, &se.pre);
4108 detach = se.expr;
4109 gfc_add_block_to_block (block, &se.post);
4110
4111 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DETACH);
4112 TREE_ADDRESSABLE (detach) = 1;
4113 OMP_CLAUSE_DECL (c) = detach;
4114 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4115 }
4116
4117 if (clauses->filter)
4118 {
4119 tree filter;
4120
4121 gfc_init_se (&se, NULL);
4122 gfc_conv_expr (&se, clauses->filter);
4123 gfc_add_block_to_block (block, &se.pre);
4124 filter = gfc_evaluate_now (se.expr, block);
4125 gfc_add_block_to_block (block, &se.post);
4126
4127 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FILTER);
4128 OMP_CLAUSE_FILTER_EXPR (c) = filter;
4129 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4130 }
4131
4132 if (clauses->hint)
4133 {
4134 tree hint;
4135
4136 gfc_init_se (&se, NULL);
4137 gfc_conv_expr (&se, clauses->hint);
4138 gfc_add_block_to_block (block, &se.pre);
4139 hint = gfc_evaluate_now (se.expr, block);
4140 gfc_add_block_to_block (block, &se.post);
4141
4142 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_HINT);
4143 OMP_CLAUSE_HINT_EXPR (c) = hint;
4144 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4145 }
4146
4147 if (clauses->simd)
4148 {
4149 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMD);
4150 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4151 }
4152 if (clauses->threads)
4153 {
4154 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_THREADS);
4155 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4156 }
4157 if (clauses->nogroup)
4158 {
4159 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOGROUP);
4160 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4161 }
4162
4163 for (int i = 0; i < OMP_DEFAULTMAP_CAT_NUM; i++)
4164 {
4165 if (clauses->defaultmap[i] == OMP_DEFAULTMAP_UNSET)
4166 continue;
4167 enum omp_clause_defaultmap_kind behavior, category;
4168 switch ((gfc_omp_defaultmap_category) i)
4169 {
4170 case OMP_DEFAULTMAP_CAT_UNCATEGORIZED:
4171 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
4172 break;
4173 case OMP_DEFAULTMAP_CAT_SCALAR:
4174 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR;
4175 break;
4176 case OMP_DEFAULTMAP_CAT_AGGREGATE:
4177 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE;
4178 break;
4179 case OMP_DEFAULTMAP_CAT_ALLOCATABLE:
4180 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALLOCATABLE;
4181 break;
4182 case OMP_DEFAULTMAP_CAT_POINTER:
4183 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER;
4184 break;
4185 default: gcc_unreachable ();
4186 }
4187 switch (clauses->defaultmap[i])
4188 {
4189 case OMP_DEFAULTMAP_ALLOC:
4190 behavior = OMP_CLAUSE_DEFAULTMAP_ALLOC;
4191 break;
4192 case OMP_DEFAULTMAP_TO: behavior = OMP_CLAUSE_DEFAULTMAP_TO; break;
4193 case OMP_DEFAULTMAP_FROM: behavior = OMP_CLAUSE_DEFAULTMAP_FROM; break;
4194 case OMP_DEFAULTMAP_TOFROM:
4195 behavior = OMP_CLAUSE_DEFAULTMAP_TOFROM;
4196 break;
4197 case OMP_DEFAULTMAP_FIRSTPRIVATE:
4198 behavior = OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
4199 break;
4200 case OMP_DEFAULTMAP_NONE: behavior = OMP_CLAUSE_DEFAULTMAP_NONE; break;
4201 case OMP_DEFAULTMAP_DEFAULT:
4202 behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
4203 break;
4204 default: gcc_unreachable ();
4205 }
4206 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEFAULTMAP);
4207 OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, behavior, category);
4208 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4209 }
4210
4211 if (clauses->depend_source)
4212 {
4213 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEPEND);
4214 OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_SOURCE;
4215 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4216 }
4217
4218 if (clauses->async)
4219 {
4220 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ASYNC);
4221 if (clauses->async_expr)
4222 OMP_CLAUSE_ASYNC_EXPR (c)
4223 = gfc_convert_expr_to_tree (block, clauses->async_expr);
4224 else
4225 OMP_CLAUSE_ASYNC_EXPR (c) = NULL;
4226 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4227 }
4228 if (clauses->seq)
4229 {
4230 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SEQ);
4231 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4232 }
4233 if (clauses->par_auto)
4234 {
4235 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_AUTO);
4236 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4237 }
4238 if (clauses->if_present)
4239 {
4240 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF_PRESENT);
4241 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4242 }
4243 if (clauses->finalize)
4244 {
4245 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FINALIZE);
4246 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4247 }
4248 if (clauses->independent)
4249 {
4250 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_INDEPENDENT);
4251 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4252 }
4253 if (clauses->wait_list)
4254 {
4255 gfc_expr_list *el;
4256
4257 for (el = clauses->wait_list; el; el = el->next)
4258 {
4259 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_WAIT);
4260 OMP_CLAUSE_DECL (c) = gfc_convert_expr_to_tree (block, el->expr);
4261 OMP_CLAUSE_CHAIN (c) = omp_clauses;
4262 omp_clauses = c;
4263 }
4264 }
4265 if (clauses->num_gangs_expr)
4266 {
4267 tree num_gangs_var
4268 = gfc_convert_expr_to_tree (block, clauses->num_gangs_expr);
4269 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_GANGS);
4270 OMP_CLAUSE_NUM_GANGS_EXPR (c) = num_gangs_var;
4271 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4272 }
4273 if (clauses->num_workers_expr)
4274 {
4275 tree num_workers_var
4276 = gfc_convert_expr_to_tree (block, clauses->num_workers_expr);
4277 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_WORKERS);
4278 OMP_CLAUSE_NUM_WORKERS_EXPR (c) = num_workers_var;
4279 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4280 }
4281 if (clauses->vector_length_expr)
4282 {
4283 tree vector_length_var
4284 = gfc_convert_expr_to_tree (block, clauses->vector_length_expr);
4285 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_VECTOR_LENGTH);
4286 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c) = vector_length_var;
4287 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4288 }
4289 if (clauses->tile_list)
4290 {
4291 vec<tree, va_gc> *tvec;
4292 gfc_expr_list *el;
4293
4294 vec_alloc (tvec, 4);
4295
4296 for (el = clauses->tile_list; el; el = el->next)
4297 vec_safe_push (tvec, gfc_convert_expr_to_tree (block, el->expr));
4298
4299 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_TILE);
4300 OMP_CLAUSE_TILE_LIST (c) = build_tree_list_vec (tvec);
4301 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4302 tvec->truncate (0);
4303 }
4304 if (clauses->vector)
4305 {
4306 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_VECTOR);
4307 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4308
4309 if (clauses->vector_expr)
4310 {
4311 tree vector_var
4312 = gfc_convert_expr_to_tree (block, clauses->vector_expr);
4313 OMP_CLAUSE_VECTOR_EXPR (c) = vector_var;
4314
4315 /* TODO: We're not capturing location information for individual
4316 clauses. However, if we have an expression attached to the
4317 clause, that one provides better location information. */
4318 OMP_CLAUSE_LOCATION (c)
4319 = gfc_get_location (&clauses->vector_expr->where);
4320 }
4321 }
4322 if (clauses->worker)
4323 {
4324 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_WORKER);
4325 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4326
4327 if (clauses->worker_expr)
4328 {
4329 tree worker_var
4330 = gfc_convert_expr_to_tree (block, clauses->worker_expr);
4331 OMP_CLAUSE_WORKER_EXPR (c) = worker_var;
4332
4333 /* TODO: We're not capturing location information for individual
4334 clauses. However, if we have an expression attached to the
4335 clause, that one provides better location information. */
4336 OMP_CLAUSE_LOCATION (c)
4337 = gfc_get_location (&clauses->worker_expr->where);
4338 }
4339 }
4340 if (clauses->gang)
4341 {
4342 tree arg;
4343 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_GANG);
4344 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4345
4346 if (clauses->gang_num_expr)
4347 {
4348 arg = gfc_convert_expr_to_tree (block, clauses->gang_num_expr);
4349 OMP_CLAUSE_GANG_EXPR (c) = arg;
4350
4351 /* TODO: We're not capturing location information for individual
4352 clauses. However, if we have an expression attached to the
4353 clause, that one provides better location information. */
4354 OMP_CLAUSE_LOCATION (c)
4355 = gfc_get_location (&clauses->gang_num_expr->where);
4356 }
4357
4358 if (clauses->gang_static)
4359 {
4360 arg = clauses->gang_static_expr
4361 ? gfc_convert_expr_to_tree (block, clauses->gang_static_expr)
4362 : integer_minus_one_node;
4363 OMP_CLAUSE_GANG_STATIC_EXPR (c) = arg;
4364 }
4365 }
4366 if (clauses->bind != OMP_BIND_UNSET)
4367 {
4368 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_BIND);
4369 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4370 switch (clauses->bind)
4371 {
4372 case OMP_BIND_TEAMS:
4373 OMP_CLAUSE_BIND_KIND (c) = OMP_CLAUSE_BIND_TEAMS;
4374 break;
4375 case OMP_BIND_PARALLEL:
4376 OMP_CLAUSE_BIND_KIND (c) = OMP_CLAUSE_BIND_PARALLEL;
4377 break;
4378 case OMP_BIND_THREAD:
4379 OMP_CLAUSE_BIND_KIND (c) = OMP_CLAUSE_BIND_THREAD;
4380 break;
4381 default:
4382 gcc_unreachable ();
4383 }
4384 }
4385 /* OpenACC 'nohost' clauses cannot appear here. */
4386 gcc_checking_assert (!clauses->nohost);
4387
4388 return nreverse (omp_clauses);
4389 }
4390
4391 /* Like gfc_trans_code, but force creation of a BIND_EXPR around it. */
4392
4393 static tree
gfc_trans_omp_code(gfc_code * code,bool force_empty)4394 gfc_trans_omp_code (gfc_code *code, bool force_empty)
4395 {
4396 tree stmt;
4397
4398 pushlevel ();
4399 stmt = gfc_trans_code (code);
4400 if (TREE_CODE (stmt) != BIND_EXPR)
4401 {
4402 if (!IS_EMPTY_STMT (stmt) || force_empty)
4403 {
4404 tree block = poplevel (1, 0);
4405 stmt = build3_v (BIND_EXPR, NULL, stmt, block);
4406 }
4407 else
4408 poplevel (0, 0);
4409 }
4410 else
4411 poplevel (0, 0);
4412 return stmt;
4413 }
4414
4415 /* Translate OpenACC 'parallel', 'kernels', 'serial', 'data', 'host_data'
4416 construct. */
4417
4418 static tree
gfc_trans_oacc_construct(gfc_code * code)4419 gfc_trans_oacc_construct (gfc_code *code)
4420 {
4421 stmtblock_t block;
4422 tree stmt, oacc_clauses;
4423 enum tree_code construct_code;
4424
4425 switch (code->op)
4426 {
4427 case EXEC_OACC_PARALLEL:
4428 construct_code = OACC_PARALLEL;
4429 break;
4430 case EXEC_OACC_KERNELS:
4431 construct_code = OACC_KERNELS;
4432 break;
4433 case EXEC_OACC_SERIAL:
4434 construct_code = OACC_SERIAL;
4435 break;
4436 case EXEC_OACC_DATA:
4437 construct_code = OACC_DATA;
4438 break;
4439 case EXEC_OACC_HOST_DATA:
4440 construct_code = OACC_HOST_DATA;
4441 break;
4442 default:
4443 gcc_unreachable ();
4444 }
4445
4446 gfc_start_block (&block);
4447 oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
4448 code->loc, false, true);
4449 pushlevel ();
4450 stmt = gfc_trans_omp_code (code->block->next, true);
4451 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
4452 stmt = build2_loc (gfc_get_location (&code->loc), construct_code,
4453 void_type_node, stmt, oacc_clauses);
4454 gfc_add_expr_to_block (&block, stmt);
4455 return gfc_finish_block (&block);
4456 }
4457
4458 /* update, enter_data, exit_data, cache. */
4459 static tree
gfc_trans_oacc_executable_directive(gfc_code * code)4460 gfc_trans_oacc_executable_directive (gfc_code *code)
4461 {
4462 stmtblock_t block;
4463 tree stmt, oacc_clauses;
4464 enum tree_code construct_code;
4465
4466 switch (code->op)
4467 {
4468 case EXEC_OACC_UPDATE:
4469 construct_code = OACC_UPDATE;
4470 break;
4471 case EXEC_OACC_ENTER_DATA:
4472 construct_code = OACC_ENTER_DATA;
4473 break;
4474 case EXEC_OACC_EXIT_DATA:
4475 construct_code = OACC_EXIT_DATA;
4476 break;
4477 case EXEC_OACC_CACHE:
4478 construct_code = OACC_CACHE;
4479 break;
4480 default:
4481 gcc_unreachable ();
4482 }
4483
4484 gfc_start_block (&block);
4485 oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
4486 code->loc, false, true);
4487 stmt = build1_loc (input_location, construct_code, void_type_node,
4488 oacc_clauses);
4489 gfc_add_expr_to_block (&block, stmt);
4490 return gfc_finish_block (&block);
4491 }
4492
4493 static tree
gfc_trans_oacc_wait_directive(gfc_code * code)4494 gfc_trans_oacc_wait_directive (gfc_code *code)
4495 {
4496 stmtblock_t block;
4497 tree stmt, t;
4498 vec<tree, va_gc> *args;
4499 int nparms = 0;
4500 gfc_expr_list *el;
4501 gfc_omp_clauses *clauses = code->ext.omp_clauses;
4502 location_t loc = input_location;
4503
4504 for (el = clauses->wait_list; el; el = el->next)
4505 nparms++;
4506
4507 vec_alloc (args, nparms + 2);
4508 stmt = builtin_decl_explicit (BUILT_IN_GOACC_WAIT);
4509
4510 gfc_start_block (&block);
4511
4512 if (clauses->async_expr)
4513 t = gfc_convert_expr_to_tree (&block, clauses->async_expr);
4514 else
4515 t = build_int_cst (integer_type_node, -2);
4516
4517 args->quick_push (t);
4518 args->quick_push (build_int_cst (integer_type_node, nparms));
4519
4520 for (el = clauses->wait_list; el; el = el->next)
4521 args->quick_push (gfc_convert_expr_to_tree (&block, el->expr));
4522
4523 stmt = build_call_expr_loc_vec (loc, stmt, args);
4524 gfc_add_expr_to_block (&block, stmt);
4525
4526 vec_free (args);
4527
4528 return gfc_finish_block (&block);
4529 }
4530
4531 static tree gfc_trans_omp_sections (gfc_code *, gfc_omp_clauses *);
4532 static tree gfc_trans_omp_workshare (gfc_code *, gfc_omp_clauses *);
4533
4534 static tree
gfc_trans_omp_atomic(gfc_code * code)4535 gfc_trans_omp_atomic (gfc_code *code)
4536 {
4537 gfc_code *atomic_code = code->block;
4538 gfc_se lse;
4539 gfc_se rse;
4540 gfc_se vse;
4541 gfc_expr *expr1, *expr2, *e, *capture_expr1 = NULL, *capture_expr2 = NULL;
4542 gfc_symbol *var;
4543 stmtblock_t block;
4544 tree lhsaddr, type, rhs, x, compare = NULL_TREE, comp_tgt = NULL_TREE;
4545 enum tree_code op = ERROR_MARK;
4546 enum tree_code aop = OMP_ATOMIC;
4547 bool var_on_left = false, else_branch = false;
4548 enum omp_memory_order mo, fail_mo;
4549 switch (atomic_code->ext.omp_clauses->memorder)
4550 {
4551 case OMP_MEMORDER_UNSET: mo = OMP_MEMORY_ORDER_UNSPECIFIED; break;
4552 case OMP_MEMORDER_ACQ_REL: mo = OMP_MEMORY_ORDER_ACQ_REL; break;
4553 case OMP_MEMORDER_ACQUIRE: mo = OMP_MEMORY_ORDER_ACQUIRE; break;
4554 case OMP_MEMORDER_RELAXED: mo = OMP_MEMORY_ORDER_RELAXED; break;
4555 case OMP_MEMORDER_RELEASE: mo = OMP_MEMORY_ORDER_RELEASE; break;
4556 case OMP_MEMORDER_SEQ_CST: mo = OMP_MEMORY_ORDER_SEQ_CST; break;
4557 default: gcc_unreachable ();
4558 }
4559 switch (atomic_code->ext.omp_clauses->fail)
4560 {
4561 case OMP_MEMORDER_UNSET: fail_mo = OMP_FAIL_MEMORY_ORDER_UNSPECIFIED; break;
4562 case OMP_MEMORDER_ACQUIRE: fail_mo = OMP_FAIL_MEMORY_ORDER_ACQUIRE; break;
4563 case OMP_MEMORDER_RELAXED: fail_mo = OMP_FAIL_MEMORY_ORDER_RELAXED; break;
4564 case OMP_MEMORDER_SEQ_CST: fail_mo = OMP_FAIL_MEMORY_ORDER_SEQ_CST; break;
4565 default: gcc_unreachable ();
4566 }
4567 mo = (omp_memory_order) (mo | fail_mo);
4568
4569 code = code->block->next;
4570 if (atomic_code->ext.omp_clauses->compare)
4571 {
4572 gfc_expr *comp_expr;
4573 if (code->op == EXEC_IF)
4574 {
4575 comp_expr = code->block->expr1;
4576 gcc_assert (code->block->next->op == EXEC_ASSIGN);
4577 expr1 = code->block->next->expr1;
4578 expr2 = code->block->next->expr2;
4579 if (code->block->block)
4580 {
4581 gcc_assert (atomic_code->ext.omp_clauses->capture
4582 && code->block->block->next->op == EXEC_ASSIGN);
4583 else_branch = true;
4584 aop = OMP_ATOMIC_CAPTURE_OLD;
4585 capture_expr1 = code->block->block->next->expr1;
4586 capture_expr2 = code->block->block->next->expr2;
4587 }
4588 else if (atomic_code->ext.omp_clauses->capture)
4589 {
4590 gcc_assert (code->next->op == EXEC_ASSIGN);
4591 aop = OMP_ATOMIC_CAPTURE_NEW;
4592 capture_expr1 = code->next->expr1;
4593 capture_expr2 = code->next->expr2;
4594 }
4595 }
4596 else
4597 {
4598 gcc_assert (atomic_code->ext.omp_clauses->capture
4599 && code->op == EXEC_ASSIGN
4600 && code->next->op == EXEC_IF);
4601 aop = OMP_ATOMIC_CAPTURE_OLD;
4602 capture_expr1 = code->expr1;
4603 capture_expr2 = code->expr2;
4604 expr1 = code->next->block->next->expr1;
4605 expr2 = code->next->block->next->expr2;
4606 comp_expr = code->next->block->expr1;
4607 }
4608 gfc_init_se (&lse, NULL);
4609 gfc_conv_expr (&lse, comp_expr->value.op.op2);
4610 gfc_add_block_to_block (&block, &lse.pre);
4611 compare = lse.expr;
4612 var = expr1->symtree->n.sym;
4613 }
4614 else
4615 {
4616 gcc_assert (code->op == EXEC_ASSIGN);
4617 expr1 = code->expr1;
4618 expr2 = code->expr2;
4619 if (atomic_code->ext.omp_clauses->capture
4620 && (expr2->expr_type == EXPR_VARIABLE
4621 || (expr2->expr_type == EXPR_FUNCTION
4622 && expr2->value.function.isym
4623 && expr2->value.function.isym->id == GFC_ISYM_CONVERSION
4624 && (expr2->value.function.actual->expr->expr_type
4625 == EXPR_VARIABLE))))
4626 {
4627 capture_expr1 = expr1;
4628 capture_expr2 = expr2;
4629 expr1 = code->next->expr1;
4630 expr2 = code->next->expr2;
4631 aop = OMP_ATOMIC_CAPTURE_OLD;
4632 }
4633 else if (atomic_code->ext.omp_clauses->capture)
4634 {
4635 aop = OMP_ATOMIC_CAPTURE_NEW;
4636 capture_expr1 = code->next->expr1;
4637 capture_expr2 = code->next->expr2;
4638 }
4639 var = expr1->symtree->n.sym;
4640 }
4641
4642 gfc_init_se (&lse, NULL);
4643 gfc_init_se (&rse, NULL);
4644 gfc_init_se (&vse, NULL);
4645 gfc_start_block (&block);
4646
4647 if (((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
4648 != GFC_OMP_ATOMIC_WRITE)
4649 && expr2->expr_type == EXPR_FUNCTION
4650 && expr2->value.function.isym
4651 && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
4652 expr2 = expr2->value.function.actual->expr;
4653
4654 if ((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
4655 == GFC_OMP_ATOMIC_READ)
4656 {
4657 gfc_conv_expr (&vse, expr1);
4658 gfc_add_block_to_block (&block, &vse.pre);
4659
4660 gfc_conv_expr (&lse, expr2);
4661 gfc_add_block_to_block (&block, &lse.pre);
4662 type = TREE_TYPE (lse.expr);
4663 lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
4664
4665 x = build1 (OMP_ATOMIC_READ, type, lhsaddr);
4666 OMP_ATOMIC_MEMORY_ORDER (x) = mo;
4667 x = convert (TREE_TYPE (vse.expr), x);
4668 gfc_add_modify (&block, vse.expr, x);
4669
4670 gfc_add_block_to_block (&block, &lse.pre);
4671 gfc_add_block_to_block (&block, &rse.pre);
4672
4673 return gfc_finish_block (&block);
4674 }
4675
4676 if (capture_expr2
4677 && capture_expr2->expr_type == EXPR_FUNCTION
4678 && capture_expr2->value.function.isym
4679 && capture_expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
4680 capture_expr2 = capture_expr2->value.function.actual->expr;
4681 gcc_assert (!capture_expr2 || capture_expr2->expr_type == EXPR_VARIABLE);
4682
4683 if (aop == OMP_ATOMIC_CAPTURE_OLD)
4684 {
4685 gfc_conv_expr (&vse, capture_expr1);
4686 gfc_add_block_to_block (&block, &vse.pre);
4687 gfc_conv_expr (&lse, capture_expr2);
4688 gfc_add_block_to_block (&block, &lse.pre);
4689 gfc_init_se (&lse, NULL);
4690 }
4691
4692 gfc_conv_expr (&lse, expr1);
4693 gfc_add_block_to_block (&block, &lse.pre);
4694 type = TREE_TYPE (lse.expr);
4695 lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
4696
4697 if (((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
4698 == GFC_OMP_ATOMIC_WRITE)
4699 || (atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_SWAP)
4700 || compare)
4701 {
4702 gfc_conv_expr (&rse, expr2);
4703 gfc_add_block_to_block (&block, &rse.pre);
4704 }
4705 else if (expr2->expr_type == EXPR_OP)
4706 {
4707 gfc_expr *e;
4708 switch (expr2->value.op.op)
4709 {
4710 case INTRINSIC_PLUS:
4711 op = PLUS_EXPR;
4712 break;
4713 case INTRINSIC_TIMES:
4714 op = MULT_EXPR;
4715 break;
4716 case INTRINSIC_MINUS:
4717 op = MINUS_EXPR;
4718 break;
4719 case INTRINSIC_DIVIDE:
4720 if (expr2->ts.type == BT_INTEGER)
4721 op = TRUNC_DIV_EXPR;
4722 else
4723 op = RDIV_EXPR;
4724 break;
4725 case INTRINSIC_AND:
4726 op = TRUTH_ANDIF_EXPR;
4727 break;
4728 case INTRINSIC_OR:
4729 op = TRUTH_ORIF_EXPR;
4730 break;
4731 case INTRINSIC_EQV:
4732 op = EQ_EXPR;
4733 break;
4734 case INTRINSIC_NEQV:
4735 op = NE_EXPR;
4736 break;
4737 default:
4738 gcc_unreachable ();
4739 }
4740 e = expr2->value.op.op1;
4741 if (e->expr_type == EXPR_FUNCTION
4742 && e->value.function.isym
4743 && e->value.function.isym->id == GFC_ISYM_CONVERSION)
4744 e = e->value.function.actual->expr;
4745 if (e->expr_type == EXPR_VARIABLE
4746 && e->symtree != NULL
4747 && e->symtree->n.sym == var)
4748 {
4749 expr2 = expr2->value.op.op2;
4750 var_on_left = true;
4751 }
4752 else
4753 {
4754 e = expr2->value.op.op2;
4755 if (e->expr_type == EXPR_FUNCTION
4756 && e->value.function.isym
4757 && e->value.function.isym->id == GFC_ISYM_CONVERSION)
4758 e = e->value.function.actual->expr;
4759 gcc_assert (e->expr_type == EXPR_VARIABLE
4760 && e->symtree != NULL
4761 && e->symtree->n.sym == var);
4762 expr2 = expr2->value.op.op1;
4763 var_on_left = false;
4764 }
4765 gfc_conv_expr (&rse, expr2);
4766 gfc_add_block_to_block (&block, &rse.pre);
4767 }
4768 else
4769 {
4770 gcc_assert (expr2->expr_type == EXPR_FUNCTION);
4771 switch (expr2->value.function.isym->id)
4772 {
4773 case GFC_ISYM_MIN:
4774 op = MIN_EXPR;
4775 break;
4776 case GFC_ISYM_MAX:
4777 op = MAX_EXPR;
4778 break;
4779 case GFC_ISYM_IAND:
4780 op = BIT_AND_EXPR;
4781 break;
4782 case GFC_ISYM_IOR:
4783 op = BIT_IOR_EXPR;
4784 break;
4785 case GFC_ISYM_IEOR:
4786 op = BIT_XOR_EXPR;
4787 break;
4788 default:
4789 gcc_unreachable ();
4790 }
4791 e = expr2->value.function.actual->expr;
4792 if (e->expr_type == EXPR_FUNCTION
4793 && e->value.function.isym
4794 && e->value.function.isym->id == GFC_ISYM_CONVERSION)
4795 e = e->value.function.actual->expr;
4796 gcc_assert (e->expr_type == EXPR_VARIABLE
4797 && e->symtree != NULL
4798 && e->symtree->n.sym == var);
4799
4800 gfc_conv_expr (&rse, expr2->value.function.actual->next->expr);
4801 gfc_add_block_to_block (&block, &rse.pre);
4802 if (expr2->value.function.actual->next->next != NULL)
4803 {
4804 tree accum = gfc_create_var (TREE_TYPE (rse.expr), NULL);
4805 gfc_actual_arglist *arg;
4806
4807 gfc_add_modify (&block, accum, rse.expr);
4808 for (arg = expr2->value.function.actual->next->next; arg;
4809 arg = arg->next)
4810 {
4811 gfc_init_block (&rse.pre);
4812 gfc_conv_expr (&rse, arg->expr);
4813 gfc_add_block_to_block (&block, &rse.pre);
4814 x = fold_build2_loc (input_location, op, TREE_TYPE (accum),
4815 accum, rse.expr);
4816 gfc_add_modify (&block, accum, x);
4817 }
4818
4819 rse.expr = accum;
4820 }
4821
4822 expr2 = expr2->value.function.actual->next->expr;
4823 }
4824
4825 lhsaddr = save_expr (lhsaddr);
4826 if (TREE_CODE (lhsaddr) != SAVE_EXPR
4827 && (TREE_CODE (lhsaddr) != ADDR_EXPR
4828 || !VAR_P (TREE_OPERAND (lhsaddr, 0))))
4829 {
4830 /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
4831 it even after unsharing function body. */
4832 tree var = create_tmp_var_raw (TREE_TYPE (lhsaddr));
4833 DECL_CONTEXT (var) = current_function_decl;
4834 lhsaddr = build4 (TARGET_EXPR, TREE_TYPE (lhsaddr), var, lhsaddr,
4835 NULL_TREE, NULL_TREE);
4836 }
4837
4838 if (compare)
4839 {
4840 tree var = create_tmp_var_raw (TREE_TYPE (lhsaddr));
4841 DECL_CONTEXT (var) = current_function_decl;
4842 lhsaddr = build4 (TARGET_EXPR, TREE_TYPE (lhsaddr), var, lhsaddr, NULL,
4843 NULL);
4844 lse.expr = build_fold_indirect_ref_loc (input_location, lhsaddr);
4845 compare = convert (TREE_TYPE (lse.expr), compare);
4846 compare = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
4847 lse.expr, compare);
4848 }
4849
4850 if (expr2->expr_type == EXPR_VARIABLE || compare)
4851 rhs = rse.expr;
4852 else
4853 rhs = gfc_evaluate_now (rse.expr, &block);
4854
4855 if (((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
4856 == GFC_OMP_ATOMIC_WRITE)
4857 || (atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_SWAP)
4858 || compare)
4859 x = rhs;
4860 else
4861 {
4862 x = convert (TREE_TYPE (rhs),
4863 build_fold_indirect_ref_loc (input_location, lhsaddr));
4864 if (var_on_left)
4865 x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), x, rhs);
4866 else
4867 x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), rhs, x);
4868 }
4869
4870 if (TREE_CODE (TREE_TYPE (rhs)) == COMPLEX_TYPE
4871 && TREE_CODE (type) != COMPLEX_TYPE)
4872 x = fold_build1_loc (input_location, REALPART_EXPR,
4873 TREE_TYPE (TREE_TYPE (rhs)), x);
4874
4875 gfc_add_block_to_block (&block, &lse.pre);
4876 gfc_add_block_to_block (&block, &rse.pre);
4877
4878 if (aop == OMP_ATOMIC_CAPTURE_NEW)
4879 {
4880 gfc_conv_expr (&vse, capture_expr1);
4881 gfc_add_block_to_block (&block, &vse.pre);
4882 gfc_add_block_to_block (&block, &lse.pre);
4883 }
4884
4885 if (compare && else_branch)
4886 {
4887 tree var2 = create_tmp_var_raw (boolean_type_node);
4888 DECL_CONTEXT (var2) = current_function_decl;
4889 comp_tgt = build4 (TARGET_EXPR, boolean_type_node, var2,
4890 boolean_false_node, NULL, NULL);
4891 compare = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (var2),
4892 var2, compare);
4893 TREE_OPERAND (compare, 0) = comp_tgt;
4894 compare = omit_one_operand_loc (input_location, boolean_type_node,
4895 compare, comp_tgt);
4896 }
4897
4898 if (compare)
4899 x = build3_loc (input_location, COND_EXPR, type, compare,
4900 convert (type, x), lse.expr);
4901
4902 if (aop == OMP_ATOMIC)
4903 {
4904 x = build2_v (OMP_ATOMIC, lhsaddr, convert (type, x));
4905 OMP_ATOMIC_MEMORY_ORDER (x) = mo;
4906 OMP_ATOMIC_WEAK (x) = atomic_code->ext.omp_clauses->weak;
4907 gfc_add_expr_to_block (&block, x);
4908 }
4909 else
4910 {
4911 x = build2 (aop, type, lhsaddr, convert (type, x));
4912 OMP_ATOMIC_MEMORY_ORDER (x) = mo;
4913 OMP_ATOMIC_WEAK (x) = atomic_code->ext.omp_clauses->weak;
4914 if (compare && else_branch)
4915 {
4916 tree vtmp = create_tmp_var_raw (TREE_TYPE (x));
4917 DECL_CONTEXT (vtmp) = current_function_decl;
4918 x = fold_build2_loc (input_location, MODIFY_EXPR,
4919 TREE_TYPE (vtmp), vtmp, x);
4920 vtmp = build4 (TARGET_EXPR, TREE_TYPE (vtmp), vtmp,
4921 build_zero_cst (TREE_TYPE (vtmp)), NULL, NULL);
4922 TREE_OPERAND (x, 0) = vtmp;
4923 tree x2 = convert (TREE_TYPE (vse.expr), vtmp);
4924 x2 = fold_build2_loc (input_location, MODIFY_EXPR,
4925 TREE_TYPE (vse.expr), vse.expr, x2);
4926 x2 = build3_loc (input_location, COND_EXPR, void_type_node, comp_tgt,
4927 void_node, x2);
4928 x = omit_one_operand_loc (input_location, TREE_TYPE (x2), x2, x);
4929 gfc_add_expr_to_block (&block, x);
4930 }
4931 else
4932 {
4933 x = convert (TREE_TYPE (vse.expr), x);
4934 gfc_add_modify (&block, vse.expr, x);
4935 }
4936 }
4937
4938 return gfc_finish_block (&block);
4939 }
4940
4941 static tree
gfc_trans_omp_barrier(void)4942 gfc_trans_omp_barrier (void)
4943 {
4944 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
4945 return build_call_expr_loc (input_location, decl, 0);
4946 }
4947
4948 static tree
gfc_trans_omp_cancel(gfc_code * code)4949 gfc_trans_omp_cancel (gfc_code *code)
4950 {
4951 int mask = 0;
4952 tree ifc = boolean_true_node;
4953 stmtblock_t block;
4954 switch (code->ext.omp_clauses->cancel)
4955 {
4956 case OMP_CANCEL_PARALLEL: mask = 1; break;
4957 case OMP_CANCEL_DO: mask = 2; break;
4958 case OMP_CANCEL_SECTIONS: mask = 4; break;
4959 case OMP_CANCEL_TASKGROUP: mask = 8; break;
4960 default: gcc_unreachable ();
4961 }
4962 gfc_start_block (&block);
4963 if (code->ext.omp_clauses->if_expr
4964 || code->ext.omp_clauses->if_exprs[OMP_IF_CANCEL])
4965 {
4966 gfc_se se;
4967 tree if_var;
4968
4969 gcc_assert ((code->ext.omp_clauses->if_expr == NULL)
4970 ^ (code->ext.omp_clauses->if_exprs[OMP_IF_CANCEL] == NULL));
4971 gfc_init_se (&se, NULL);
4972 gfc_conv_expr (&se, code->ext.omp_clauses->if_expr != NULL
4973 ? code->ext.omp_clauses->if_expr
4974 : code->ext.omp_clauses->if_exprs[OMP_IF_CANCEL]);
4975 gfc_add_block_to_block (&block, &se.pre);
4976 if_var = gfc_evaluate_now (se.expr, &block);
4977 gfc_add_block_to_block (&block, &se.post);
4978 tree type = TREE_TYPE (if_var);
4979 ifc = fold_build2_loc (input_location, NE_EXPR,
4980 boolean_type_node, if_var,
4981 build_zero_cst (type));
4982 }
4983 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
4984 tree c_bool_type = TREE_TYPE (TREE_TYPE (decl));
4985 ifc = fold_convert (c_bool_type, ifc);
4986 gfc_add_expr_to_block (&block,
4987 build_call_expr_loc (input_location, decl, 2,
4988 build_int_cst (integer_type_node,
4989 mask), ifc));
4990 return gfc_finish_block (&block);
4991 }
4992
4993 static tree
gfc_trans_omp_cancellation_point(gfc_code * code)4994 gfc_trans_omp_cancellation_point (gfc_code *code)
4995 {
4996 int mask = 0;
4997 switch (code->ext.omp_clauses->cancel)
4998 {
4999 case OMP_CANCEL_PARALLEL: mask = 1; break;
5000 case OMP_CANCEL_DO: mask = 2; break;
5001 case OMP_CANCEL_SECTIONS: mask = 4; break;
5002 case OMP_CANCEL_TASKGROUP: mask = 8; break;
5003 default: gcc_unreachable ();
5004 }
5005 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCELLATION_POINT);
5006 return build_call_expr_loc (input_location, decl, 1,
5007 build_int_cst (integer_type_node, mask));
5008 }
5009
5010 static tree
gfc_trans_omp_critical(gfc_code * code)5011 gfc_trans_omp_critical (gfc_code *code)
5012 {
5013 stmtblock_t block;
5014 tree stmt, name = NULL_TREE;
5015 if (code->ext.omp_clauses->critical_name != NULL)
5016 name = get_identifier (code->ext.omp_clauses->critical_name);
5017 gfc_start_block (&block);
5018 stmt = make_node (OMP_CRITICAL);
5019 TREE_TYPE (stmt) = void_type_node;
5020 OMP_CRITICAL_BODY (stmt) = gfc_trans_code (code->block->next);
5021 OMP_CRITICAL_NAME (stmt) = name;
5022 OMP_CRITICAL_CLAUSES (stmt) = gfc_trans_omp_clauses (&block,
5023 code->ext.omp_clauses,
5024 code->loc);
5025 gfc_add_expr_to_block (&block, stmt);
5026 return gfc_finish_block (&block);
5027 }
5028
5029 typedef struct dovar_init_d {
5030 tree var;
5031 tree init;
5032 } dovar_init;
5033
5034
5035 static tree
gfc_trans_omp_do(gfc_code * code,gfc_exec_op op,stmtblock_t * pblock,gfc_omp_clauses * do_clauses,tree par_clauses)5036 gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
5037 gfc_omp_clauses *do_clauses, tree par_clauses)
5038 {
5039 gfc_se se;
5040 tree dovar, stmt, from, to, step, type, init, cond, incr, orig_decls;
5041 tree count = NULL_TREE, cycle_label, tmp, omp_clauses;
5042 stmtblock_t block;
5043 stmtblock_t body;
5044 gfc_omp_clauses *clauses = code->ext.omp_clauses;
5045 int i, collapse = clauses->collapse;
5046 vec<dovar_init> inits = vNULL;
5047 dovar_init *di;
5048 unsigned ix;
5049 vec<tree, va_heap, vl_embed> *saved_doacross_steps = doacross_steps;
5050 gfc_expr_list *tile = do_clauses ? do_clauses->tile_list : clauses->tile_list;
5051
5052 /* Both collapsed and tiled loops are lowered the same way. In
5053 OpenACC, those clauses are not compatible, so prioritize the tile
5054 clause, if present. */
5055 if (tile)
5056 {
5057 collapse = 0;
5058 for (gfc_expr_list *el = tile; el; el = el->next)
5059 collapse++;
5060 }
5061
5062 doacross_steps = NULL;
5063 if (clauses->orderedc)
5064 collapse = clauses->orderedc;
5065 if (collapse <= 0)
5066 collapse = 1;
5067
5068 code = code->block->next;
5069 gcc_assert (code->op == EXEC_DO);
5070
5071 init = make_tree_vec (collapse);
5072 cond = make_tree_vec (collapse);
5073 incr = make_tree_vec (collapse);
5074 orig_decls = clauses->orderedc ? make_tree_vec (collapse) : NULL_TREE;
5075
5076 if (pblock == NULL)
5077 {
5078 gfc_start_block (&block);
5079 pblock = █
5080 }
5081
5082 /* simd schedule modifier is only useful for composite do simd and other
5083 constructs including that, where gfc_trans_omp_do is only called
5084 on the simd construct and DO's clauses are translated elsewhere. */
5085 do_clauses->sched_simd = false;
5086
5087 omp_clauses = gfc_trans_omp_clauses (pblock, do_clauses, code->loc);
5088
5089 for (i = 0; i < collapse; i++)
5090 {
5091 int simple = 0;
5092 int dovar_found = 0;
5093 tree dovar_decl;
5094
5095 if (clauses)
5096 {
5097 gfc_omp_namelist *n = NULL;
5098 if (op == EXEC_OMP_SIMD && collapse == 1)
5099 for (n = clauses->lists[OMP_LIST_LINEAR];
5100 n != NULL; n = n->next)
5101 if (code->ext.iterator->var->symtree->n.sym == n->sym)
5102 {
5103 dovar_found = 3;
5104 break;
5105 }
5106 if (n == NULL && op != EXEC_OMP_DISTRIBUTE)
5107 for (n = clauses->lists[OMP_LIST_LASTPRIVATE];
5108 n != NULL; n = n->next)
5109 if (code->ext.iterator->var->symtree->n.sym == n->sym)
5110 {
5111 dovar_found = 2;
5112 break;
5113 }
5114 if (n == NULL)
5115 for (n = clauses->lists[OMP_LIST_PRIVATE]; n != NULL; n = n->next)
5116 if (code->ext.iterator->var->symtree->n.sym == n->sym)
5117 {
5118 dovar_found = 1;
5119 break;
5120 }
5121 }
5122
5123 /* Evaluate all the expressions in the iterator. */
5124 gfc_init_se (&se, NULL);
5125 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
5126 gfc_add_block_to_block (pblock, &se.pre);
5127 dovar = se.expr;
5128 type = TREE_TYPE (dovar);
5129 gcc_assert (TREE_CODE (type) == INTEGER_TYPE);
5130
5131 gfc_init_se (&se, NULL);
5132 gfc_conv_expr_val (&se, code->ext.iterator->start);
5133 gfc_add_block_to_block (pblock, &se.pre);
5134 from = gfc_evaluate_now (se.expr, pblock);
5135
5136 gfc_init_se (&se, NULL);
5137 gfc_conv_expr_val (&se, code->ext.iterator->end);
5138 gfc_add_block_to_block (pblock, &se.pre);
5139 to = gfc_evaluate_now (se.expr, pblock);
5140
5141 gfc_init_se (&se, NULL);
5142 gfc_conv_expr_val (&se, code->ext.iterator->step);
5143 gfc_add_block_to_block (pblock, &se.pre);
5144 step = gfc_evaluate_now (se.expr, pblock);
5145 dovar_decl = dovar;
5146
5147 /* Special case simple loops. */
5148 if (VAR_P (dovar))
5149 {
5150 if (integer_onep (step))
5151 simple = 1;
5152 else if (tree_int_cst_equal (step, integer_minus_one_node))
5153 simple = -1;
5154 }
5155 else
5156 dovar_decl
5157 = gfc_trans_omp_variable (code->ext.iterator->var->symtree->n.sym,
5158 false);
5159
5160 /* Loop body. */
5161 if (simple)
5162 {
5163 TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, dovar, from);
5164 /* The condition should not be folded. */
5165 TREE_VEC_ELT (cond, i) = build2_loc (input_location, simple > 0
5166 ? LE_EXPR : GE_EXPR,
5167 logical_type_node, dovar, to);
5168 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR,
5169 type, dovar, step);
5170 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location,
5171 MODIFY_EXPR,
5172 type, dovar,
5173 TREE_VEC_ELT (incr, i));
5174 }
5175 else
5176 {
5177 /* STEP is not 1 or -1. Use:
5178 for (count = 0; count < (to + step - from) / step; count++)
5179 {
5180 dovar = from + count * step;
5181 body;
5182 cycle_label:;
5183 } */
5184 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, step, from);
5185 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, to, tmp);
5186 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, type, tmp,
5187 step);
5188 tmp = gfc_evaluate_now (tmp, pblock);
5189 count = gfc_create_var (type, "count");
5190 TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, count,
5191 build_int_cst (type, 0));
5192 /* The condition should not be folded. */
5193 TREE_VEC_ELT (cond, i) = build2_loc (input_location, LT_EXPR,
5194 logical_type_node,
5195 count, tmp);
5196 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR,
5197 type, count,
5198 build_int_cst (type, 1));
5199 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location,
5200 MODIFY_EXPR, type, count,
5201 TREE_VEC_ELT (incr, i));
5202
5203 /* Initialize DOVAR. */
5204 tmp = fold_build2_loc (input_location, MULT_EXPR, type, count, step);
5205 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, from, tmp);
5206 dovar_init e = {dovar, tmp};
5207 inits.safe_push (e);
5208 if (clauses->orderedc)
5209 {
5210 if (doacross_steps == NULL)
5211 vec_safe_grow_cleared (doacross_steps, clauses->orderedc, true);
5212 (*doacross_steps)[i] = step;
5213 }
5214 }
5215 if (orig_decls)
5216 TREE_VEC_ELT (orig_decls, i) = dovar_decl;
5217
5218 if (dovar_found == 3
5219 && op == EXEC_OMP_SIMD
5220 && collapse == 1
5221 && !simple)
5222 {
5223 for (tmp = omp_clauses; tmp; tmp = OMP_CLAUSE_CHAIN (tmp))
5224 if (OMP_CLAUSE_CODE (tmp) == OMP_CLAUSE_LINEAR
5225 && OMP_CLAUSE_DECL (tmp) == dovar)
5226 {
5227 OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
5228 break;
5229 }
5230 }
5231 if (!dovar_found && op == EXEC_OMP_SIMD)
5232 {
5233 if (collapse == 1)
5234 {
5235 tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
5236 OMP_CLAUSE_LINEAR_STEP (tmp) = step;
5237 OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
5238 OMP_CLAUSE_DECL (tmp) = dovar_decl;
5239 omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
5240 }
5241 if (!simple)
5242 dovar_found = 3;
5243 }
5244 else if (!dovar_found && !simple)
5245 {
5246 tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
5247 OMP_CLAUSE_DECL (tmp) = dovar_decl;
5248 omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
5249 }
5250 if (dovar_found > 1)
5251 {
5252 tree c = NULL;
5253
5254 tmp = NULL;
5255 if (!simple)
5256 {
5257 /* If dovar is lastprivate, but different counter is used,
5258 dovar += step needs to be added to
5259 OMP_CLAUSE_LASTPRIVATE_STMT, otherwise the copied dovar
5260 will have the value on entry of the last loop, rather
5261 than value after iterator increment. */
5262 if (clauses->orderedc)
5263 {
5264 if (clauses->collapse <= 1 || i >= clauses->collapse)
5265 tmp = count;
5266 else
5267 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5268 type, count, build_one_cst (type));
5269 tmp = fold_build2_loc (input_location, MULT_EXPR, type,
5270 tmp, step);
5271 tmp = fold_build2_loc (input_location, PLUS_EXPR, type,
5272 from, tmp);
5273 }
5274 else
5275 {
5276 tmp = gfc_evaluate_now (step, pblock);
5277 tmp = fold_build2_loc (input_location, PLUS_EXPR, type,
5278 dovar, tmp);
5279 }
5280 tmp = fold_build2_loc (input_location, MODIFY_EXPR, type,
5281 dovar, tmp);
5282 for (c = omp_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5283 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5284 && OMP_CLAUSE_DECL (c) == dovar_decl)
5285 {
5286 OMP_CLAUSE_LASTPRIVATE_STMT (c) = tmp;
5287 break;
5288 }
5289 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5290 && OMP_CLAUSE_DECL (c) == dovar_decl)
5291 {
5292 OMP_CLAUSE_LINEAR_STMT (c) = tmp;
5293 break;
5294 }
5295 }
5296 if (c == NULL && op == EXEC_OMP_DO && par_clauses != NULL)
5297 {
5298 for (c = par_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5299 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5300 && OMP_CLAUSE_DECL (c) == dovar_decl)
5301 {
5302 tree l = build_omp_clause (input_location,
5303 OMP_CLAUSE_LASTPRIVATE);
5304 if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
5305 OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (l) = 1;
5306 OMP_CLAUSE_DECL (l) = dovar_decl;
5307 OMP_CLAUSE_CHAIN (l) = omp_clauses;
5308 OMP_CLAUSE_LASTPRIVATE_STMT (l) = tmp;
5309 omp_clauses = l;
5310 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_SHARED);
5311 break;
5312 }
5313 }
5314 gcc_assert (simple || c != NULL);
5315 }
5316 if (!simple)
5317 {
5318 if (op != EXEC_OMP_SIMD || dovar_found == 1)
5319 tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
5320 else if (collapse == 1)
5321 {
5322 tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
5323 OMP_CLAUSE_LINEAR_STEP (tmp) = build_int_cst (type, 1);
5324 OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
5325 OMP_CLAUSE_LINEAR_NO_COPYOUT (tmp) = 1;
5326 }
5327 else
5328 tmp = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
5329 OMP_CLAUSE_DECL (tmp) = count;
5330 omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
5331 }
5332
5333 if (i + 1 < collapse)
5334 code = code->block->next;
5335 }
5336
5337 if (pblock != &block)
5338 {
5339 pushlevel ();
5340 gfc_start_block (&block);
5341 }
5342
5343 gfc_start_block (&body);
5344
5345 FOR_EACH_VEC_ELT (inits, ix, di)
5346 gfc_add_modify (&body, di->var, di->init);
5347 inits.release ();
5348
5349 /* Cycle statement is implemented with a goto. Exit statement must not be
5350 present for this loop. */
5351 cycle_label = gfc_build_label_decl (NULL_TREE);
5352
5353 /* Put these labels where they can be found later. */
5354
5355 code->cycle_label = cycle_label;
5356 code->exit_label = NULL_TREE;
5357
5358 /* Main loop body. */
5359 if (clauses->lists[OMP_LIST_REDUCTION_INSCAN])
5360 {
5361 gcc_assert (code->block->next->next->op == EXEC_OMP_SCAN);
5362 gcc_assert (code->block->next->next->next->next == NULL);
5363 locus *cloc = &code->block->next->next->loc;
5364 location_t loc = gfc_get_location (cloc);
5365
5366 gfc_code code2 = *code->block->next;
5367 code2.next = NULL;
5368 tmp = gfc_trans_code (&code2);
5369 tmp = build2 (OMP_SCAN, void_type_node, tmp, NULL_TREE);
5370 SET_EXPR_LOCATION (tmp, loc);
5371 gfc_add_expr_to_block (&body, tmp);
5372 input_location = loc;
5373 tree c = gfc_trans_omp_clauses (&body,
5374 code->block->next->next->ext.omp_clauses,
5375 *cloc);
5376 code2 = *code->block->next->next->next;
5377 code2.next = NULL;
5378 tmp = gfc_trans_code (&code2);
5379 tmp = build2 (OMP_SCAN, void_type_node, tmp, c);
5380 SET_EXPR_LOCATION (tmp, loc);
5381 }
5382 else
5383 tmp = gfc_trans_omp_code (code->block->next, true);
5384 gfc_add_expr_to_block (&body, tmp);
5385
5386 /* Label for cycle statements (if needed). */
5387 if (TREE_USED (cycle_label))
5388 {
5389 tmp = build1_v (LABEL_EXPR, cycle_label);
5390 gfc_add_expr_to_block (&body, tmp);
5391 }
5392
5393 /* End of loop body. */
5394 switch (op)
5395 {
5396 case EXEC_OMP_SIMD: stmt = make_node (OMP_SIMD); break;
5397 case EXEC_OMP_DO: stmt = make_node (OMP_FOR); break;
5398 case EXEC_OMP_DISTRIBUTE: stmt = make_node (OMP_DISTRIBUTE); break;
5399 case EXEC_OMP_LOOP: stmt = make_node (OMP_LOOP); break;
5400 case EXEC_OMP_TASKLOOP: stmt = make_node (OMP_TASKLOOP); break;
5401 case EXEC_OACC_LOOP: stmt = make_node (OACC_LOOP); break;
5402 default: gcc_unreachable ();
5403 }
5404
5405 TREE_TYPE (stmt) = void_type_node;
5406 OMP_FOR_BODY (stmt) = gfc_finish_block (&body);
5407 OMP_FOR_CLAUSES (stmt) = omp_clauses;
5408 OMP_FOR_INIT (stmt) = init;
5409 OMP_FOR_COND (stmt) = cond;
5410 OMP_FOR_INCR (stmt) = incr;
5411 if (orig_decls)
5412 OMP_FOR_ORIG_DECLS (stmt) = orig_decls;
5413 gfc_add_expr_to_block (&block, stmt);
5414
5415 vec_free (doacross_steps);
5416 doacross_steps = saved_doacross_steps;
5417
5418 return gfc_finish_block (&block);
5419 }
5420
5421 /* Translate combined OpenACC 'parallel loop', 'kernels loop', 'serial loop'
5422 construct. */
5423
5424 static tree
gfc_trans_oacc_combined_directive(gfc_code * code)5425 gfc_trans_oacc_combined_directive (gfc_code *code)
5426 {
5427 stmtblock_t block, *pblock = NULL;
5428 gfc_omp_clauses construct_clauses, loop_clauses;
5429 tree stmt, oacc_clauses = NULL_TREE;
5430 enum tree_code construct_code;
5431 location_t loc = input_location;
5432
5433 switch (code->op)
5434 {
5435 case EXEC_OACC_PARALLEL_LOOP:
5436 construct_code = OACC_PARALLEL;
5437 break;
5438 case EXEC_OACC_KERNELS_LOOP:
5439 construct_code = OACC_KERNELS;
5440 break;
5441 case EXEC_OACC_SERIAL_LOOP:
5442 construct_code = OACC_SERIAL;
5443 break;
5444 default:
5445 gcc_unreachable ();
5446 }
5447
5448 gfc_start_block (&block);
5449
5450 memset (&loop_clauses, 0, sizeof (loop_clauses));
5451 if (code->ext.omp_clauses != NULL)
5452 {
5453 memcpy (&construct_clauses, code->ext.omp_clauses,
5454 sizeof (construct_clauses));
5455 loop_clauses.collapse = construct_clauses.collapse;
5456 loop_clauses.gang = construct_clauses.gang;
5457 loop_clauses.gang_static = construct_clauses.gang_static;
5458 loop_clauses.gang_num_expr = construct_clauses.gang_num_expr;
5459 loop_clauses.gang_static_expr = construct_clauses.gang_static_expr;
5460 loop_clauses.vector = construct_clauses.vector;
5461 loop_clauses.vector_expr = construct_clauses.vector_expr;
5462 loop_clauses.worker = construct_clauses.worker;
5463 loop_clauses.worker_expr = construct_clauses.worker_expr;
5464 loop_clauses.seq = construct_clauses.seq;
5465 loop_clauses.par_auto = construct_clauses.par_auto;
5466 loop_clauses.independent = construct_clauses.independent;
5467 loop_clauses.tile_list = construct_clauses.tile_list;
5468 loop_clauses.lists[OMP_LIST_PRIVATE]
5469 = construct_clauses.lists[OMP_LIST_PRIVATE];
5470 loop_clauses.lists[OMP_LIST_REDUCTION]
5471 = construct_clauses.lists[OMP_LIST_REDUCTION];
5472 construct_clauses.gang = false;
5473 construct_clauses.gang_static = false;
5474 construct_clauses.gang_num_expr = NULL;
5475 construct_clauses.gang_static_expr = NULL;
5476 construct_clauses.vector = false;
5477 construct_clauses.vector_expr = NULL;
5478 construct_clauses.worker = false;
5479 construct_clauses.worker_expr = NULL;
5480 construct_clauses.seq = false;
5481 construct_clauses.par_auto = false;
5482 construct_clauses.independent = false;
5483 construct_clauses.independent = false;
5484 construct_clauses.tile_list = NULL;
5485 construct_clauses.lists[OMP_LIST_PRIVATE] = NULL;
5486 if (construct_code == OACC_KERNELS)
5487 construct_clauses.lists[OMP_LIST_REDUCTION] = NULL;
5488 oacc_clauses = gfc_trans_omp_clauses (&block, &construct_clauses,
5489 code->loc, false, true);
5490 }
5491 if (!loop_clauses.seq)
5492 pblock = █
5493 else
5494 pushlevel ();
5495 stmt = gfc_trans_omp_do (code, EXEC_OACC_LOOP, pblock, &loop_clauses, NULL);
5496 protected_set_expr_location (stmt, loc);
5497 if (TREE_CODE (stmt) != BIND_EXPR)
5498 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5499 else
5500 poplevel (0, 0);
5501 stmt = build2_loc (loc, construct_code, void_type_node, stmt, oacc_clauses);
5502 gfc_add_expr_to_block (&block, stmt);
5503 return gfc_finish_block (&block);
5504 }
5505
5506 static tree
gfc_trans_omp_depobj(gfc_code * code)5507 gfc_trans_omp_depobj (gfc_code *code)
5508 {
5509 stmtblock_t block;
5510 gfc_se se;
5511 gfc_init_se (&se, NULL);
5512 gfc_init_block (&block);
5513 gfc_conv_expr (&se, code->ext.omp_clauses->depobj);
5514 gcc_assert (se.pre.head == NULL && se.post.head == NULL);
5515 tree depobj = se.expr;
5516 location_t loc = EXPR_LOCATION (depobj);
5517 if (!POINTER_TYPE_P (TREE_TYPE (depobj)))
5518 depobj = gfc_build_addr_expr (NULL, depobj);
5519 depobj = fold_convert (build_pointer_type_for_mode (ptr_type_node,
5520 TYPE_MODE (ptr_type_node),
5521 true), depobj);
5522 gfc_omp_namelist *n = code->ext.omp_clauses->lists[OMP_LIST_DEPEND];
5523 if (n)
5524 {
5525 tree var;
5526 if (n->expr && n->expr->ref->u.ar.type != AR_FULL)
5527 {
5528 gfc_init_se (&se, NULL);
5529 if (n->expr->ref->u.ar.type == AR_ELEMENT)
5530 {
5531 gfc_conv_expr_reference (&se, n->expr);
5532 var = se.expr;
5533 }
5534 else
5535 {
5536 gfc_conv_expr_descriptor (&se, n->expr);
5537 var = gfc_conv_array_data (se.expr);
5538 }
5539 gfc_add_block_to_block (&block, &se.pre);
5540 gfc_add_block_to_block (&block, &se.post);
5541 gcc_assert (POINTER_TYPE_P (TREE_TYPE (var)));
5542 }
5543 else
5544 {
5545 var = gfc_get_symbol_decl (n->sym);
5546 if (POINTER_TYPE_P (TREE_TYPE (var))
5547 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (var))))
5548 var = build_fold_indirect_ref (var);
5549 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (var)))
5550 {
5551 var = gfc_conv_descriptor_data_get (var);
5552 gcc_assert (POINTER_TYPE_P (TREE_TYPE (var)));
5553 }
5554 else if ((n->sym->attr.allocatable || n->sym->attr.pointer)
5555 && n->sym->attr.dummy)
5556 var = build_fold_indirect_ref (var);
5557 else if (!POINTER_TYPE_P (TREE_TYPE (var))
5558 || (n->sym->ts.f90_type == BT_VOID
5559 && !POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (var)))
5560 && !GFC_ARRAY_TYPE_P (TREE_TYPE (TREE_TYPE (var)))))
5561 {
5562 TREE_ADDRESSABLE (var) = 1;
5563 var = gfc_build_addr_expr (NULL, var);
5564 }
5565 }
5566 depobj = save_expr (depobj);
5567 tree r = build_fold_indirect_ref_loc (loc, depobj);
5568 gfc_add_expr_to_block (&block,
5569 build2 (MODIFY_EXPR, void_type_node, r, var));
5570 }
5571
5572 /* Only one may be set. */
5573 gcc_assert (((int)(n != NULL) + (int)(code->ext.omp_clauses->destroy)
5574 + (int)(code->ext.omp_clauses->depobj_update != OMP_DEPEND_UNSET))
5575 == 1);
5576 int k = -1; /* omp_clauses->destroy */
5577 if (!code->ext.omp_clauses->destroy)
5578 switch (code->ext.omp_clauses->depobj_update != OMP_DEPEND_UNSET
5579 ? code->ext.omp_clauses->depobj_update : n->u.depend_op)
5580 {
5581 case OMP_DEPEND_IN: k = GOMP_DEPEND_IN; break;
5582 case OMP_DEPEND_OUT: k = GOMP_DEPEND_OUT; break;
5583 case OMP_DEPEND_INOUT: k = GOMP_DEPEND_INOUT; break;
5584 case OMP_DEPEND_MUTEXINOUTSET: k = GOMP_DEPEND_MUTEXINOUTSET; break;
5585 default: gcc_unreachable ();
5586 }
5587 tree t = build_int_cst (ptr_type_node, k);
5588 depobj = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (depobj), depobj,
5589 TYPE_SIZE_UNIT (ptr_type_node));
5590 depobj = build_fold_indirect_ref_loc (loc, depobj);
5591 gfc_add_expr_to_block (&block, build2 (MODIFY_EXPR, void_type_node, depobj, t));
5592
5593 return gfc_finish_block (&block);
5594 }
5595
5596 static tree
gfc_trans_omp_error(gfc_code * code)5597 gfc_trans_omp_error (gfc_code *code)
5598 {
5599 stmtblock_t block;
5600 gfc_se se;
5601 tree len, message;
5602 bool fatal = code->ext.omp_clauses->severity == OMP_SEVERITY_FATAL;
5603 tree fndecl = builtin_decl_explicit (fatal ? BUILT_IN_GOMP_ERROR
5604 : BUILT_IN_GOMP_WARNING);
5605 gfc_start_block (&block);
5606 gfc_init_se (&se, NULL );
5607 if (!code->ext.omp_clauses->message)
5608 {
5609 message = null_pointer_node;
5610 len = build_int_cst (size_type_node, 0);
5611 }
5612 else
5613 {
5614 gfc_conv_expr (&se, code->ext.omp_clauses->message);
5615 message = se.expr;
5616 if (!POINTER_TYPE_P (TREE_TYPE (message)))
5617 /* To ensure an ARRAY_TYPE is not passed as such. */
5618 message = gfc_build_addr_expr (NULL, message);
5619 len = se.string_length;
5620 }
5621 gfc_add_block_to_block (&block, &se.pre);
5622 gfc_add_expr_to_block (&block, build_call_expr_loc (input_location, fndecl,
5623 2, message, len));
5624 gfc_add_block_to_block (&block, &se.post);
5625 return gfc_finish_block (&block);
5626 }
5627
5628 static tree
gfc_trans_omp_flush(gfc_code * code)5629 gfc_trans_omp_flush (gfc_code *code)
5630 {
5631 tree call;
5632 if (!code->ext.omp_clauses
5633 || code->ext.omp_clauses->memorder == OMP_MEMORDER_UNSET
5634 || code->ext.omp_clauses->memorder == OMP_MEMORDER_SEQ_CST)
5635 {
5636 call = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
5637 call = build_call_expr_loc (input_location, call, 0);
5638 }
5639 else
5640 {
5641 enum memmodel mo = MEMMODEL_LAST;
5642 switch (code->ext.omp_clauses->memorder)
5643 {
5644 case OMP_MEMORDER_ACQ_REL: mo = MEMMODEL_ACQ_REL; break;
5645 case OMP_MEMORDER_RELEASE: mo = MEMMODEL_RELEASE; break;
5646 case OMP_MEMORDER_ACQUIRE: mo = MEMMODEL_ACQUIRE; break;
5647 default: gcc_unreachable (); break;
5648 }
5649 call = builtin_decl_explicit (BUILT_IN_ATOMIC_THREAD_FENCE);
5650 call = build_call_expr_loc (input_location, call, 1,
5651 build_int_cst (integer_type_node, mo));
5652 }
5653 return call;
5654 }
5655
5656 static tree
gfc_trans_omp_master(gfc_code * code)5657 gfc_trans_omp_master (gfc_code *code)
5658 {
5659 tree stmt = gfc_trans_code (code->block->next);
5660 if (IS_EMPTY_STMT (stmt))
5661 return stmt;
5662 return build1_v (OMP_MASTER, stmt);
5663 }
5664
5665 static tree
gfc_trans_omp_masked(gfc_code * code,gfc_omp_clauses * clauses)5666 gfc_trans_omp_masked (gfc_code *code, gfc_omp_clauses *clauses)
5667 {
5668 stmtblock_t block;
5669 tree body = gfc_trans_code (code->block->next);
5670 if (IS_EMPTY_STMT (body))
5671 return body;
5672 if (!clauses)
5673 clauses = code->ext.omp_clauses;
5674 gfc_start_block (&block);
5675 tree omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
5676 tree stmt = make_node (OMP_MASKED);
5677 TREE_TYPE (stmt) = void_type_node;
5678 OMP_MASKED_BODY (stmt) = body;
5679 OMP_MASKED_CLAUSES (stmt) = omp_clauses;
5680 gfc_add_expr_to_block (&block, stmt);
5681 return gfc_finish_block (&block);
5682 }
5683
5684
5685 static tree
gfc_trans_omp_ordered(gfc_code * code)5686 gfc_trans_omp_ordered (gfc_code *code)
5687 {
5688 if (!flag_openmp)
5689 {
5690 if (!code->ext.omp_clauses->simd)
5691 return gfc_trans_code (code->block ? code->block->next : NULL);
5692 code->ext.omp_clauses->threads = 0;
5693 }
5694 tree omp_clauses = gfc_trans_omp_clauses (NULL, code->ext.omp_clauses,
5695 code->loc);
5696 return build2_loc (input_location, OMP_ORDERED, void_type_node,
5697 code->block ? gfc_trans_code (code->block->next)
5698 : NULL_TREE, omp_clauses);
5699 }
5700
5701 static tree
gfc_trans_omp_parallel(gfc_code * code)5702 gfc_trans_omp_parallel (gfc_code *code)
5703 {
5704 stmtblock_t block;
5705 tree stmt, omp_clauses;
5706
5707 gfc_start_block (&block);
5708 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
5709 code->loc);
5710 pushlevel ();
5711 stmt = gfc_trans_omp_code (code->block->next, true);
5712 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5713 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
5714 omp_clauses);
5715 gfc_add_expr_to_block (&block, stmt);
5716 return gfc_finish_block (&block);
5717 }
5718
5719 enum
5720 {
5721 GFC_OMP_SPLIT_SIMD,
5722 GFC_OMP_SPLIT_DO,
5723 GFC_OMP_SPLIT_PARALLEL,
5724 GFC_OMP_SPLIT_DISTRIBUTE,
5725 GFC_OMP_SPLIT_TEAMS,
5726 GFC_OMP_SPLIT_TARGET,
5727 GFC_OMP_SPLIT_TASKLOOP,
5728 GFC_OMP_SPLIT_MASKED,
5729 GFC_OMP_SPLIT_NUM
5730 };
5731
5732 enum
5733 {
5734 GFC_OMP_MASK_SIMD = (1 << GFC_OMP_SPLIT_SIMD),
5735 GFC_OMP_MASK_DO = (1 << GFC_OMP_SPLIT_DO),
5736 GFC_OMP_MASK_PARALLEL = (1 << GFC_OMP_SPLIT_PARALLEL),
5737 GFC_OMP_MASK_DISTRIBUTE = (1 << GFC_OMP_SPLIT_DISTRIBUTE),
5738 GFC_OMP_MASK_TEAMS = (1 << GFC_OMP_SPLIT_TEAMS),
5739 GFC_OMP_MASK_TARGET = (1 << GFC_OMP_SPLIT_TARGET),
5740 GFC_OMP_MASK_TASKLOOP = (1 << GFC_OMP_SPLIT_TASKLOOP),
5741 GFC_OMP_MASK_MASKED = (1 << GFC_OMP_SPLIT_MASKED)
5742 };
5743
5744 /* If a var is in lastprivate/firstprivate/reduction but not in a
5745 data mapping/sharing clause, add it to 'map(tofrom:' if is_target
5746 and to 'shared' otherwise. */
5747 static void
gfc_add_clause_implicitly(gfc_omp_clauses * clauses_out,gfc_omp_clauses * clauses_in,bool is_target,bool is_parallel_do)5748 gfc_add_clause_implicitly (gfc_omp_clauses *clauses_out,
5749 gfc_omp_clauses *clauses_in,
5750 bool is_target, bool is_parallel_do)
5751 {
5752 int clauselist_to_add = is_target ? OMP_LIST_MAP : OMP_LIST_SHARED;
5753 gfc_omp_namelist *tail = NULL;
5754 for (int i = 0; i < 5; ++i)
5755 {
5756 gfc_omp_namelist *n;
5757 switch (i)
5758 {
5759 case 0: n = clauses_in->lists[OMP_LIST_FIRSTPRIVATE]; break;
5760 case 1: n = clauses_in->lists[OMP_LIST_LASTPRIVATE]; break;
5761 case 2: n = clauses_in->lists[OMP_LIST_REDUCTION]; break;
5762 case 3: n = clauses_in->lists[OMP_LIST_REDUCTION_INSCAN]; break;
5763 case 4: n = clauses_in->lists[OMP_LIST_REDUCTION_TASK]; break;
5764 default: gcc_unreachable ();
5765 }
5766 for (; n != NULL; n = n->next)
5767 {
5768 gfc_omp_namelist *n2, **n_firstp = NULL, **n_lastp = NULL;
5769 for (int j = 0; j < 6; ++j)
5770 {
5771 gfc_omp_namelist **n2ref = NULL, *prev2 = NULL;
5772 switch (j)
5773 {
5774 case 0:
5775 n2ref = &clauses_out->lists[clauselist_to_add];
5776 break;
5777 case 1:
5778 n2ref = &clauses_out->lists[OMP_LIST_FIRSTPRIVATE];
5779 break;
5780 case 2:
5781 if (is_target)
5782 n2ref = &clauses_in->lists[OMP_LIST_LASTPRIVATE];
5783 else
5784 n2ref = &clauses_out->lists[OMP_LIST_LASTPRIVATE];
5785 break;
5786 case 3: n2ref = &clauses_out->lists[OMP_LIST_REDUCTION]; break;
5787 case 4:
5788 n2ref = &clauses_out->lists[OMP_LIST_REDUCTION_INSCAN];
5789 break;
5790 case 5:
5791 n2ref = &clauses_out->lists[OMP_LIST_REDUCTION_TASK];
5792 break;
5793 default: gcc_unreachable ();
5794 }
5795 for (n2 = *n2ref; n2 != NULL; prev2 = n2, n2 = n2->next)
5796 if (n2->sym == n->sym)
5797 break;
5798 if (n2)
5799 {
5800 if (j == 0 /* clauselist_to_add */)
5801 break; /* Already present. */
5802 if (j == 1 /* OMP_LIST_FIRSTPRIVATE */)
5803 {
5804 n_firstp = prev2 ? &prev2->next : n2ref;
5805 continue;
5806 }
5807 if (j == 2 /* OMP_LIST_LASTPRIVATE */)
5808 {
5809 n_lastp = prev2 ? &prev2->next : n2ref;
5810 continue;
5811 }
5812 break;
5813 }
5814 }
5815 if (n_firstp && n_lastp)
5816 {
5817 /* For parallel do, GCC puts firstprivatee/lastprivate
5818 on the parallel. */
5819 if (is_parallel_do)
5820 continue;
5821 *n_firstp = (*n_firstp)->next;
5822 if (!is_target)
5823 *n_lastp = (*n_lastp)->next;
5824 }
5825 else if (is_target && n_lastp)
5826 ;
5827 else if (n2 || n_firstp || n_lastp)
5828 continue;
5829 if (clauses_out->lists[clauselist_to_add]
5830 && (clauses_out->lists[clauselist_to_add]
5831 == clauses_in->lists[clauselist_to_add]))
5832 {
5833 gfc_omp_namelist *p = NULL;
5834 for (n2 = clauses_in->lists[clauselist_to_add]; n2; n2 = n2->next)
5835 {
5836 if (p)
5837 {
5838 p->next = gfc_get_omp_namelist ();
5839 p = p->next;
5840 }
5841 else
5842 {
5843 p = gfc_get_omp_namelist ();
5844 clauses_out->lists[clauselist_to_add] = p;
5845 }
5846 *p = *n2;
5847 }
5848 }
5849 if (!tail)
5850 {
5851 tail = clauses_out->lists[clauselist_to_add];
5852 for (; tail && tail->next; tail = tail->next)
5853 ;
5854 }
5855 n2 = gfc_get_omp_namelist ();
5856 n2->where = n->where;
5857 n2->sym = n->sym;
5858 if (is_target)
5859 n2->u.map_op = OMP_MAP_TOFROM;
5860 if (tail)
5861 {
5862 tail->next = n2;
5863 tail = n2;
5864 }
5865 else
5866 clauses_out->lists[clauselist_to_add] = n2;
5867 }
5868 }
5869 }
5870
5871 static void
gfc_free_split_omp_clauses(gfc_code * code,gfc_omp_clauses * clausesa)5872 gfc_free_split_omp_clauses (gfc_code *code, gfc_omp_clauses *clausesa)
5873 {
5874 for (int i = 0; i < GFC_OMP_SPLIT_NUM; ++i)
5875 for (int j = 0; j < OMP_LIST_NUM; ++j)
5876 if (clausesa[i].lists[j] && clausesa[i].lists[j] != code->ext.omp_clauses->lists[j])
5877 for (gfc_omp_namelist *n = clausesa[i].lists[j]; n;)
5878 {
5879 gfc_omp_namelist *p = n;
5880 n = n->next;
5881 free (p);
5882 }
5883 }
5884
5885 static void
gfc_split_omp_clauses(gfc_code * code,gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM])5886 gfc_split_omp_clauses (gfc_code *code,
5887 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM])
5888 {
5889 int mask = 0, innermost = 0;
5890 bool is_loop = false;
5891 memset (clausesa, 0, GFC_OMP_SPLIT_NUM * sizeof (gfc_omp_clauses));
5892 switch (code->op)
5893 {
5894 case EXEC_OMP_DISTRIBUTE:
5895 innermost = GFC_OMP_SPLIT_DISTRIBUTE;
5896 break;
5897 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
5898 mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
5899 innermost = GFC_OMP_SPLIT_DO;
5900 break;
5901 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
5902 mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL
5903 | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
5904 innermost = GFC_OMP_SPLIT_SIMD;
5905 break;
5906 case EXEC_OMP_DISTRIBUTE_SIMD:
5907 mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
5908 innermost = GFC_OMP_SPLIT_SIMD;
5909 break;
5910 case EXEC_OMP_DO:
5911 case EXEC_OMP_LOOP:
5912 innermost = GFC_OMP_SPLIT_DO;
5913 break;
5914 case EXEC_OMP_DO_SIMD:
5915 mask = GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
5916 innermost = GFC_OMP_SPLIT_SIMD;
5917 break;
5918 case EXEC_OMP_PARALLEL:
5919 innermost = GFC_OMP_SPLIT_PARALLEL;
5920 break;
5921 case EXEC_OMP_PARALLEL_DO:
5922 case EXEC_OMP_PARALLEL_LOOP:
5923 mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
5924 innermost = GFC_OMP_SPLIT_DO;
5925 break;
5926 case EXEC_OMP_PARALLEL_DO_SIMD:
5927 mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
5928 innermost = GFC_OMP_SPLIT_SIMD;
5929 break;
5930 case EXEC_OMP_PARALLEL_MASKED:
5931 mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_MASKED;
5932 innermost = GFC_OMP_SPLIT_MASKED;
5933 break;
5934 case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
5935 mask = (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_MASKED
5936 | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD);
5937 innermost = GFC_OMP_SPLIT_TASKLOOP;
5938 break;
5939 case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
5940 mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
5941 innermost = GFC_OMP_SPLIT_TASKLOOP;
5942 break;
5943 case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
5944 mask = (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_MASKED
5945 | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD);
5946 innermost = GFC_OMP_SPLIT_SIMD;
5947 break;
5948 case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
5949 mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
5950 innermost = GFC_OMP_SPLIT_SIMD;
5951 break;
5952 case EXEC_OMP_SIMD:
5953 innermost = GFC_OMP_SPLIT_SIMD;
5954 break;
5955 case EXEC_OMP_TARGET:
5956 innermost = GFC_OMP_SPLIT_TARGET;
5957 break;
5958 case EXEC_OMP_TARGET_PARALLEL:
5959 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL;
5960 innermost = GFC_OMP_SPLIT_PARALLEL;
5961 break;
5962 case EXEC_OMP_TARGET_PARALLEL_DO:
5963 case EXEC_OMP_TARGET_PARALLEL_LOOP:
5964 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
5965 innermost = GFC_OMP_SPLIT_DO;
5966 break;
5967 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
5968 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO
5969 | GFC_OMP_MASK_SIMD;
5970 innermost = GFC_OMP_SPLIT_SIMD;
5971 break;
5972 case EXEC_OMP_TARGET_SIMD:
5973 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_SIMD;
5974 innermost = GFC_OMP_SPLIT_SIMD;
5975 break;
5976 case EXEC_OMP_TARGET_TEAMS:
5977 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS;
5978 innermost = GFC_OMP_SPLIT_TEAMS;
5979 break;
5980 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
5981 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS
5982 | GFC_OMP_MASK_DISTRIBUTE;
5983 innermost = GFC_OMP_SPLIT_DISTRIBUTE;
5984 break;
5985 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
5986 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
5987 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
5988 innermost = GFC_OMP_SPLIT_DO;
5989 break;
5990 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5991 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
5992 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
5993 innermost = GFC_OMP_SPLIT_SIMD;
5994 break;
5995 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
5996 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS
5997 | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
5998 innermost = GFC_OMP_SPLIT_SIMD;
5999 break;
6000 case EXEC_OMP_TARGET_TEAMS_LOOP:
6001 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DO;
6002 innermost = GFC_OMP_SPLIT_DO;
6003 break;
6004 case EXEC_OMP_MASKED_TASKLOOP:
6005 mask = GFC_OMP_MASK_MASKED | GFC_OMP_MASK_TASKLOOP;
6006 innermost = GFC_OMP_SPLIT_TASKLOOP;
6007 break;
6008 case EXEC_OMP_MASTER_TASKLOOP:
6009 case EXEC_OMP_TASKLOOP:
6010 innermost = GFC_OMP_SPLIT_TASKLOOP;
6011 break;
6012 case EXEC_OMP_MASKED_TASKLOOP_SIMD:
6013 mask = GFC_OMP_MASK_MASKED | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
6014 innermost = GFC_OMP_SPLIT_SIMD;
6015 break;
6016 case EXEC_OMP_MASTER_TASKLOOP_SIMD:
6017 case EXEC_OMP_TASKLOOP_SIMD:
6018 mask = GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
6019 innermost = GFC_OMP_SPLIT_SIMD;
6020 break;
6021 case EXEC_OMP_TEAMS:
6022 innermost = GFC_OMP_SPLIT_TEAMS;
6023 break;
6024 case EXEC_OMP_TEAMS_DISTRIBUTE:
6025 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE;
6026 innermost = GFC_OMP_SPLIT_DISTRIBUTE;
6027 break;
6028 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
6029 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
6030 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
6031 innermost = GFC_OMP_SPLIT_DO;
6032 break;
6033 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
6034 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
6035 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
6036 innermost = GFC_OMP_SPLIT_SIMD;
6037 break;
6038 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
6039 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
6040 innermost = GFC_OMP_SPLIT_SIMD;
6041 break;
6042 case EXEC_OMP_TEAMS_LOOP:
6043 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DO;
6044 innermost = GFC_OMP_SPLIT_DO;
6045 break;
6046 default:
6047 gcc_unreachable ();
6048 }
6049 if (mask == 0)
6050 {
6051 clausesa[innermost] = *code->ext.omp_clauses;
6052 return;
6053 }
6054 /* Loops are similar to DO but still a bit different. */
6055 switch (code->op)
6056 {
6057 case EXEC_OMP_LOOP:
6058 case EXEC_OMP_PARALLEL_LOOP:
6059 case EXEC_OMP_TEAMS_LOOP:
6060 case EXEC_OMP_TARGET_PARALLEL_LOOP:
6061 case EXEC_OMP_TARGET_TEAMS_LOOP:
6062 is_loop = true;
6063 default:
6064 break;
6065 }
6066 if (code->ext.omp_clauses != NULL)
6067 {
6068 if (mask & GFC_OMP_MASK_TARGET)
6069 {
6070 /* First the clauses that are unique to some constructs. */
6071 clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_MAP]
6072 = code->ext.omp_clauses->lists[OMP_LIST_MAP];
6073 clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_IS_DEVICE_PTR]
6074 = code->ext.omp_clauses->lists[OMP_LIST_IS_DEVICE_PTR];
6075 clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_HAS_DEVICE_ADDR]
6076 = code->ext.omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR];
6077 clausesa[GFC_OMP_SPLIT_TARGET].device
6078 = code->ext.omp_clauses->device;
6079 clausesa[GFC_OMP_SPLIT_TARGET].thread_limit
6080 = code->ext.omp_clauses->thread_limit;
6081 for (int i = 0; i < OMP_DEFAULTMAP_CAT_NUM; i++)
6082 clausesa[GFC_OMP_SPLIT_TARGET].defaultmap[i]
6083 = code->ext.omp_clauses->defaultmap[i];
6084 clausesa[GFC_OMP_SPLIT_TARGET].if_exprs[OMP_IF_TARGET]
6085 = code->ext.omp_clauses->if_exprs[OMP_IF_TARGET];
6086 /* And this is copied to all. */
6087 clausesa[GFC_OMP_SPLIT_TARGET].if_expr
6088 = code->ext.omp_clauses->if_expr;
6089 clausesa[GFC_OMP_SPLIT_TARGET].nowait
6090 = code->ext.omp_clauses->nowait;
6091 }
6092 if (mask & GFC_OMP_MASK_TEAMS)
6093 {
6094 /* First the clauses that are unique to some constructs. */
6095 clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_lower
6096 = code->ext.omp_clauses->num_teams_lower;
6097 clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper
6098 = code->ext.omp_clauses->num_teams_upper;
6099 clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit
6100 = code->ext.omp_clauses->thread_limit;
6101 /* Shared and default clauses are allowed on parallel, teams
6102 and taskloop. */
6103 clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_SHARED]
6104 = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
6105 clausesa[GFC_OMP_SPLIT_TEAMS].default_sharing
6106 = code->ext.omp_clauses->default_sharing;
6107 }
6108 if (mask & GFC_OMP_MASK_DISTRIBUTE)
6109 {
6110 /* First the clauses that are unique to some constructs. */
6111 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_sched_kind
6112 = code->ext.omp_clauses->dist_sched_kind;
6113 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_chunk_size
6114 = code->ext.omp_clauses->dist_chunk_size;
6115 /* Duplicate collapse. */
6116 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].collapse
6117 = code->ext.omp_clauses->collapse;
6118 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_concurrent
6119 = code->ext.omp_clauses->order_concurrent;
6120 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_unconstrained
6121 = code->ext.omp_clauses->order_unconstrained;
6122 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_reproducible
6123 = code->ext.omp_clauses->order_reproducible;
6124 }
6125 if (mask & GFC_OMP_MASK_PARALLEL)
6126 {
6127 /* First the clauses that are unique to some constructs. */
6128 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_COPYIN]
6129 = code->ext.omp_clauses->lists[OMP_LIST_COPYIN];
6130 clausesa[GFC_OMP_SPLIT_PARALLEL].num_threads
6131 = code->ext.omp_clauses->num_threads;
6132 clausesa[GFC_OMP_SPLIT_PARALLEL].proc_bind
6133 = code->ext.omp_clauses->proc_bind;
6134 /* Shared and default clauses are allowed on parallel, teams
6135 and taskloop. */
6136 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_SHARED]
6137 = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
6138 clausesa[GFC_OMP_SPLIT_PARALLEL].default_sharing
6139 = code->ext.omp_clauses->default_sharing;
6140 clausesa[GFC_OMP_SPLIT_PARALLEL].if_exprs[OMP_IF_PARALLEL]
6141 = code->ext.omp_clauses->if_exprs[OMP_IF_PARALLEL];
6142 /* And this is copied to all. */
6143 clausesa[GFC_OMP_SPLIT_PARALLEL].if_expr
6144 = code->ext.omp_clauses->if_expr;
6145 }
6146 if (mask & GFC_OMP_MASK_MASKED)
6147 clausesa[GFC_OMP_SPLIT_MASKED].filter = code->ext.omp_clauses->filter;
6148 if ((mask & GFC_OMP_MASK_DO) && !is_loop)
6149 {
6150 /* First the clauses that are unique to some constructs. */
6151 clausesa[GFC_OMP_SPLIT_DO].ordered
6152 = code->ext.omp_clauses->ordered;
6153 clausesa[GFC_OMP_SPLIT_DO].orderedc
6154 = code->ext.omp_clauses->orderedc;
6155 clausesa[GFC_OMP_SPLIT_DO].sched_kind
6156 = code->ext.omp_clauses->sched_kind;
6157 if (innermost == GFC_OMP_SPLIT_SIMD)
6158 clausesa[GFC_OMP_SPLIT_DO].sched_simd
6159 = code->ext.omp_clauses->sched_simd;
6160 clausesa[GFC_OMP_SPLIT_DO].sched_monotonic
6161 = code->ext.omp_clauses->sched_monotonic;
6162 clausesa[GFC_OMP_SPLIT_DO].sched_nonmonotonic
6163 = code->ext.omp_clauses->sched_nonmonotonic;
6164 clausesa[GFC_OMP_SPLIT_DO].chunk_size
6165 = code->ext.omp_clauses->chunk_size;
6166 clausesa[GFC_OMP_SPLIT_DO].nowait
6167 = code->ext.omp_clauses->nowait;
6168 }
6169 if (mask & GFC_OMP_MASK_DO)
6170 {
6171 clausesa[GFC_OMP_SPLIT_DO].bind
6172 = code->ext.omp_clauses->bind;
6173 /* Duplicate collapse. */
6174 clausesa[GFC_OMP_SPLIT_DO].collapse
6175 = code->ext.omp_clauses->collapse;
6176 clausesa[GFC_OMP_SPLIT_DO].order_concurrent
6177 = code->ext.omp_clauses->order_concurrent;
6178 clausesa[GFC_OMP_SPLIT_DO].order_unconstrained
6179 = code->ext.omp_clauses->order_unconstrained;
6180 clausesa[GFC_OMP_SPLIT_DO].order_reproducible
6181 = code->ext.omp_clauses->order_reproducible;
6182 }
6183 if (mask & GFC_OMP_MASK_SIMD)
6184 {
6185 clausesa[GFC_OMP_SPLIT_SIMD].safelen_expr
6186 = code->ext.omp_clauses->safelen_expr;
6187 clausesa[GFC_OMP_SPLIT_SIMD].simdlen_expr
6188 = code->ext.omp_clauses->simdlen_expr;
6189 clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_ALIGNED]
6190 = code->ext.omp_clauses->lists[OMP_LIST_ALIGNED];
6191 /* Duplicate collapse. */
6192 clausesa[GFC_OMP_SPLIT_SIMD].collapse
6193 = code->ext.omp_clauses->collapse;
6194 clausesa[GFC_OMP_SPLIT_SIMD].if_exprs[OMP_IF_SIMD]
6195 = code->ext.omp_clauses->if_exprs[OMP_IF_SIMD];
6196 clausesa[GFC_OMP_SPLIT_SIMD].order_concurrent
6197 = code->ext.omp_clauses->order_concurrent;
6198 clausesa[GFC_OMP_SPLIT_SIMD].order_unconstrained
6199 = code->ext.omp_clauses->order_unconstrained;
6200 clausesa[GFC_OMP_SPLIT_SIMD].order_reproducible
6201 = code->ext.omp_clauses->order_reproducible;
6202 /* And this is copied to all. */
6203 clausesa[GFC_OMP_SPLIT_SIMD].if_expr
6204 = code->ext.omp_clauses->if_expr;
6205 }
6206 if (mask & GFC_OMP_MASK_TASKLOOP)
6207 {
6208 /* First the clauses that are unique to some constructs. */
6209 clausesa[GFC_OMP_SPLIT_TASKLOOP].nogroup
6210 = code->ext.omp_clauses->nogroup;
6211 clausesa[GFC_OMP_SPLIT_TASKLOOP].grainsize
6212 = code->ext.omp_clauses->grainsize;
6213 clausesa[GFC_OMP_SPLIT_TASKLOOP].grainsize_strict
6214 = code->ext.omp_clauses->grainsize_strict;
6215 clausesa[GFC_OMP_SPLIT_TASKLOOP].num_tasks
6216 = code->ext.omp_clauses->num_tasks;
6217 clausesa[GFC_OMP_SPLIT_TASKLOOP].num_tasks_strict
6218 = code->ext.omp_clauses->num_tasks_strict;
6219 clausesa[GFC_OMP_SPLIT_TASKLOOP].priority
6220 = code->ext.omp_clauses->priority;
6221 clausesa[GFC_OMP_SPLIT_TASKLOOP].final_expr
6222 = code->ext.omp_clauses->final_expr;
6223 clausesa[GFC_OMP_SPLIT_TASKLOOP].untied
6224 = code->ext.omp_clauses->untied;
6225 clausesa[GFC_OMP_SPLIT_TASKLOOP].mergeable
6226 = code->ext.omp_clauses->mergeable;
6227 clausesa[GFC_OMP_SPLIT_TASKLOOP].if_exprs[OMP_IF_TASKLOOP]
6228 = code->ext.omp_clauses->if_exprs[OMP_IF_TASKLOOP];
6229 /* And this is copied to all. */
6230 clausesa[GFC_OMP_SPLIT_TASKLOOP].if_expr
6231 = code->ext.omp_clauses->if_expr;
6232 /* Shared and default clauses are allowed on parallel, teams
6233 and taskloop. */
6234 clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_SHARED]
6235 = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
6236 clausesa[GFC_OMP_SPLIT_TASKLOOP].default_sharing
6237 = code->ext.omp_clauses->default_sharing;
6238 /* Duplicate collapse. */
6239 clausesa[GFC_OMP_SPLIT_TASKLOOP].collapse
6240 = code->ext.omp_clauses->collapse;
6241 }
6242 /* Private clause is supported on all constructs but master/masked,
6243 it is enough to put it on the innermost one except for master/masked. For
6244 !$ omp parallel do put it on parallel though,
6245 as that's what we did for OpenMP 3.1. */
6246 clausesa[((innermost == GFC_OMP_SPLIT_DO && !is_loop)
6247 || code->op == EXEC_OMP_PARALLEL_MASTER
6248 || code->op == EXEC_OMP_PARALLEL_MASKED)
6249 ? (int) GFC_OMP_SPLIT_PARALLEL
6250 : innermost].lists[OMP_LIST_PRIVATE]
6251 = code->ext.omp_clauses->lists[OMP_LIST_PRIVATE];
6252 /* Firstprivate clause is supported on all constructs but
6253 simd and masked/master. Put it on the outermost of those and duplicate
6254 on parallel and teams. */
6255 if (mask & GFC_OMP_MASK_TARGET)
6256 clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_FIRSTPRIVATE]
6257 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
6258 if (mask & GFC_OMP_MASK_TEAMS)
6259 clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_FIRSTPRIVATE]
6260 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
6261 else if (mask & GFC_OMP_MASK_DISTRIBUTE)
6262 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_FIRSTPRIVATE]
6263 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
6264 if (mask & GFC_OMP_MASK_TASKLOOP)
6265 clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_FIRSTPRIVATE]
6266 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
6267 if ((mask & GFC_OMP_MASK_PARALLEL)
6268 && !(mask & GFC_OMP_MASK_TASKLOOP))
6269 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_FIRSTPRIVATE]
6270 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
6271 else if ((mask & GFC_OMP_MASK_DO) && !is_loop)
6272 clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_FIRSTPRIVATE]
6273 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
6274 /* Lastprivate is allowed on distribute, do, simd, taskloop and loop.
6275 In parallel do{, simd} we actually want to put it on
6276 parallel rather than do. */
6277 if (mask & GFC_OMP_MASK_DISTRIBUTE)
6278 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_LASTPRIVATE]
6279 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
6280 if (mask & GFC_OMP_MASK_TASKLOOP)
6281 clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_LASTPRIVATE]
6282 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
6283 if ((mask & GFC_OMP_MASK_PARALLEL) && !is_loop
6284 && !(mask & GFC_OMP_MASK_TASKLOOP))
6285 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_LASTPRIVATE]
6286 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
6287 else if (mask & GFC_OMP_MASK_DO)
6288 clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_LASTPRIVATE]
6289 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
6290 if (mask & GFC_OMP_MASK_SIMD)
6291 clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_LASTPRIVATE]
6292 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
6293 /* Reduction is allowed on simd, do, parallel, teams, taskloop, and loop.
6294 Duplicate it on all of them, but
6295 - omit on do if parallel is present;
6296 - omit on task and parallel if loop is present;
6297 additionally, inscan applies to do/simd only. */
6298 for (int i = OMP_LIST_REDUCTION; i <= OMP_LIST_REDUCTION_TASK; i++)
6299 {
6300 if (mask & GFC_OMP_MASK_TASKLOOP
6301 && i != OMP_LIST_REDUCTION_INSCAN)
6302 clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[i]
6303 = code->ext.omp_clauses->lists[i];
6304 if (mask & GFC_OMP_MASK_TEAMS
6305 && i != OMP_LIST_REDUCTION_INSCAN
6306 && !is_loop)
6307 clausesa[GFC_OMP_SPLIT_TEAMS].lists[i]
6308 = code->ext.omp_clauses->lists[i];
6309 if (mask & GFC_OMP_MASK_PARALLEL
6310 && i != OMP_LIST_REDUCTION_INSCAN
6311 && !(mask & GFC_OMP_MASK_TASKLOOP)
6312 && !is_loop)
6313 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[i]
6314 = code->ext.omp_clauses->lists[i];
6315 else if (mask & GFC_OMP_MASK_DO)
6316 clausesa[GFC_OMP_SPLIT_DO].lists[i]
6317 = code->ext.omp_clauses->lists[i];
6318 if (mask & GFC_OMP_MASK_SIMD)
6319 clausesa[GFC_OMP_SPLIT_SIMD].lists[i]
6320 = code->ext.omp_clauses->lists[i];
6321 }
6322 if (mask & GFC_OMP_MASK_TARGET)
6323 clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_IN_REDUCTION]
6324 = code->ext.omp_clauses->lists[OMP_LIST_IN_REDUCTION];
6325 if (mask & GFC_OMP_MASK_TASKLOOP)
6326 clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_IN_REDUCTION]
6327 = code->ext.omp_clauses->lists[OMP_LIST_IN_REDUCTION];
6328 /* Linear clause is supported on do and simd,
6329 put it on the innermost one. */
6330 clausesa[innermost].lists[OMP_LIST_LINEAR]
6331 = code->ext.omp_clauses->lists[OMP_LIST_LINEAR];
6332 }
6333 /* Propagate firstprivate/lastprivate/reduction vars to
6334 shared (parallel, teams) and map-tofrom (target). */
6335 if (mask & GFC_OMP_MASK_TARGET)
6336 gfc_add_clause_implicitly (&clausesa[GFC_OMP_SPLIT_TARGET],
6337 code->ext.omp_clauses, true, false);
6338 if ((mask & GFC_OMP_MASK_PARALLEL) && innermost != GFC_OMP_MASK_PARALLEL)
6339 gfc_add_clause_implicitly (&clausesa[GFC_OMP_SPLIT_PARALLEL],
6340 code->ext.omp_clauses, false,
6341 mask & GFC_OMP_MASK_DO);
6342 if (mask & GFC_OMP_MASK_TEAMS && innermost != GFC_OMP_MASK_TEAMS)
6343 gfc_add_clause_implicitly (&clausesa[GFC_OMP_SPLIT_TEAMS],
6344 code->ext.omp_clauses, false, false);
6345 if (((mask & (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
6346 == (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
6347 && !is_loop)
6348 clausesa[GFC_OMP_SPLIT_DO].nowait = true;
6349
6350 /* Distribute allocate clause to do, parallel, distribute, teams, target
6351 and taskloop. The code below itereates over variables in the
6352 allocate list and checks if that available is also in any
6353 privatization clause on those construct. If yes, then we add it
6354 to the list of 'allocate'ed variables for that construct. If a
6355 variable is found in none of them then we issue an error. */
6356
6357 if (code->ext.omp_clauses->lists[OMP_LIST_ALLOCATE])
6358 {
6359 gfc_omp_namelist *alloc_nl, *priv_nl;
6360 gfc_omp_namelist *tails[GFC_OMP_SPLIT_NUM];
6361 for (alloc_nl = code->ext.omp_clauses->lists[OMP_LIST_ALLOCATE];
6362 alloc_nl; alloc_nl = alloc_nl->next)
6363 {
6364 bool found = false;
6365 for (int i = GFC_OMP_SPLIT_DO; i <= GFC_OMP_SPLIT_TASKLOOP; i++)
6366 {
6367 gfc_omp_namelist *p;
6368 int list;
6369 for (list = 0; list < OMP_LIST_NUM; list++)
6370 {
6371 switch (list)
6372 {
6373 case OMP_LIST_PRIVATE:
6374 case OMP_LIST_FIRSTPRIVATE:
6375 case OMP_LIST_LASTPRIVATE:
6376 case OMP_LIST_REDUCTION:
6377 case OMP_LIST_REDUCTION_INSCAN:
6378 case OMP_LIST_REDUCTION_TASK:
6379 case OMP_LIST_IN_REDUCTION:
6380 case OMP_LIST_TASK_REDUCTION:
6381 case OMP_LIST_LINEAR:
6382 for (priv_nl = clausesa[i].lists[list]; priv_nl;
6383 priv_nl = priv_nl->next)
6384 if (alloc_nl->sym == priv_nl->sym)
6385 {
6386 found = true;
6387 p = gfc_get_omp_namelist ();
6388 p->sym = alloc_nl->sym;
6389 p->expr = alloc_nl->expr;
6390 p->where = alloc_nl->where;
6391 if (clausesa[i].lists[OMP_LIST_ALLOCATE] == NULL)
6392 {
6393 clausesa[i].lists[OMP_LIST_ALLOCATE] = p;
6394 tails[i] = p;
6395 }
6396 else
6397 {
6398 tails[i]->next = p;
6399 tails[i] = tails[i]->next;
6400 }
6401 }
6402 break;
6403 default:
6404 break;
6405 }
6406 }
6407 }
6408 if (!found)
6409 gfc_error ("%qs specified in 'allocate' clause at %L but not "
6410 "in an explicit privatization clause",
6411 alloc_nl->sym->name, &alloc_nl->where);
6412 }
6413 }
6414 }
6415
6416 static tree
gfc_trans_omp_do_simd(gfc_code * code,stmtblock_t * pblock,gfc_omp_clauses * clausesa,tree omp_clauses)6417 gfc_trans_omp_do_simd (gfc_code *code, stmtblock_t *pblock,
6418 gfc_omp_clauses *clausesa, tree omp_clauses)
6419 {
6420 stmtblock_t block;
6421 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
6422 tree stmt, body, omp_do_clauses = NULL_TREE;
6423 bool free_clausesa = false;
6424
6425 if (pblock == NULL)
6426 gfc_start_block (&block);
6427 else
6428 gfc_init_block (&block);
6429
6430 if (clausesa == NULL)
6431 {
6432 clausesa = clausesa_buf;
6433 gfc_split_omp_clauses (code, clausesa);
6434 free_clausesa = true;
6435 }
6436 if (flag_openmp)
6437 omp_do_clauses
6438 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DO], code->loc);
6439 body = gfc_trans_omp_do (code, EXEC_OMP_SIMD, pblock ? pblock : &block,
6440 &clausesa[GFC_OMP_SPLIT_SIMD], omp_clauses);
6441 if (pblock == NULL)
6442 {
6443 if (TREE_CODE (body) != BIND_EXPR)
6444 body = build3_v (BIND_EXPR, NULL, body, poplevel (1, 0));
6445 else
6446 poplevel (0, 0);
6447 }
6448 else if (TREE_CODE (body) != BIND_EXPR)
6449 body = build3_v (BIND_EXPR, NULL, body, NULL_TREE);
6450 if (flag_openmp)
6451 {
6452 stmt = make_node (OMP_FOR);
6453 TREE_TYPE (stmt) = void_type_node;
6454 OMP_FOR_BODY (stmt) = body;
6455 OMP_FOR_CLAUSES (stmt) = omp_do_clauses;
6456 }
6457 else
6458 stmt = body;
6459 gfc_add_expr_to_block (&block, stmt);
6460 if (free_clausesa)
6461 gfc_free_split_omp_clauses (code, clausesa);
6462 return gfc_finish_block (&block);
6463 }
6464
6465 static tree
gfc_trans_omp_parallel_do(gfc_code * code,bool is_loop,stmtblock_t * pblock,gfc_omp_clauses * clausesa)6466 gfc_trans_omp_parallel_do (gfc_code *code, bool is_loop, stmtblock_t *pblock,
6467 gfc_omp_clauses *clausesa)
6468 {
6469 stmtblock_t block, *new_pblock = pblock;
6470 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
6471 tree stmt, omp_clauses = NULL_TREE;
6472 bool free_clausesa = false;
6473
6474 if (pblock == NULL)
6475 gfc_start_block (&block);
6476 else
6477 gfc_init_block (&block);
6478
6479 if (clausesa == NULL)
6480 {
6481 clausesa = clausesa_buf;
6482 gfc_split_omp_clauses (code, clausesa);
6483 free_clausesa = true;
6484 }
6485 omp_clauses
6486 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
6487 code->loc);
6488 if (pblock == NULL)
6489 {
6490 if (!clausesa[GFC_OMP_SPLIT_DO].ordered
6491 && clausesa[GFC_OMP_SPLIT_DO].sched_kind != OMP_SCHED_STATIC)
6492 new_pblock = █
6493 else
6494 pushlevel ();
6495 }
6496 stmt = gfc_trans_omp_do (code, is_loop ? EXEC_OMP_LOOP : EXEC_OMP_DO,
6497 new_pblock, &clausesa[GFC_OMP_SPLIT_DO],
6498 omp_clauses);
6499 if (pblock == NULL)
6500 {
6501 if (TREE_CODE (stmt) != BIND_EXPR)
6502 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6503 else
6504 poplevel (0, 0);
6505 }
6506 else if (TREE_CODE (stmt) != BIND_EXPR)
6507 stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
6508 stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
6509 void_type_node, stmt, omp_clauses);
6510 OMP_PARALLEL_COMBINED (stmt) = 1;
6511 gfc_add_expr_to_block (&block, stmt);
6512 if (free_clausesa)
6513 gfc_free_split_omp_clauses (code, clausesa);
6514 return gfc_finish_block (&block);
6515 }
6516
6517 static tree
gfc_trans_omp_parallel_do_simd(gfc_code * code,stmtblock_t * pblock,gfc_omp_clauses * clausesa)6518 gfc_trans_omp_parallel_do_simd (gfc_code *code, stmtblock_t *pblock,
6519 gfc_omp_clauses *clausesa)
6520 {
6521 stmtblock_t block;
6522 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
6523 tree stmt, omp_clauses = NULL_TREE;
6524 bool free_clausesa = false;
6525
6526 if (pblock == NULL)
6527 gfc_start_block (&block);
6528 else
6529 gfc_init_block (&block);
6530
6531 if (clausesa == NULL)
6532 {
6533 clausesa = clausesa_buf;
6534 gfc_split_omp_clauses (code, clausesa);
6535 free_clausesa = true;
6536 }
6537 if (flag_openmp)
6538 omp_clauses
6539 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
6540 code->loc);
6541 if (pblock == NULL)
6542 pushlevel ();
6543 stmt = gfc_trans_omp_do_simd (code, pblock, clausesa, omp_clauses);
6544 if (pblock == NULL)
6545 {
6546 if (TREE_CODE (stmt) != BIND_EXPR)
6547 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6548 else
6549 poplevel (0, 0);
6550 }
6551 else if (TREE_CODE (stmt) != BIND_EXPR)
6552 stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
6553 if (flag_openmp)
6554 {
6555 stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
6556 void_type_node, stmt, omp_clauses);
6557 OMP_PARALLEL_COMBINED (stmt) = 1;
6558 }
6559 gfc_add_expr_to_block (&block, stmt);
6560 if (free_clausesa)
6561 gfc_free_split_omp_clauses (code, clausesa);
6562 return gfc_finish_block (&block);
6563 }
6564
6565 static tree
gfc_trans_omp_parallel_sections(gfc_code * code)6566 gfc_trans_omp_parallel_sections (gfc_code *code)
6567 {
6568 stmtblock_t block;
6569 gfc_omp_clauses section_clauses;
6570 tree stmt, omp_clauses;
6571
6572 memset (§ion_clauses, 0, sizeof (section_clauses));
6573 section_clauses.nowait = true;
6574
6575 gfc_start_block (&block);
6576 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
6577 code->loc);
6578 pushlevel ();
6579 stmt = gfc_trans_omp_sections (code, §ion_clauses);
6580 if (TREE_CODE (stmt) != BIND_EXPR)
6581 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6582 else
6583 poplevel (0, 0);
6584 stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
6585 void_type_node, stmt, omp_clauses);
6586 OMP_PARALLEL_COMBINED (stmt) = 1;
6587 gfc_add_expr_to_block (&block, stmt);
6588 return gfc_finish_block (&block);
6589 }
6590
6591 static tree
gfc_trans_omp_parallel_workshare(gfc_code * code)6592 gfc_trans_omp_parallel_workshare (gfc_code *code)
6593 {
6594 stmtblock_t block;
6595 gfc_omp_clauses workshare_clauses;
6596 tree stmt, omp_clauses;
6597
6598 memset (&workshare_clauses, 0, sizeof (workshare_clauses));
6599 workshare_clauses.nowait = true;
6600
6601 gfc_start_block (&block);
6602 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
6603 code->loc);
6604 pushlevel ();
6605 stmt = gfc_trans_omp_workshare (code, &workshare_clauses);
6606 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6607 stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
6608 void_type_node, stmt, omp_clauses);
6609 OMP_PARALLEL_COMBINED (stmt) = 1;
6610 gfc_add_expr_to_block (&block, stmt);
6611 return gfc_finish_block (&block);
6612 }
6613
6614 static tree
gfc_trans_omp_scope(gfc_code * code)6615 gfc_trans_omp_scope (gfc_code *code)
6616 {
6617 stmtblock_t block;
6618 tree body = gfc_trans_code (code->block->next);
6619 if (IS_EMPTY_STMT (body))
6620 return body;
6621 gfc_start_block (&block);
6622 tree omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
6623 code->loc);
6624 tree stmt = make_node (OMP_SCOPE);
6625 TREE_TYPE (stmt) = void_type_node;
6626 OMP_SCOPE_BODY (stmt) = body;
6627 OMP_SCOPE_CLAUSES (stmt) = omp_clauses;
6628 gfc_add_expr_to_block (&block, stmt);
6629 return gfc_finish_block (&block);
6630 }
6631
6632 static tree
gfc_trans_omp_sections(gfc_code * code,gfc_omp_clauses * clauses)6633 gfc_trans_omp_sections (gfc_code *code, gfc_omp_clauses *clauses)
6634 {
6635 stmtblock_t block, body;
6636 tree omp_clauses, stmt;
6637 bool has_lastprivate = clauses->lists[OMP_LIST_LASTPRIVATE] != NULL;
6638 location_t loc = gfc_get_location (&code->loc);
6639
6640 gfc_start_block (&block);
6641
6642 omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
6643
6644 gfc_init_block (&body);
6645 for (code = code->block; code; code = code->block)
6646 {
6647 /* Last section is special because of lastprivate, so even if it
6648 is empty, chain it in. */
6649 stmt = gfc_trans_omp_code (code->next,
6650 has_lastprivate && code->block == NULL);
6651 if (! IS_EMPTY_STMT (stmt))
6652 {
6653 stmt = build1_v (OMP_SECTION, stmt);
6654 gfc_add_expr_to_block (&body, stmt);
6655 }
6656 }
6657 stmt = gfc_finish_block (&body);
6658
6659 stmt = build2_loc (loc, OMP_SECTIONS, void_type_node, stmt, omp_clauses);
6660 gfc_add_expr_to_block (&block, stmt);
6661
6662 return gfc_finish_block (&block);
6663 }
6664
6665 static tree
gfc_trans_omp_single(gfc_code * code,gfc_omp_clauses * clauses)6666 gfc_trans_omp_single (gfc_code *code, gfc_omp_clauses *clauses)
6667 {
6668 tree omp_clauses = gfc_trans_omp_clauses (NULL, clauses, code->loc);
6669 tree stmt = gfc_trans_omp_code (code->block->next, true);
6670 stmt = build2_loc (gfc_get_location (&code->loc), OMP_SINGLE, void_type_node,
6671 stmt, omp_clauses);
6672 return stmt;
6673 }
6674
6675 static tree
gfc_trans_omp_task(gfc_code * code)6676 gfc_trans_omp_task (gfc_code *code)
6677 {
6678 stmtblock_t block;
6679 tree stmt, omp_clauses;
6680
6681 gfc_start_block (&block);
6682 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
6683 code->loc);
6684 pushlevel ();
6685 stmt = gfc_trans_omp_code (code->block->next, true);
6686 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6687 stmt = build2_loc (gfc_get_location (&code->loc), OMP_TASK, void_type_node,
6688 stmt, omp_clauses);
6689 gfc_add_expr_to_block (&block, stmt);
6690 return gfc_finish_block (&block);
6691 }
6692
6693 static tree
gfc_trans_omp_taskgroup(gfc_code * code)6694 gfc_trans_omp_taskgroup (gfc_code *code)
6695 {
6696 stmtblock_t block;
6697 gfc_start_block (&block);
6698 tree body = gfc_trans_code (code->block->next);
6699 tree stmt = make_node (OMP_TASKGROUP);
6700 TREE_TYPE (stmt) = void_type_node;
6701 OMP_TASKGROUP_BODY (stmt) = body;
6702 OMP_TASKGROUP_CLAUSES (stmt) = gfc_trans_omp_clauses (&block,
6703 code->ext.omp_clauses,
6704 code->loc);
6705 gfc_add_expr_to_block (&block, stmt);
6706 return gfc_finish_block (&block);
6707 }
6708
6709 static tree
gfc_trans_omp_taskwait(gfc_code * code)6710 gfc_trans_omp_taskwait (gfc_code *code)
6711 {
6712 if (!code->ext.omp_clauses)
6713 {
6714 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
6715 return build_call_expr_loc (input_location, decl, 0);
6716 }
6717 stmtblock_t block;
6718 gfc_start_block (&block);
6719 tree stmt = make_node (OMP_TASK);
6720 TREE_TYPE (stmt) = void_type_node;
6721 OMP_TASK_BODY (stmt) = NULL_TREE;
6722 OMP_TASK_CLAUSES (stmt) = gfc_trans_omp_clauses (&block,
6723 code->ext.omp_clauses,
6724 code->loc);
6725 gfc_add_expr_to_block (&block, stmt);
6726 return gfc_finish_block (&block);
6727 }
6728
6729 static tree
gfc_trans_omp_taskyield(void)6730 gfc_trans_omp_taskyield (void)
6731 {
6732 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
6733 return build_call_expr_loc (input_location, decl, 0);
6734 }
6735
6736 static tree
gfc_trans_omp_distribute(gfc_code * code,gfc_omp_clauses * clausesa)6737 gfc_trans_omp_distribute (gfc_code *code, gfc_omp_clauses *clausesa)
6738 {
6739 stmtblock_t block;
6740 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
6741 tree stmt, omp_clauses = NULL_TREE;
6742 bool free_clausesa = false;
6743
6744 gfc_start_block (&block);
6745 if (clausesa == NULL)
6746 {
6747 clausesa = clausesa_buf;
6748 gfc_split_omp_clauses (code, clausesa);
6749 free_clausesa = true;
6750 }
6751 if (flag_openmp)
6752 omp_clauses
6753 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
6754 code->loc);
6755 switch (code->op)
6756 {
6757 case EXEC_OMP_DISTRIBUTE:
6758 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
6759 case EXEC_OMP_TEAMS_DISTRIBUTE:
6760 /* This is handled in gfc_trans_omp_do. */
6761 gcc_unreachable ();
6762 break;
6763 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
6764 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
6765 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
6766 stmt = gfc_trans_omp_parallel_do (code, false, &block, clausesa);
6767 if (TREE_CODE (stmt) != BIND_EXPR)
6768 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6769 else
6770 poplevel (0, 0);
6771 break;
6772 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
6773 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
6774 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
6775 stmt = gfc_trans_omp_parallel_do_simd (code, &block, clausesa);
6776 if (TREE_CODE (stmt) != BIND_EXPR)
6777 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6778 else
6779 poplevel (0, 0);
6780 break;
6781 case EXEC_OMP_DISTRIBUTE_SIMD:
6782 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
6783 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
6784 stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
6785 &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
6786 if (TREE_CODE (stmt) != BIND_EXPR)
6787 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6788 else
6789 poplevel (0, 0);
6790 break;
6791 default:
6792 gcc_unreachable ();
6793 }
6794 if (flag_openmp)
6795 {
6796 tree distribute = make_node (OMP_DISTRIBUTE);
6797 TREE_TYPE (distribute) = void_type_node;
6798 OMP_FOR_BODY (distribute) = stmt;
6799 OMP_FOR_CLAUSES (distribute) = omp_clauses;
6800 stmt = distribute;
6801 }
6802 gfc_add_expr_to_block (&block, stmt);
6803 if (free_clausesa)
6804 gfc_free_split_omp_clauses (code, clausesa);
6805 return gfc_finish_block (&block);
6806 }
6807
6808 static tree
gfc_trans_omp_teams(gfc_code * code,gfc_omp_clauses * clausesa,tree omp_clauses)6809 gfc_trans_omp_teams (gfc_code *code, gfc_omp_clauses *clausesa,
6810 tree omp_clauses)
6811 {
6812 stmtblock_t block;
6813 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
6814 tree stmt;
6815 bool combined = true, free_clausesa = false;
6816
6817 gfc_start_block (&block);
6818 if (clausesa == NULL)
6819 {
6820 clausesa = clausesa_buf;
6821 gfc_split_omp_clauses (code, clausesa);
6822 free_clausesa = true;
6823 }
6824 if (flag_openmp)
6825 {
6826 omp_clauses
6827 = chainon (omp_clauses,
6828 gfc_trans_omp_clauses (&block,
6829 &clausesa[GFC_OMP_SPLIT_TEAMS],
6830 code->loc));
6831 pushlevel ();
6832 }
6833 switch (code->op)
6834 {
6835 case EXEC_OMP_TARGET_TEAMS:
6836 case EXEC_OMP_TEAMS:
6837 stmt = gfc_trans_omp_code (code->block->next, true);
6838 combined = false;
6839 break;
6840 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
6841 case EXEC_OMP_TEAMS_DISTRIBUTE:
6842 stmt = gfc_trans_omp_do (code, EXEC_OMP_DISTRIBUTE, NULL,
6843 &clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
6844 NULL);
6845 break;
6846 case EXEC_OMP_TARGET_TEAMS_LOOP:
6847 case EXEC_OMP_TEAMS_LOOP:
6848 stmt = gfc_trans_omp_do (code, EXEC_OMP_LOOP, NULL,
6849 &clausesa[GFC_OMP_SPLIT_DO],
6850 NULL);
6851 break;
6852 default:
6853 stmt = gfc_trans_omp_distribute (code, clausesa);
6854 break;
6855 }
6856 if (flag_openmp)
6857 {
6858 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6859 stmt = build2_loc (gfc_get_location (&code->loc), OMP_TEAMS,
6860 void_type_node, stmt, omp_clauses);
6861 if (combined)
6862 OMP_TEAMS_COMBINED (stmt) = 1;
6863 }
6864 gfc_add_expr_to_block (&block, stmt);
6865 if (free_clausesa)
6866 gfc_free_split_omp_clauses (code, clausesa);
6867 return gfc_finish_block (&block);
6868 }
6869
6870 static tree
gfc_trans_omp_target(gfc_code * code)6871 gfc_trans_omp_target (gfc_code *code)
6872 {
6873 stmtblock_t block;
6874 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
6875 tree stmt, omp_clauses = NULL_TREE;
6876
6877 gfc_start_block (&block);
6878 gfc_split_omp_clauses (code, clausesa);
6879 if (flag_openmp)
6880 omp_clauses
6881 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TARGET],
6882 code->loc);
6883 switch (code->op)
6884 {
6885 case EXEC_OMP_TARGET:
6886 pushlevel ();
6887 stmt = gfc_trans_omp_code (code->block->next, true);
6888 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6889 break;
6890 case EXEC_OMP_TARGET_PARALLEL:
6891 {
6892 stmtblock_t iblock;
6893
6894 pushlevel ();
6895 gfc_start_block (&iblock);
6896 tree inner_clauses
6897 = gfc_trans_omp_clauses (&iblock, &clausesa[GFC_OMP_SPLIT_PARALLEL],
6898 code->loc);
6899 stmt = gfc_trans_omp_code (code->block->next, true);
6900 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
6901 inner_clauses);
6902 gfc_add_expr_to_block (&iblock, stmt);
6903 stmt = gfc_finish_block (&iblock);
6904 if (TREE_CODE (stmt) != BIND_EXPR)
6905 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6906 else
6907 poplevel (0, 0);
6908 }
6909 break;
6910 case EXEC_OMP_TARGET_PARALLEL_DO:
6911 case EXEC_OMP_TARGET_PARALLEL_LOOP:
6912 stmt = gfc_trans_omp_parallel_do (code,
6913 (code->op
6914 == EXEC_OMP_TARGET_PARALLEL_LOOP),
6915 &block, clausesa);
6916 if (TREE_CODE (stmt) != BIND_EXPR)
6917 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6918 else
6919 poplevel (0, 0);
6920 break;
6921 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
6922 stmt = gfc_trans_omp_parallel_do_simd (code, &block, clausesa);
6923 if (TREE_CODE (stmt) != BIND_EXPR)
6924 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6925 else
6926 poplevel (0, 0);
6927 break;
6928 case EXEC_OMP_TARGET_SIMD:
6929 stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
6930 &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
6931 if (TREE_CODE (stmt) != BIND_EXPR)
6932 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6933 else
6934 poplevel (0, 0);
6935 break;
6936 default:
6937 if (flag_openmp
6938 && (clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper
6939 || clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit))
6940 {
6941 gfc_omp_clauses clausesb;
6942 tree teams_clauses;
6943 /* For combined !$omp target teams, the num_teams and
6944 thread_limit clauses are evaluated before entering the
6945 target construct. */
6946 memset (&clausesb, '\0', sizeof (clausesb));
6947 clausesb.num_teams_lower
6948 = clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_lower;
6949 clausesb.num_teams_upper
6950 = clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper;
6951 clausesb.thread_limit = clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit;
6952 clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_lower = NULL;
6953 clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper = NULL;
6954 clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit = NULL;
6955 teams_clauses
6956 = gfc_trans_omp_clauses (&block, &clausesb, code->loc);
6957 pushlevel ();
6958 stmt = gfc_trans_omp_teams (code, clausesa, teams_clauses);
6959 }
6960 else
6961 {
6962 pushlevel ();
6963 stmt = gfc_trans_omp_teams (code, clausesa, NULL_TREE);
6964 }
6965 if (TREE_CODE (stmt) != BIND_EXPR)
6966 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6967 else
6968 poplevel (0, 0);
6969 break;
6970 }
6971 if (flag_openmp)
6972 {
6973 stmt = build2_loc (gfc_get_location (&code->loc), OMP_TARGET,
6974 void_type_node, stmt, omp_clauses);
6975 if (code->op != EXEC_OMP_TARGET)
6976 OMP_TARGET_COMBINED (stmt) = 1;
6977 cfun->has_omp_target = true;
6978 }
6979 gfc_add_expr_to_block (&block, stmt);
6980 gfc_free_split_omp_clauses (code, clausesa);
6981 return gfc_finish_block (&block);
6982 }
6983
6984 static tree
gfc_trans_omp_taskloop(gfc_code * code,gfc_exec_op op)6985 gfc_trans_omp_taskloop (gfc_code *code, gfc_exec_op op)
6986 {
6987 stmtblock_t block;
6988 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
6989 tree stmt, omp_clauses = NULL_TREE;
6990
6991 gfc_start_block (&block);
6992 gfc_split_omp_clauses (code, clausesa);
6993 if (flag_openmp)
6994 omp_clauses
6995 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TASKLOOP],
6996 code->loc);
6997 switch (op)
6998 {
6999 case EXEC_OMP_TASKLOOP:
7000 /* This is handled in gfc_trans_omp_do. */
7001 gcc_unreachable ();
7002 break;
7003 case EXEC_OMP_TASKLOOP_SIMD:
7004 stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
7005 &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
7006 if (TREE_CODE (stmt) != BIND_EXPR)
7007 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7008 else
7009 poplevel (0, 0);
7010 break;
7011 default:
7012 gcc_unreachable ();
7013 }
7014 if (flag_openmp)
7015 {
7016 tree taskloop = make_node (OMP_TASKLOOP);
7017 TREE_TYPE (taskloop) = void_type_node;
7018 OMP_FOR_BODY (taskloop) = stmt;
7019 OMP_FOR_CLAUSES (taskloop) = omp_clauses;
7020 stmt = taskloop;
7021 }
7022 gfc_add_expr_to_block (&block, stmt);
7023 gfc_free_split_omp_clauses (code, clausesa);
7024 return gfc_finish_block (&block);
7025 }
7026
7027 static tree
gfc_trans_omp_master_masked_taskloop(gfc_code * code,gfc_exec_op op)7028 gfc_trans_omp_master_masked_taskloop (gfc_code *code, gfc_exec_op op)
7029 {
7030 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
7031 stmtblock_t block;
7032 tree stmt;
7033
7034 if (op != EXEC_OMP_MASTER_TASKLOOP_SIMD
7035 && code->op != EXEC_OMP_MASTER_TASKLOOP)
7036 gfc_split_omp_clauses (code, clausesa);
7037
7038 pushlevel ();
7039 if (op == EXEC_OMP_MASKED_TASKLOOP_SIMD
7040 || op == EXEC_OMP_MASTER_TASKLOOP_SIMD)
7041 stmt = gfc_trans_omp_taskloop (code, EXEC_OMP_TASKLOOP_SIMD);
7042 else
7043 {
7044 gcc_assert (op == EXEC_OMP_MASKED_TASKLOOP
7045 || op == EXEC_OMP_MASTER_TASKLOOP);
7046 stmt = gfc_trans_omp_do (code, EXEC_OMP_TASKLOOP, NULL,
7047 code->op != EXEC_OMP_MASTER_TASKLOOP
7048 ? &clausesa[GFC_OMP_SPLIT_TASKLOOP]
7049 : code->ext.omp_clauses, NULL);
7050 }
7051 if (TREE_CODE (stmt) != BIND_EXPR)
7052 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7053 else
7054 poplevel (0, 0);
7055 gfc_start_block (&block);
7056 if (op == EXEC_OMP_MASKED_TASKLOOP || op == EXEC_OMP_MASKED_TASKLOOP_SIMD)
7057 {
7058 tree clauses = gfc_trans_omp_clauses (&block,
7059 &clausesa[GFC_OMP_SPLIT_MASKED],
7060 code->loc);
7061 tree msk = make_node (OMP_MASKED);
7062 TREE_TYPE (msk) = void_type_node;
7063 OMP_MASKED_BODY (msk) = stmt;
7064 OMP_MASKED_CLAUSES (msk) = clauses;
7065 OMP_MASKED_COMBINED (msk) = 1;
7066 gfc_add_expr_to_block (&block, msk);
7067 }
7068 else
7069 {
7070 gcc_assert (op == EXEC_OMP_MASTER_TASKLOOP
7071 || op == EXEC_OMP_MASTER_TASKLOOP_SIMD);
7072 stmt = build1_v (OMP_MASTER, stmt);
7073 gfc_add_expr_to_block (&block, stmt);
7074 }
7075 if (op != EXEC_OMP_MASTER_TASKLOOP_SIMD
7076 && code->op != EXEC_OMP_MASTER_TASKLOOP)
7077 gfc_free_split_omp_clauses (code, clausesa);
7078 return gfc_finish_block (&block);
7079 }
7080
7081 static tree
gfc_trans_omp_parallel_master_masked(gfc_code * code)7082 gfc_trans_omp_parallel_master_masked (gfc_code *code)
7083 {
7084 stmtblock_t block;
7085 tree stmt, omp_clauses;
7086 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
7087 bool parallel_combined = false;
7088
7089 if (code->op != EXEC_OMP_PARALLEL_MASTER)
7090 gfc_split_omp_clauses (code, clausesa);
7091
7092 gfc_start_block (&block);
7093 omp_clauses = gfc_trans_omp_clauses (&block,
7094 code->op == EXEC_OMP_PARALLEL_MASTER
7095 ? code->ext.omp_clauses
7096 : &clausesa[GFC_OMP_SPLIT_PARALLEL],
7097 code->loc);
7098 pushlevel ();
7099 if (code->op == EXEC_OMP_PARALLEL_MASTER)
7100 stmt = gfc_trans_omp_master (code);
7101 else if (code->op == EXEC_OMP_PARALLEL_MASKED)
7102 stmt = gfc_trans_omp_masked (code, &clausesa[GFC_OMP_SPLIT_MASKED]);
7103 else
7104 {
7105 gfc_exec_op op;
7106 switch (code->op)
7107 {
7108 case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
7109 op = EXEC_OMP_MASKED_TASKLOOP;
7110 break;
7111 case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
7112 op = EXEC_OMP_MASKED_TASKLOOP_SIMD;
7113 break;
7114 case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
7115 op = EXEC_OMP_MASTER_TASKLOOP;
7116 break;
7117 case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
7118 op = EXEC_OMP_MASTER_TASKLOOP_SIMD;
7119 break;
7120 default:
7121 gcc_unreachable ();
7122 }
7123 stmt = gfc_trans_omp_master_masked_taskloop (code, op);
7124 parallel_combined = true;
7125 }
7126 if (TREE_CODE (stmt) != BIND_EXPR)
7127 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7128 else
7129 poplevel (0, 0);
7130 stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
7131 void_type_node, stmt, omp_clauses);
7132 /* masked does have just filter clause, but during gimplification
7133 isn't represented by a gimplification omp context, so for
7134 !$omp parallel masked don't set OMP_PARALLEL_COMBINED,
7135 so that
7136 !$omp parallel masked
7137 !$omp taskloop simd lastprivate (x)
7138 isn't confused with
7139 !$omp parallel masked taskloop simd lastprivate (x) */
7140 if (parallel_combined)
7141 OMP_PARALLEL_COMBINED (stmt) = 1;
7142 gfc_add_expr_to_block (&block, stmt);
7143 if (code->op != EXEC_OMP_PARALLEL_MASTER)
7144 gfc_free_split_omp_clauses (code, clausesa);
7145 return gfc_finish_block (&block);
7146 }
7147
7148 static tree
gfc_trans_omp_target_data(gfc_code * code)7149 gfc_trans_omp_target_data (gfc_code *code)
7150 {
7151 stmtblock_t block;
7152 tree stmt, omp_clauses;
7153
7154 gfc_start_block (&block);
7155 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
7156 code->loc);
7157 stmt = gfc_trans_omp_code (code->block->next, true);
7158 stmt = build2_loc (gfc_get_location (&code->loc), OMP_TARGET_DATA,
7159 void_type_node, stmt, omp_clauses);
7160 gfc_add_expr_to_block (&block, stmt);
7161 return gfc_finish_block (&block);
7162 }
7163
7164 static tree
gfc_trans_omp_target_enter_data(gfc_code * code)7165 gfc_trans_omp_target_enter_data (gfc_code *code)
7166 {
7167 stmtblock_t block;
7168 tree stmt, omp_clauses;
7169
7170 gfc_start_block (&block);
7171 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
7172 code->loc);
7173 stmt = build1_loc (input_location, OMP_TARGET_ENTER_DATA, void_type_node,
7174 omp_clauses);
7175 gfc_add_expr_to_block (&block, stmt);
7176 return gfc_finish_block (&block);
7177 }
7178
7179 static tree
gfc_trans_omp_target_exit_data(gfc_code * code)7180 gfc_trans_omp_target_exit_data (gfc_code *code)
7181 {
7182 stmtblock_t block;
7183 tree stmt, omp_clauses;
7184
7185 gfc_start_block (&block);
7186 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
7187 code->loc);
7188 stmt = build1_loc (input_location, OMP_TARGET_EXIT_DATA, void_type_node,
7189 omp_clauses);
7190 gfc_add_expr_to_block (&block, stmt);
7191 return gfc_finish_block (&block);
7192 }
7193
7194 static tree
gfc_trans_omp_target_update(gfc_code * code)7195 gfc_trans_omp_target_update (gfc_code *code)
7196 {
7197 stmtblock_t block;
7198 tree stmt, omp_clauses;
7199
7200 gfc_start_block (&block);
7201 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
7202 code->loc);
7203 stmt = build1_loc (input_location, OMP_TARGET_UPDATE, void_type_node,
7204 omp_clauses);
7205 gfc_add_expr_to_block (&block, stmt);
7206 return gfc_finish_block (&block);
7207 }
7208
7209 static tree
gfc_trans_omp_workshare(gfc_code * code,gfc_omp_clauses * clauses)7210 gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses)
7211 {
7212 tree res, tmp, stmt;
7213 stmtblock_t block, *pblock = NULL;
7214 stmtblock_t singleblock;
7215 int saved_ompws_flags;
7216 bool singleblock_in_progress = false;
7217 /* True if previous gfc_code in workshare construct is not workshared. */
7218 bool prev_singleunit;
7219 location_t loc = gfc_get_location (&code->loc);
7220
7221 code = code->block->next;
7222
7223 pushlevel ();
7224
7225 gfc_start_block (&block);
7226 pblock = █
7227
7228 ompws_flags = OMPWS_WORKSHARE_FLAG;
7229 prev_singleunit = false;
7230
7231 /* Translate statements one by one to trees until we reach
7232 the end of the workshare construct. Adjacent gfc_codes that
7233 are a single unit of work are clustered and encapsulated in a
7234 single OMP_SINGLE construct. */
7235 for (; code; code = code->next)
7236 {
7237 if (code->here != 0)
7238 {
7239 res = gfc_trans_label_here (code);
7240 gfc_add_expr_to_block (pblock, res);
7241 }
7242
7243 /* No dependence analysis, use for clauses with wait.
7244 If this is the last gfc_code, use default omp_clauses. */
7245 if (code->next == NULL && clauses->nowait)
7246 ompws_flags |= OMPWS_NOWAIT;
7247
7248 /* By default, every gfc_code is a single unit of work. */
7249 ompws_flags |= OMPWS_CURR_SINGLEUNIT;
7250 ompws_flags &= ~(OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY);
7251
7252 switch (code->op)
7253 {
7254 case EXEC_NOP:
7255 res = NULL_TREE;
7256 break;
7257
7258 case EXEC_ASSIGN:
7259 res = gfc_trans_assign (code);
7260 break;
7261
7262 case EXEC_POINTER_ASSIGN:
7263 res = gfc_trans_pointer_assign (code);
7264 break;
7265
7266 case EXEC_INIT_ASSIGN:
7267 res = gfc_trans_init_assign (code);
7268 break;
7269
7270 case EXEC_FORALL:
7271 res = gfc_trans_forall (code);
7272 break;
7273
7274 case EXEC_WHERE:
7275 res = gfc_trans_where (code);
7276 break;
7277
7278 case EXEC_OMP_ATOMIC:
7279 res = gfc_trans_omp_directive (code);
7280 break;
7281
7282 case EXEC_OMP_PARALLEL:
7283 case EXEC_OMP_PARALLEL_DO:
7284 case EXEC_OMP_PARALLEL_MASTER:
7285 case EXEC_OMP_PARALLEL_SECTIONS:
7286 case EXEC_OMP_PARALLEL_WORKSHARE:
7287 case EXEC_OMP_CRITICAL:
7288 saved_ompws_flags = ompws_flags;
7289 ompws_flags = 0;
7290 res = gfc_trans_omp_directive (code);
7291 ompws_flags = saved_ompws_flags;
7292 break;
7293
7294 case EXEC_BLOCK:
7295 res = gfc_trans_block_construct (code);
7296 break;
7297
7298 default:
7299 gfc_internal_error ("gfc_trans_omp_workshare(): Bad statement code");
7300 }
7301
7302 gfc_set_backend_locus (&code->loc);
7303
7304 if (res != NULL_TREE && ! IS_EMPTY_STMT (res))
7305 {
7306 if (prev_singleunit)
7307 {
7308 if (ompws_flags & OMPWS_CURR_SINGLEUNIT)
7309 /* Add current gfc_code to single block. */
7310 gfc_add_expr_to_block (&singleblock, res);
7311 else
7312 {
7313 /* Finish single block and add it to pblock. */
7314 tmp = gfc_finish_block (&singleblock);
7315 tmp = build2_loc (loc, OMP_SINGLE,
7316 void_type_node, tmp, NULL_TREE);
7317 gfc_add_expr_to_block (pblock, tmp);
7318 /* Add current gfc_code to pblock. */
7319 gfc_add_expr_to_block (pblock, res);
7320 singleblock_in_progress = false;
7321 }
7322 }
7323 else
7324 {
7325 if (ompws_flags & OMPWS_CURR_SINGLEUNIT)
7326 {
7327 /* Start single block. */
7328 gfc_init_block (&singleblock);
7329 gfc_add_expr_to_block (&singleblock, res);
7330 singleblock_in_progress = true;
7331 loc = gfc_get_location (&code->loc);
7332 }
7333 else
7334 /* Add the new statement to the block. */
7335 gfc_add_expr_to_block (pblock, res);
7336 }
7337 prev_singleunit = (ompws_flags & OMPWS_CURR_SINGLEUNIT) != 0;
7338 }
7339 }
7340
7341 /* Finish remaining SINGLE block, if we were in the middle of one. */
7342 if (singleblock_in_progress)
7343 {
7344 /* Finish single block and add it to pblock. */
7345 tmp = gfc_finish_block (&singleblock);
7346 tmp = build2_loc (loc, OMP_SINGLE, void_type_node, tmp,
7347 clauses->nowait
7348 ? build_omp_clause (input_location, OMP_CLAUSE_NOWAIT)
7349 : NULL_TREE);
7350 gfc_add_expr_to_block (pblock, tmp);
7351 }
7352
7353 stmt = gfc_finish_block (pblock);
7354 if (TREE_CODE (stmt) != BIND_EXPR)
7355 {
7356 if (!IS_EMPTY_STMT (stmt))
7357 {
7358 tree bindblock = poplevel (1, 0);
7359 stmt = build3_v (BIND_EXPR, NULL, stmt, bindblock);
7360 }
7361 else
7362 poplevel (0, 0);
7363 }
7364 else
7365 poplevel (0, 0);
7366
7367 if (IS_EMPTY_STMT (stmt) && !clauses->nowait)
7368 stmt = gfc_trans_omp_barrier ();
7369
7370 ompws_flags = 0;
7371 return stmt;
7372 }
7373
7374 tree
gfc_trans_oacc_declare(gfc_code * code)7375 gfc_trans_oacc_declare (gfc_code *code)
7376 {
7377 stmtblock_t block;
7378 tree stmt, oacc_clauses;
7379 enum tree_code construct_code;
7380
7381 construct_code = OACC_DATA;
7382
7383 gfc_start_block (&block);
7384
7385 oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.oacc_declare->clauses,
7386 code->loc, false, true);
7387 stmt = gfc_trans_omp_code (code->block->next, true);
7388 stmt = build2_loc (input_location, construct_code, void_type_node, stmt,
7389 oacc_clauses);
7390 gfc_add_expr_to_block (&block, stmt);
7391
7392 return gfc_finish_block (&block);
7393 }
7394
7395 tree
gfc_trans_oacc_directive(gfc_code * code)7396 gfc_trans_oacc_directive (gfc_code *code)
7397 {
7398 switch (code->op)
7399 {
7400 case EXEC_OACC_PARALLEL_LOOP:
7401 case EXEC_OACC_KERNELS_LOOP:
7402 case EXEC_OACC_SERIAL_LOOP:
7403 return gfc_trans_oacc_combined_directive (code);
7404 case EXEC_OACC_PARALLEL:
7405 case EXEC_OACC_KERNELS:
7406 case EXEC_OACC_SERIAL:
7407 case EXEC_OACC_DATA:
7408 case EXEC_OACC_HOST_DATA:
7409 return gfc_trans_oacc_construct (code);
7410 case EXEC_OACC_LOOP:
7411 return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses,
7412 NULL);
7413 case EXEC_OACC_UPDATE:
7414 case EXEC_OACC_CACHE:
7415 case EXEC_OACC_ENTER_DATA:
7416 case EXEC_OACC_EXIT_DATA:
7417 return gfc_trans_oacc_executable_directive (code);
7418 case EXEC_OACC_WAIT:
7419 return gfc_trans_oacc_wait_directive (code);
7420 case EXEC_OACC_ATOMIC:
7421 return gfc_trans_omp_atomic (code);
7422 case EXEC_OACC_DECLARE:
7423 return gfc_trans_oacc_declare (code);
7424 default:
7425 gcc_unreachable ();
7426 }
7427 }
7428
7429 tree
gfc_trans_omp_directive(gfc_code * code)7430 gfc_trans_omp_directive (gfc_code *code)
7431 {
7432 switch (code->op)
7433 {
7434 case EXEC_OMP_ATOMIC:
7435 return gfc_trans_omp_atomic (code);
7436 case EXEC_OMP_BARRIER:
7437 return gfc_trans_omp_barrier ();
7438 case EXEC_OMP_CANCEL:
7439 return gfc_trans_omp_cancel (code);
7440 case EXEC_OMP_CANCELLATION_POINT:
7441 return gfc_trans_omp_cancellation_point (code);
7442 case EXEC_OMP_CRITICAL:
7443 return gfc_trans_omp_critical (code);
7444 case EXEC_OMP_DEPOBJ:
7445 return gfc_trans_omp_depobj (code);
7446 case EXEC_OMP_DISTRIBUTE:
7447 case EXEC_OMP_DO:
7448 case EXEC_OMP_LOOP:
7449 case EXEC_OMP_SIMD:
7450 case EXEC_OMP_TASKLOOP:
7451 return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses,
7452 NULL);
7453 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
7454 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
7455 case EXEC_OMP_DISTRIBUTE_SIMD:
7456 return gfc_trans_omp_distribute (code, NULL);
7457 case EXEC_OMP_DO_SIMD:
7458 return gfc_trans_omp_do_simd (code, NULL, NULL, NULL_TREE);
7459 case EXEC_OMP_ERROR:
7460 return gfc_trans_omp_error (code);
7461 case EXEC_OMP_FLUSH:
7462 return gfc_trans_omp_flush (code);
7463 case EXEC_OMP_MASKED:
7464 return gfc_trans_omp_masked (code, NULL);
7465 case EXEC_OMP_MASTER:
7466 return gfc_trans_omp_master (code);
7467 case EXEC_OMP_MASKED_TASKLOOP:
7468 case EXEC_OMP_MASKED_TASKLOOP_SIMD:
7469 case EXEC_OMP_MASTER_TASKLOOP:
7470 case EXEC_OMP_MASTER_TASKLOOP_SIMD:
7471 return gfc_trans_omp_master_masked_taskloop (code, code->op);
7472 case EXEC_OMP_ORDERED:
7473 return gfc_trans_omp_ordered (code);
7474 case EXEC_OMP_PARALLEL:
7475 return gfc_trans_omp_parallel (code);
7476 case EXEC_OMP_PARALLEL_DO:
7477 return gfc_trans_omp_parallel_do (code, false, NULL, NULL);
7478 case EXEC_OMP_PARALLEL_LOOP:
7479 return gfc_trans_omp_parallel_do (code, true, NULL, NULL);
7480 case EXEC_OMP_PARALLEL_DO_SIMD:
7481 return gfc_trans_omp_parallel_do_simd (code, NULL, NULL);
7482 case EXEC_OMP_PARALLEL_MASKED:
7483 case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
7484 case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
7485 case EXEC_OMP_PARALLEL_MASTER:
7486 case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
7487 case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
7488 return gfc_trans_omp_parallel_master_masked (code);
7489 case EXEC_OMP_PARALLEL_SECTIONS:
7490 return gfc_trans_omp_parallel_sections (code);
7491 case EXEC_OMP_PARALLEL_WORKSHARE:
7492 return gfc_trans_omp_parallel_workshare (code);
7493 case EXEC_OMP_SCOPE:
7494 return gfc_trans_omp_scope (code);
7495 case EXEC_OMP_SECTIONS:
7496 return gfc_trans_omp_sections (code, code->ext.omp_clauses);
7497 case EXEC_OMP_SINGLE:
7498 return gfc_trans_omp_single (code, code->ext.omp_clauses);
7499 case EXEC_OMP_TARGET:
7500 case EXEC_OMP_TARGET_PARALLEL:
7501 case EXEC_OMP_TARGET_PARALLEL_DO:
7502 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
7503 case EXEC_OMP_TARGET_PARALLEL_LOOP:
7504 case EXEC_OMP_TARGET_SIMD:
7505 case EXEC_OMP_TARGET_TEAMS:
7506 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
7507 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
7508 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
7509 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
7510 case EXEC_OMP_TARGET_TEAMS_LOOP:
7511 return gfc_trans_omp_target (code);
7512 case EXEC_OMP_TARGET_DATA:
7513 return gfc_trans_omp_target_data (code);
7514 case EXEC_OMP_TARGET_ENTER_DATA:
7515 return gfc_trans_omp_target_enter_data (code);
7516 case EXEC_OMP_TARGET_EXIT_DATA:
7517 return gfc_trans_omp_target_exit_data (code);
7518 case EXEC_OMP_TARGET_UPDATE:
7519 return gfc_trans_omp_target_update (code);
7520 case EXEC_OMP_TASK:
7521 return gfc_trans_omp_task (code);
7522 case EXEC_OMP_TASKGROUP:
7523 return gfc_trans_omp_taskgroup (code);
7524 case EXEC_OMP_TASKLOOP_SIMD:
7525 return gfc_trans_omp_taskloop (code, code->op);
7526 case EXEC_OMP_TASKWAIT:
7527 return gfc_trans_omp_taskwait (code);
7528 case EXEC_OMP_TASKYIELD:
7529 return gfc_trans_omp_taskyield ();
7530 case EXEC_OMP_TEAMS:
7531 case EXEC_OMP_TEAMS_DISTRIBUTE:
7532 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
7533 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
7534 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
7535 case EXEC_OMP_TEAMS_LOOP:
7536 return gfc_trans_omp_teams (code, NULL, NULL_TREE);
7537 case EXEC_OMP_WORKSHARE:
7538 return gfc_trans_omp_workshare (code, code->ext.omp_clauses);
7539 default:
7540 gcc_unreachable ();
7541 }
7542 }
7543
7544 void
gfc_trans_omp_declare_simd(gfc_namespace * ns)7545 gfc_trans_omp_declare_simd (gfc_namespace *ns)
7546 {
7547 if (ns->entries)
7548 return;
7549
7550 gfc_omp_declare_simd *ods;
7551 for (ods = ns->omp_declare_simd; ods; ods = ods->next)
7552 {
7553 tree c = gfc_trans_omp_clauses (NULL, ods->clauses, ods->where, true);
7554 tree fndecl = ns->proc_name->backend_decl;
7555 if (c != NULL_TREE)
7556 c = tree_cons (NULL_TREE, c, NULL_TREE);
7557 c = build_tree_list (get_identifier ("omp declare simd"), c);
7558 TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
7559 DECL_ATTRIBUTES (fndecl) = c;
7560 }
7561 }
7562
7563 void
gfc_trans_omp_declare_variant(gfc_namespace * ns)7564 gfc_trans_omp_declare_variant (gfc_namespace *ns)
7565 {
7566 tree base_fn_decl = ns->proc_name->backend_decl;
7567 gfc_namespace *search_ns = ns;
7568 gfc_omp_declare_variant *next;
7569
7570 for (gfc_omp_declare_variant *odv = search_ns->omp_declare_variant;
7571 search_ns; odv = next)
7572 {
7573 /* Look in the parent namespace if there are no more directives in the
7574 current namespace. */
7575 if (!odv)
7576 {
7577 search_ns = search_ns->parent;
7578 if (search_ns)
7579 next = search_ns->omp_declare_variant;
7580 continue;
7581 }
7582
7583 next = odv->next;
7584
7585 if (odv->error_p)
7586 continue;
7587
7588 /* Check directive the first time it is encountered. */
7589 bool error_found = true;
7590
7591 if (odv->checked_p)
7592 error_found = false;
7593 if (odv->base_proc_symtree == NULL)
7594 {
7595 if (!search_ns->proc_name->attr.function
7596 && !search_ns->proc_name->attr.subroutine)
7597 gfc_error ("The base name for 'declare variant' must be "
7598 "specified at %L ", &odv->where);
7599 else
7600 error_found = false;
7601 }
7602 else
7603 {
7604 if (!search_ns->contained
7605 && strcmp (odv->base_proc_symtree->name,
7606 ns->proc_name->name))
7607 gfc_error ("The base name at %L does not match the name of the "
7608 "current procedure", &odv->where);
7609 else if (odv->base_proc_symtree->n.sym->attr.entry)
7610 gfc_error ("The base name at %L must not be an entry name",
7611 &odv->where);
7612 else if (odv->base_proc_symtree->n.sym->attr.generic)
7613 gfc_error ("The base name at %L must not be a generic name",
7614 &odv->where);
7615 else if (odv->base_proc_symtree->n.sym->attr.proc_pointer)
7616 gfc_error ("The base name at %L must not be a procedure pointer",
7617 &odv->where);
7618 else if (odv->base_proc_symtree->n.sym->attr.implicit_type)
7619 gfc_error ("The base procedure at %L must have an explicit "
7620 "interface", &odv->where);
7621 else
7622 error_found = false;
7623 }
7624
7625 odv->checked_p = true;
7626 if (error_found)
7627 {
7628 odv->error_p = true;
7629 continue;
7630 }
7631
7632 /* Ignore directives that do not apply to the current procedure. */
7633 if ((odv->base_proc_symtree == NULL && search_ns != ns)
7634 || (odv->base_proc_symtree != NULL
7635 && strcmp (odv->base_proc_symtree->name, ns->proc_name->name)))
7636 continue;
7637
7638 tree set_selectors = NULL_TREE;
7639 gfc_omp_set_selector *oss;
7640
7641 for (oss = odv->set_selectors; oss; oss = oss->next)
7642 {
7643 tree selectors = NULL_TREE;
7644 gfc_omp_selector *os;
7645 for (os = oss->trait_selectors; os; os = os->next)
7646 {
7647 tree properties = NULL_TREE;
7648 gfc_omp_trait_property *otp;
7649
7650 for (otp = os->properties; otp; otp = otp->next)
7651 {
7652 switch (otp->property_kind)
7653 {
7654 case CTX_PROPERTY_USER:
7655 case CTX_PROPERTY_EXPR:
7656 {
7657 gfc_se se;
7658 gfc_init_se (&se, NULL);
7659 gfc_conv_expr (&se, otp->expr);
7660 properties = tree_cons (NULL_TREE, se.expr,
7661 properties);
7662 }
7663 break;
7664 case CTX_PROPERTY_ID:
7665 properties = tree_cons (get_identifier (otp->name),
7666 NULL_TREE, properties);
7667 break;
7668 case CTX_PROPERTY_NAME_LIST:
7669 {
7670 tree prop = NULL_TREE, value = NULL_TREE;
7671 if (otp->is_name)
7672 prop = get_identifier (otp->name);
7673 else
7674 value = gfc_conv_constant_to_tree (otp->expr);
7675
7676 properties = tree_cons (prop, value, properties);
7677 }
7678 break;
7679 case CTX_PROPERTY_SIMD:
7680 properties = gfc_trans_omp_clauses (NULL, otp->clauses,
7681 odv->where, true);
7682 break;
7683 default:
7684 gcc_unreachable ();
7685 }
7686 }
7687
7688 if (os->score)
7689 {
7690 gfc_se se;
7691 gfc_init_se (&se, NULL);
7692 gfc_conv_expr (&se, os->score);
7693 properties = tree_cons (get_identifier (" score"),
7694 se.expr, properties);
7695 }
7696
7697 selectors = tree_cons (get_identifier (os->trait_selector_name),
7698 properties, selectors);
7699 }
7700
7701 set_selectors
7702 = tree_cons (get_identifier (oss->trait_set_selector_name),
7703 selectors, set_selectors);
7704 }
7705
7706 const char *variant_proc_name = odv->variant_proc_symtree->name;
7707 gfc_symbol *variant_proc_sym = odv->variant_proc_symtree->n.sym;
7708 if (variant_proc_sym == NULL || variant_proc_sym->attr.implicit_type)
7709 {
7710 gfc_symtree *proc_st;
7711 gfc_find_sym_tree (variant_proc_name, gfc_current_ns, 1, &proc_st);
7712 variant_proc_sym = proc_st->n.sym;
7713 }
7714 if (variant_proc_sym == NULL)
7715 {
7716 gfc_error ("Cannot find symbol %qs", variant_proc_name);
7717 continue;
7718 }
7719 set_selectors = omp_check_context_selector
7720 (gfc_get_location (&odv->where), set_selectors);
7721 if (set_selectors != error_mark_node)
7722 {
7723 if (!variant_proc_sym->attr.implicit_type
7724 && !variant_proc_sym->attr.subroutine
7725 && !variant_proc_sym->attr.function)
7726 {
7727 gfc_error ("variant %qs at %L is not a function or subroutine",
7728 variant_proc_name, &odv->where);
7729 variant_proc_sym = NULL;
7730 }
7731 else if (omp_get_context_selector (set_selectors, "construct",
7732 "simd") == NULL_TREE)
7733 {
7734 char err[256];
7735 if (!gfc_compare_interfaces (ns->proc_name, variant_proc_sym,
7736 variant_proc_sym->name, 0, 1,
7737 err, sizeof (err), NULL, NULL))
7738 {
7739 gfc_error ("variant %qs and base %qs at %L have "
7740 "incompatible types: %s",
7741 variant_proc_name, ns->proc_name->name,
7742 &odv->where, err);
7743 variant_proc_sym = NULL;
7744 }
7745 }
7746 if (variant_proc_sym != NULL)
7747 {
7748 gfc_set_sym_referenced (variant_proc_sym);
7749 tree construct = omp_get_context_selector (set_selectors,
7750 "construct", NULL);
7751 omp_mark_declare_variant (gfc_get_location (&odv->where),
7752 gfc_get_symbol_decl (variant_proc_sym),
7753 construct);
7754 if (omp_context_selector_matches (set_selectors))
7755 {
7756 tree id = get_identifier ("omp declare variant base");
7757 tree variant = gfc_get_symbol_decl (variant_proc_sym);
7758 DECL_ATTRIBUTES (base_fn_decl)
7759 = tree_cons (id, build_tree_list (variant, set_selectors),
7760 DECL_ATTRIBUTES (base_fn_decl));
7761 }
7762 }
7763 }
7764 }
7765 }
7766