cselib: Discard useless locs of preserved VALUEs [PR116627]
[official-gcc.git] / gcc / fortran / trans-openmp.cc
blob3a335ade0f737cc7426ecbb77bd314d6d1ef0b9b
1 /* OpenMP directive translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2005-2024 Free Software Foundation, Inc.
3 Contributed by Jakub Jelinek <jakub@redhat.com>
5 This file is part of GCC.
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.
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.
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/>. */
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 #include "dependency.h"
45 #undef GCC_DIAG_STYLE
46 #define GCC_DIAG_STYLE __gcc_tdiag__
47 #include "diagnostic-core.h"
48 #undef GCC_DIAG_STYLE
49 #define GCC_DIAG_STYLE __gcc_gfc__
50 #include "attribs.h"
51 #include "function.h"
53 int ompws_flags;
55 /* True if OpenMP should regard this DECL as being a scalar which has Fortran's
56 allocatable or pointer attribute. */
58 bool
59 gfc_omp_is_allocatable_or_ptr (const_tree decl)
61 return (DECL_P (decl)
62 && (GFC_DECL_GET_SCALAR_POINTER (decl)
63 || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)));
66 /* True if the argument is an optional argument; except that false is also
67 returned for arguments with the value attribute (nonpointers) and for
68 assumed-shape variables (decl is a local variable containing arg->data).
69 Note that for 'procedure(), optional' the value false is used as that's
70 always a pointer and no additional indirection is used.
71 Note that pvoid_type_node is for 'type(c_ptr), value' (and c_funloc). */
73 static bool
74 gfc_omp_is_optional_argument (const_tree decl)
76 /* Note: VAR_DECL can occur with BIND(C) and array descriptors. */
77 return ((TREE_CODE (decl) == PARM_DECL || VAR_P (decl))
78 && DECL_LANG_SPECIFIC (decl)
79 && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
80 && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
81 && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) != FUNCTION_TYPE
82 && GFC_DECL_OPTIONAL_ARGUMENT (decl));
85 /* Check whether this DECL belongs to a Fortran optional argument.
86 With 'for_present_check' set to false, decls which are optional parameters
87 themselves are returned as tree - or a NULL_TREE otherwise. Those decls are
88 always pointers. With 'for_present_check' set to true, the decl for checking
89 whether an argument is present is returned; for arguments with value
90 attribute this is the hidden argument and of BOOLEAN_TYPE. If the decl is
91 unrelated to optional arguments, NULL_TREE is returned. */
93 tree
94 gfc_omp_check_optional_argument (tree decl, bool for_present_check)
96 if (!for_present_check)
97 return gfc_omp_is_optional_argument (decl) ? decl : NULL_TREE;
99 if (!DECL_LANG_SPECIFIC (decl))
100 return NULL_TREE;
102 tree orig_decl = decl;
104 /* For assumed-shape arrays, a local decl with arg->data is used. */
105 if (TREE_CODE (decl) != PARM_DECL
106 && (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))
107 || GFC_ARRAY_TYPE_P (TREE_TYPE (decl))))
108 decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
110 /* Note: With BIND(C), array descriptors are converted to a VAR_DECL. */
111 if (decl == NULL_TREE
112 || (TREE_CODE (decl) != PARM_DECL && TREE_CODE (decl) != VAR_DECL)
113 || !DECL_LANG_SPECIFIC (decl)
114 || !GFC_DECL_OPTIONAL_ARGUMENT (decl))
115 return NULL_TREE;
117 /* Scalars with VALUE attribute which are passed by value use a hidden
118 argument to denote the present status. They are passed as nonpointer type
119 with one exception: 'type(c_ptr), value' as 'void*'. */
120 /* Cf. trans-expr.cc's gfc_conv_expr_present. */
121 if (TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE
122 || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
124 char name[GFC_MAX_SYMBOL_LEN + 2];
125 tree tree_name;
127 name[0] = '.';
128 strcpy (&name[1], IDENTIFIER_POINTER (DECL_NAME (decl)));
129 tree_name = get_identifier (name);
131 /* Walk function argument list to find the hidden arg. */
132 decl = DECL_ARGUMENTS (DECL_CONTEXT (decl));
133 for ( ; decl != NULL_TREE; decl = TREE_CHAIN (decl))
134 if (DECL_NAME (decl) == tree_name
135 && DECL_ARTIFICIAL (decl))
136 break;
138 gcc_assert (decl);
139 return decl;
142 return fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
143 orig_decl, null_pointer_node);
147 /* Returns tree with NULL if it is not an array descriptor and with the tree to
148 access the 'data' component otherwise. With type_only = true, it returns the
149 TREE_TYPE without creating a new tree. */
151 tree
152 gfc_omp_array_data (tree decl, bool type_only)
154 tree type = TREE_TYPE (decl);
156 if (POINTER_TYPE_P (type))
157 type = TREE_TYPE (type);
159 if (!GFC_DESCRIPTOR_TYPE_P (type))
160 return NULL_TREE;
162 if (type_only)
163 return GFC_TYPE_ARRAY_DATAPTR_TYPE (type);
165 if (POINTER_TYPE_P (TREE_TYPE (decl)))
166 decl = build_fold_indirect_ref (decl);
168 decl = gfc_conv_descriptor_data_get (decl);
169 STRIP_NOPS (decl);
170 return decl;
173 /* Return the byte-size of the passed array descriptor. */
175 tree
176 gfc_omp_array_size (tree decl, gimple_seq *pre_p)
178 stmtblock_t block;
179 if (POINTER_TYPE_P (TREE_TYPE (decl)))
180 decl = build_fold_indirect_ref (decl);
181 tree type = TREE_TYPE (decl);
182 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
183 bool allocatable = (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
184 || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER
185 || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT);
186 gfc_init_block (&block);
187 tree size = gfc_full_array_size (&block, decl,
188 GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)));
189 size = fold_convert (size_type_node, size);
190 tree elemsz = gfc_get_element_type (TREE_TYPE (decl));
191 if (TREE_CODE (elemsz) == ARRAY_TYPE && TYPE_STRING_FLAG (elemsz))
192 elemsz = gfc_conv_descriptor_elem_len (decl);
193 else
194 elemsz = TYPE_SIZE_UNIT (elemsz);
195 size = fold_build2 (MULT_EXPR, size_type_node, size, elemsz);
196 if (!allocatable)
197 gimplify_and_add (gfc_finish_block (&block), pre_p);
198 else
200 tree var = create_tmp_var (size_type_node);
201 gfc_add_expr_to_block (&block, build2 (MODIFY_EXPR, sizetype, var, size));
202 tree tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
203 gfc_conv_descriptor_data_get (decl),
204 null_pointer_node);
205 tmp = build3_loc (input_location, COND_EXPR, void_type_node, tmp,
206 gfc_finish_block (&block),
207 build2 (MODIFY_EXPR, sizetype, var, size_zero_node));
208 gimplify_and_add (tmp, pre_p);
209 size = var;
211 return size;
215 /* True if OpenMP should privatize what this DECL points to rather
216 than the DECL itself. */
218 bool
219 gfc_omp_privatize_by_reference (const_tree decl)
221 tree type = TREE_TYPE (decl);
223 if (TREE_CODE (type) == REFERENCE_TYPE
224 && (!DECL_ARTIFICIAL (decl) || TREE_CODE (decl) == PARM_DECL))
225 return true;
227 if (TREE_CODE (type) == POINTER_TYPE
228 && gfc_omp_is_optional_argument (decl))
229 return true;
231 if (TREE_CODE (type) == POINTER_TYPE)
233 while (TREE_CODE (decl) == COMPONENT_REF)
234 decl = TREE_OPERAND (decl, 1);
236 /* Array POINTER/ALLOCATABLE have aggregate types, all user variables
237 that have POINTER_TYPE type and aren't scalar pointers, scalar
238 allocatables, Cray pointees or C pointers are supposed to be
239 privatized by reference. */
240 if (GFC_DECL_GET_SCALAR_POINTER (decl)
241 || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
242 || GFC_DECL_CRAY_POINTEE (decl)
243 || GFC_DECL_ASSOCIATE_VAR_P (decl)
244 || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
245 return false;
247 if (!DECL_ARTIFICIAL (decl)
248 && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
249 return true;
251 /* Some arrays are expanded as DECL_ARTIFICIAL pointers
252 by the frontend. */
253 if (DECL_LANG_SPECIFIC (decl)
254 && GFC_DECL_SAVED_DESCRIPTOR (decl))
255 return true;
258 return false;
261 /* OMP_CLAUSE_DEFAULT_UNSPECIFIED unless OpenMP sharing attribute
262 of DECL is predetermined. */
264 enum omp_clause_default_kind
265 gfc_omp_predetermined_sharing (tree decl)
267 /* Associate names preserve the association established during ASSOCIATE.
268 As they are implemented either as pointers to the selector or array
269 descriptor and shouldn't really change in the ASSOCIATE region,
270 this decl can be either shared or firstprivate. If it is a pointer,
271 use firstprivate, as it is cheaper that way, otherwise make it shared. */
272 if (GFC_DECL_ASSOCIATE_VAR_P (decl))
274 if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
275 return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
276 else
277 return OMP_CLAUSE_DEFAULT_SHARED;
280 if (DECL_ARTIFICIAL (decl)
281 && ! GFC_DECL_RESULT (decl)
282 && ! (DECL_LANG_SPECIFIC (decl)
283 && GFC_DECL_SAVED_DESCRIPTOR (decl)))
284 return OMP_CLAUSE_DEFAULT_SHARED;
286 /* Cray pointees shouldn't be listed in any clauses and should be
287 gimplified to dereference of the corresponding Cray pointer.
288 Make them all private, so that they are emitted in the debug
289 information. */
290 if (GFC_DECL_CRAY_POINTEE (decl))
291 return OMP_CLAUSE_DEFAULT_PRIVATE;
293 /* Assumed-size arrays are predetermined shared. */
294 if (TREE_CODE (decl) == PARM_DECL
295 && GFC_ARRAY_TYPE_P (TREE_TYPE (decl))
296 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN
297 && GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (decl),
298 GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)) - 1)
299 == NULL)
300 return OMP_CLAUSE_DEFAULT_SHARED;
302 /* Dummy procedures aren't considered variables by OpenMP, thus are
303 disallowed in OpenMP clauses. They are represented as PARM_DECLs
304 in the middle-end, so return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE here
305 to avoid complaining about their uses with default(none). */
306 if (TREE_CODE (decl) == PARM_DECL
307 && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
308 && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == FUNCTION_TYPE)
309 return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
311 /* COMMON and EQUIVALENCE decls are shared. They
312 are only referenced through DECL_VALUE_EXPR of the variables
313 contained in them. If those are privatized, they will not be
314 gimplified to the COMMON or EQUIVALENCE decls. */
315 if (GFC_DECL_COMMON_OR_EQUIV (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
316 return OMP_CLAUSE_DEFAULT_SHARED;
318 if (GFC_DECL_RESULT (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
319 return OMP_CLAUSE_DEFAULT_SHARED;
321 /* These are either array or derived parameters, or vtables.
322 In the former cases, the OpenMP standard doesn't consider them to be
323 variables at all (they can't be redefined), but they can nevertheless appear
324 in parallel/task regions and for default(none) purposes treat them as shared.
325 For vtables likely the same handling is desirable. */
326 if (VAR_P (decl) && TREE_READONLY (decl)
327 && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
328 return OMP_CLAUSE_DEFAULT_SHARED;
330 return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
334 /* OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED unless OpenMP mapping attribute
335 of DECL is predetermined. */
337 enum omp_clause_defaultmap_kind
338 gfc_omp_predetermined_mapping (tree decl)
340 if (DECL_ARTIFICIAL (decl)
341 && ! GFC_DECL_RESULT (decl)
342 && ! (DECL_LANG_SPECIFIC (decl)
343 && GFC_DECL_SAVED_DESCRIPTOR (decl)))
344 return OMP_CLAUSE_DEFAULTMAP_TO;
346 /* Dummy procedures aren't considered variables by OpenMP, thus are
347 disallowed in OpenMP clauses. They are represented as PARM_DECLs
348 in the middle-end, so return OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE here
349 to avoid complaining about their uses with defaultmap(none). */
350 if (TREE_CODE (decl) == PARM_DECL
351 && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
352 && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == FUNCTION_TYPE)
353 return OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
355 /* These are either array or derived parameters, or vtables. */
356 if (VAR_P (decl) && TREE_READONLY (decl)
357 && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
358 return OMP_CLAUSE_DEFAULTMAP_TO;
360 return OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
364 /* Return decl that should be used when reporting DEFAULT(NONE)
365 diagnostics. */
367 tree
368 gfc_omp_report_decl (tree decl)
370 if (DECL_ARTIFICIAL (decl)
371 && DECL_LANG_SPECIFIC (decl)
372 && GFC_DECL_SAVED_DESCRIPTOR (decl))
373 return GFC_DECL_SAVED_DESCRIPTOR (decl);
375 return decl;
378 /* Return true if TYPE has any allocatable components. */
380 static bool
381 gfc_has_alloc_comps (tree type, tree decl)
383 tree field, ftype;
385 if (POINTER_TYPE_P (type))
387 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
388 type = TREE_TYPE (type);
389 else if (GFC_DECL_GET_SCALAR_POINTER (decl))
390 return false;
393 if (GFC_DESCRIPTOR_TYPE_P (type)
394 && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER
395 || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
396 return false;
398 if (GFC_DESCRIPTOR_TYPE_P (type) || GFC_ARRAY_TYPE_P (type))
399 type = gfc_get_element_type (type);
401 if (TREE_CODE (type) != RECORD_TYPE)
402 return false;
404 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
406 ftype = TREE_TYPE (field);
407 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
408 return true;
409 if (GFC_DESCRIPTOR_TYPE_P (ftype)
410 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
411 return true;
412 if (gfc_has_alloc_comps (ftype, field))
413 return true;
415 return false;
418 /* Return true if TYPE is polymorphic but not with pointer attribute. */
420 static bool
421 gfc_is_polymorphic_nonptr (tree type)
423 if (POINTER_TYPE_P (type))
424 type = TREE_TYPE (type);
425 return GFC_CLASS_TYPE_P (type);
428 /* Return true if TYPE is unlimited polymorphic but not with pointer attribute;
429 unlimited means also intrinsic types are handled and _len is used. */
431 static bool
432 gfc_is_unlimited_polymorphic_nonptr (tree type)
434 if (POINTER_TYPE_P (type))
435 type = TREE_TYPE (type);
436 if (!GFC_CLASS_TYPE_P (type))
437 return false;
439 tree field = TYPE_FIELDS (type); /* _data */
440 gcc_assert (field);
441 field = DECL_CHAIN (field); /* _vptr */
442 gcc_assert (field);
443 field = DECL_CHAIN (field);
444 if (!field)
445 return false;
446 gcc_assert (strcmp ("_len", IDENTIFIER_POINTER (DECL_NAME (field))) == 0);
447 return true;
450 /* Return true if the DECL is for an allocatable array or scalar. */
452 bool
453 gfc_omp_allocatable_p (tree decl)
455 if (!DECL_P (decl))
456 return false;
458 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
459 return true;
461 tree type = TREE_TYPE (decl);
462 if (gfc_omp_privatize_by_reference (decl))
463 type = TREE_TYPE (type);
465 if (GFC_DESCRIPTOR_TYPE_P (type)
466 && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
467 return true;
469 return false;
473 /* Return true if DECL in private clause needs
474 OMP_CLAUSE_PRIVATE_OUTER_REF on the private clause. */
475 bool
476 gfc_omp_private_outer_ref (tree decl)
478 tree type = TREE_TYPE (decl);
480 if (gfc_omp_privatize_by_reference (decl))
481 type = TREE_TYPE (type);
483 if (GFC_DESCRIPTOR_TYPE_P (type)
484 && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
485 return true;
487 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
488 return true;
490 if (gfc_has_alloc_comps (type, decl))
491 return true;
493 return false;
496 /* Callback for gfc_omp_unshare_expr. */
498 static tree
499 gfc_omp_unshare_expr_r (tree *tp, int *walk_subtrees, void *)
501 tree t = *tp;
502 enum tree_code code = TREE_CODE (t);
504 /* Stop at types, decls, constants like copy_tree_r. */
505 if (TREE_CODE_CLASS (code) == tcc_type
506 || TREE_CODE_CLASS (code) == tcc_declaration
507 || TREE_CODE_CLASS (code) == tcc_constant
508 || code == BLOCK)
509 *walk_subtrees = 0;
510 else if (handled_component_p (t)
511 || TREE_CODE (t) == MEM_REF)
513 *tp = unshare_expr (t);
514 *walk_subtrees = 0;
517 return NULL_TREE;
520 /* Unshare in expr anything that the FE which normally doesn't
521 care much about tree sharing (because during gimplification
522 everything is unshared) could cause problems with tree sharing
523 at omp-low.cc time. */
525 static tree
526 gfc_omp_unshare_expr (tree expr)
528 walk_tree (&expr, gfc_omp_unshare_expr_r, NULL, NULL);
529 return expr;
532 enum walk_alloc_comps
534 WALK_ALLOC_COMPS_DTOR,
535 WALK_ALLOC_COMPS_DEFAULT_CTOR,
536 WALK_ALLOC_COMPS_COPY_CTOR
539 /* Handle allocatable components in OpenMP clauses. */
541 static tree
542 gfc_walk_alloc_comps (tree decl, tree dest, tree var,
543 enum walk_alloc_comps kind)
545 stmtblock_t block, tmpblock;
546 tree type = TREE_TYPE (decl), then_b, tem, field;
547 gfc_init_block (&block);
549 if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
551 if (GFC_DESCRIPTOR_TYPE_P (type))
553 gfc_init_block (&tmpblock);
554 tem = gfc_full_array_size (&tmpblock, decl,
555 GFC_TYPE_ARRAY_RANK (type));
556 then_b = gfc_finish_block (&tmpblock);
557 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (then_b));
558 tem = gfc_omp_unshare_expr (tem);
559 tem = fold_build2_loc (input_location, MINUS_EXPR,
560 gfc_array_index_type, tem,
561 gfc_index_one_node);
563 else
565 bool compute_nelts = false;
566 if (!TYPE_DOMAIN (type)
567 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE
568 || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node
569 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node)
570 compute_nelts = true;
571 else if (VAR_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
573 tree a = DECL_ATTRIBUTES (TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
574 if (lookup_attribute ("omp dummy var", a))
575 compute_nelts = true;
577 if (compute_nelts)
579 tem = fold_build2 (EXACT_DIV_EXPR, sizetype,
580 TYPE_SIZE_UNIT (type),
581 TYPE_SIZE_UNIT (TREE_TYPE (type)));
582 tem = size_binop (MINUS_EXPR, tem, size_one_node);
584 else
585 tem = array_type_nelts (type);
586 tem = fold_convert (gfc_array_index_type, tem);
589 tree nelems = gfc_evaluate_now (tem, &block);
590 tree index = gfc_create_var (gfc_array_index_type, "S");
592 gfc_init_block (&tmpblock);
593 tem = gfc_conv_array_data (decl);
594 tree declvar = build_fold_indirect_ref_loc (input_location, tem);
595 tree declvref = gfc_build_array_ref (declvar, index, NULL);
596 tree destvar, destvref = NULL_TREE;
597 if (dest)
599 tem = gfc_conv_array_data (dest);
600 destvar = build_fold_indirect_ref_loc (input_location, tem);
601 destvref = gfc_build_array_ref (destvar, index, NULL);
603 gfc_add_expr_to_block (&tmpblock,
604 gfc_walk_alloc_comps (declvref, destvref,
605 var, kind));
607 gfc_loopinfo loop;
608 gfc_init_loopinfo (&loop);
609 loop.dimen = 1;
610 loop.from[0] = gfc_index_zero_node;
611 loop.loopvar[0] = index;
612 loop.to[0] = nelems;
613 gfc_trans_scalarizing_loops (&loop, &tmpblock);
614 gfc_add_block_to_block (&block, &loop.pre);
615 return gfc_finish_block (&block);
617 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (var))
619 decl = build_fold_indirect_ref_loc (input_location, decl);
620 if (dest)
621 dest = build_fold_indirect_ref_loc (input_location, dest);
622 type = TREE_TYPE (decl);
625 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
626 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
628 tree ftype = TREE_TYPE (field);
629 tree declf, destf = NULL_TREE;
630 bool has_alloc_comps = gfc_has_alloc_comps (ftype, field);
631 if ((!GFC_DESCRIPTOR_TYPE_P (ftype)
632 || GFC_TYPE_ARRAY_AKIND (ftype) != GFC_ARRAY_ALLOCATABLE)
633 && !GFC_DECL_GET_SCALAR_ALLOCATABLE (field)
634 && !has_alloc_comps)
635 continue;
636 declf = fold_build3_loc (input_location, COMPONENT_REF, ftype,
637 decl, field, NULL_TREE);
638 if (dest)
639 destf = fold_build3_loc (input_location, COMPONENT_REF, ftype,
640 dest, field, NULL_TREE);
642 tem = NULL_TREE;
643 switch (kind)
645 case WALK_ALLOC_COMPS_DTOR:
646 break;
647 case WALK_ALLOC_COMPS_DEFAULT_CTOR:
648 if (GFC_DESCRIPTOR_TYPE_P (ftype)
649 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
651 gfc_add_modify (&block, unshare_expr (destf),
652 unshare_expr (declf));
653 tem = gfc_duplicate_allocatable_nocopy
654 (destf, declf, ftype,
655 GFC_TYPE_ARRAY_RANK (ftype));
657 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
658 tem = gfc_duplicate_allocatable_nocopy (destf, declf, ftype, 0);
659 break;
660 case WALK_ALLOC_COMPS_COPY_CTOR:
661 if (GFC_DESCRIPTOR_TYPE_P (ftype)
662 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
663 tem = gfc_duplicate_allocatable (destf, declf, ftype,
664 GFC_TYPE_ARRAY_RANK (ftype),
665 NULL_TREE);
666 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
667 tem = gfc_duplicate_allocatable (destf, declf, ftype, 0,
668 NULL_TREE);
669 break;
671 if (tem)
672 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
673 if (has_alloc_comps)
675 gfc_init_block (&tmpblock);
676 gfc_add_expr_to_block (&tmpblock,
677 gfc_walk_alloc_comps (declf, destf,
678 field, kind));
679 then_b = gfc_finish_block (&tmpblock);
680 if (GFC_DESCRIPTOR_TYPE_P (ftype)
681 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
682 tem = gfc_conv_descriptor_data_get (unshare_expr (declf));
683 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
684 tem = unshare_expr (declf);
685 else
686 tem = NULL_TREE;
687 if (tem)
689 tem = fold_convert (pvoid_type_node, tem);
690 tem = fold_build2_loc (input_location, NE_EXPR,
691 logical_type_node, tem,
692 null_pointer_node);
693 then_b = build3_loc (input_location, COND_EXPR, void_type_node,
694 tem, then_b,
695 build_empty_stmt (input_location));
697 gfc_add_expr_to_block (&block, then_b);
699 if (kind == WALK_ALLOC_COMPS_DTOR)
701 if (GFC_DESCRIPTOR_TYPE_P (ftype)
702 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
704 tem = gfc_conv_descriptor_data_get (unshare_expr (declf));
705 tem = gfc_deallocate_with_status (tem, NULL_TREE, NULL_TREE,
706 NULL_TREE, NULL_TREE, true,
707 NULL,
708 GFC_CAF_COARRAY_NOCOARRAY);
709 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
711 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
713 tem = gfc_call_free (unshare_expr (declf));
714 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
719 return gfc_finish_block (&block);
722 /* Return code to initialize DECL with its default constructor, or
723 NULL if there's nothing to do. */
725 tree
726 gfc_omp_clause_default_ctor (tree clause, tree decl, tree outer)
728 tree type = TREE_TYPE (decl), size, ptr, cond, then_b, else_b;
729 stmtblock_t block, cond_block;
731 switch (OMP_CLAUSE_CODE (clause))
733 case OMP_CLAUSE__LOOPTEMP_:
734 case OMP_CLAUSE__REDUCTEMP_:
735 case OMP_CLAUSE__CONDTEMP_:
736 case OMP_CLAUSE__SCANTEMP_:
737 return NULL;
738 case OMP_CLAUSE_PRIVATE:
739 case OMP_CLAUSE_LASTPRIVATE:
740 case OMP_CLAUSE_LINEAR:
741 case OMP_CLAUSE_REDUCTION:
742 case OMP_CLAUSE_IN_REDUCTION:
743 case OMP_CLAUSE_TASK_REDUCTION:
744 break;
745 default:
746 gcc_unreachable ();
749 if ((! GFC_DESCRIPTOR_TYPE_P (type)
750 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
751 && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
752 || !POINTER_TYPE_P (type)))
754 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
756 gcc_assert (outer);
757 gfc_start_block (&block);
758 tree tem = gfc_walk_alloc_comps (outer, decl,
759 OMP_CLAUSE_DECL (clause),
760 WALK_ALLOC_COMPS_DEFAULT_CTOR);
761 gfc_add_expr_to_block (&block, tem);
762 return gfc_finish_block (&block);
764 return NULL_TREE;
767 gcc_assert (outer != NULL_TREE);
769 /* Allocatable arrays and scalars in PRIVATE clauses need to be set to
770 "not currently allocated" allocation status if outer
771 array is "not currently allocated", otherwise should be allocated. */
772 gfc_start_block (&block);
774 gfc_init_block (&cond_block);
776 if (GFC_DESCRIPTOR_TYPE_P (type))
778 gfc_add_modify (&cond_block, decl, outer);
779 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
780 size = gfc_conv_descriptor_ubound_get (decl, rank);
781 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
782 size,
783 gfc_conv_descriptor_lbound_get (decl, rank));
784 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
785 size, gfc_index_one_node);
786 if (GFC_TYPE_ARRAY_RANK (type) > 1)
787 size = fold_build2_loc (input_location, MULT_EXPR,
788 gfc_array_index_type, size,
789 gfc_conv_descriptor_stride_get (decl, rank));
790 tree esize = fold_convert (gfc_array_index_type,
791 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
792 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
793 size, esize);
794 size = unshare_expr (size);
795 size = gfc_evaluate_now (fold_convert (size_type_node, size),
796 &cond_block);
798 else
799 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
800 ptr = gfc_create_var (pvoid_type_node, NULL);
801 gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
802 if (GFC_DESCRIPTOR_TYPE_P (type))
803 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl), ptr);
804 else
805 gfc_add_modify (&cond_block, unshare_expr (decl),
806 fold_convert (TREE_TYPE (decl), ptr));
807 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
809 tree tem = gfc_walk_alloc_comps (outer, decl,
810 OMP_CLAUSE_DECL (clause),
811 WALK_ALLOC_COMPS_DEFAULT_CTOR);
812 gfc_add_expr_to_block (&cond_block, tem);
814 then_b = gfc_finish_block (&cond_block);
816 /* Reduction clause requires allocated ALLOCATABLE. */
817 if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_REDUCTION
818 && OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_IN_REDUCTION
819 && OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_TASK_REDUCTION)
821 gfc_init_block (&cond_block);
822 if (GFC_DESCRIPTOR_TYPE_P (type))
823 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl),
824 null_pointer_node);
825 else
826 gfc_add_modify (&cond_block, unshare_expr (decl),
827 build_zero_cst (TREE_TYPE (decl)));
828 else_b = gfc_finish_block (&cond_block);
830 tree tem = fold_convert (pvoid_type_node,
831 GFC_DESCRIPTOR_TYPE_P (type)
832 ? gfc_conv_descriptor_data_get (outer) : outer);
833 tem = unshare_expr (tem);
834 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
835 tem, null_pointer_node);
836 gfc_add_expr_to_block (&block,
837 build3_loc (input_location, COND_EXPR,
838 void_type_node, cond, then_b,
839 else_b));
840 /* Avoid -W*uninitialized warnings. */
841 if (DECL_P (decl))
842 suppress_warning (decl, OPT_Wuninitialized);
844 else
845 gfc_add_expr_to_block (&block, then_b);
847 return gfc_finish_block (&block);
850 /* Build and return code for a copy constructor from SRC to DEST. */
852 tree
853 gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
855 tree type = TREE_TYPE (dest), ptr, size, call;
856 tree decl_type = TREE_TYPE (OMP_CLAUSE_DECL (clause));
857 tree cond, then_b, else_b;
858 stmtblock_t block, cond_block;
860 gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE
861 || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
863 /* Privatize pointer, only; cf. gfc_omp_predetermined_sharing. */
864 if (DECL_P (OMP_CLAUSE_DECL (clause))
865 && GFC_DECL_ASSOCIATE_VAR_P (OMP_CLAUSE_DECL (clause)))
866 return build2 (MODIFY_EXPR, TREE_TYPE (dest), dest, src);
868 if (DECL_ARTIFICIAL (OMP_CLAUSE_DECL (clause))
869 && DECL_LANG_SPECIFIC (OMP_CLAUSE_DECL (clause))
870 && GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause)))
871 decl_type
872 = TREE_TYPE (GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause)));
874 if (gfc_is_polymorphic_nonptr (decl_type))
876 if (POINTER_TYPE_P (decl_type))
877 decl_type = TREE_TYPE (decl_type);
878 decl_type = TREE_TYPE (TYPE_FIELDS (decl_type));
879 if (GFC_DESCRIPTOR_TYPE_P (decl_type) || GFC_ARRAY_TYPE_P (decl_type))
880 fatal_error (input_location,
881 "Sorry, polymorphic arrays not yet supported for "
882 "firstprivate");
883 tree src_len;
884 tree nelems = build_int_cst (size_type_node, 1); /* Scalar. */
885 tree src_data = gfc_class_data_get (unshare_expr (src));
886 tree dest_data = gfc_class_data_get (unshare_expr (dest));
887 bool unlimited = gfc_is_unlimited_polymorphic_nonptr (type);
889 gfc_start_block (&block);
890 gfc_add_modify (&block, gfc_class_vptr_get (dest),
891 gfc_class_vptr_get (src));
892 gfc_init_block (&cond_block);
894 if (unlimited)
896 src_len = gfc_class_len_get (src);
897 gfc_add_modify (&cond_block, gfc_class_len_get (unshare_expr (dest)), src_len);
900 /* Use: size = class._vtab._size * (class._len > 0 ? class._len : 1). */
901 size = fold_convert (size_type_node, gfc_class_vtab_size_get (src));
902 if (unlimited)
904 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
905 unshare_expr (src_len),
906 build_zero_cst (TREE_TYPE (src_len)));
907 cond = build3_loc (input_location, COND_EXPR, size_type_node, cond,
908 fold_convert (size_type_node,
909 unshare_expr (src_len)),
910 build_int_cst (size_type_node, 1));
911 size = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
912 size, cond);
915 /* Malloc memory + call class->_vpt->_copy. */
916 call = builtin_decl_explicit (BUILT_IN_MALLOC);
917 call = build_call_expr_loc (input_location, call, 1, size);
918 gfc_add_modify (&cond_block, dest_data,
919 fold_convert (TREE_TYPE (dest_data), call));
920 gfc_add_expr_to_block (&cond_block,
921 gfc_copy_class_to_class (src, dest, nelems,
922 unlimited));
924 gcc_assert (TREE_CODE (dest_data) == COMPONENT_REF);
925 if (!GFC_DECL_GET_SCALAR_ALLOCATABLE (TREE_OPERAND (dest_data, 1)))
927 gfc_add_block_to_block (&block, &cond_block);
929 else
931 /* Create: if (class._data != 0) <cond_block> else class._data = NULL; */
932 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
933 src_data, null_pointer_node);
934 gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR,
935 void_type_node, cond,
936 gfc_finish_block (&cond_block),
937 fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
938 unshare_expr (dest_data), null_pointer_node)));
940 return gfc_finish_block (&block);
943 if ((! GFC_DESCRIPTOR_TYPE_P (type)
944 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
945 && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
946 || !POINTER_TYPE_P (type)))
948 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
950 gfc_start_block (&block);
951 gfc_add_modify (&block, dest, src);
952 tree tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause),
953 WALK_ALLOC_COMPS_COPY_CTOR);
954 gfc_add_expr_to_block (&block, tem);
955 return gfc_finish_block (&block);
957 else
958 return build2_v (MODIFY_EXPR, dest, src);
961 /* Allocatable arrays in FIRSTPRIVATE clauses need to be allocated
962 and copied from SRC. */
963 gfc_start_block (&block);
965 gfc_init_block (&cond_block);
967 gfc_add_modify (&cond_block, dest, fold_convert (TREE_TYPE (dest), src));
968 if (GFC_DESCRIPTOR_TYPE_P (type))
970 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
971 size = gfc_conv_descriptor_ubound_get (dest, rank);
972 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
973 size,
974 gfc_conv_descriptor_lbound_get (dest, rank));
975 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
976 size, gfc_index_one_node);
977 if (GFC_TYPE_ARRAY_RANK (type) > 1)
978 size = fold_build2_loc (input_location, MULT_EXPR,
979 gfc_array_index_type, size,
980 gfc_conv_descriptor_stride_get (dest, rank));
981 tree esize = fold_convert (gfc_array_index_type,
982 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
983 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
984 size, esize);
985 size = unshare_expr (size);
986 size = gfc_evaluate_now (fold_convert (size_type_node, size),
987 &cond_block);
989 else
990 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
991 ptr = gfc_create_var (pvoid_type_node, NULL);
992 gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
993 if (GFC_DESCRIPTOR_TYPE_P (type))
994 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest), ptr);
995 else
996 gfc_add_modify (&cond_block, unshare_expr (dest),
997 fold_convert (TREE_TYPE (dest), ptr));
999 tree srcptr = GFC_DESCRIPTOR_TYPE_P (type)
1000 ? gfc_conv_descriptor_data_get (src) : src;
1001 srcptr = unshare_expr (srcptr);
1002 srcptr = fold_convert (pvoid_type_node, srcptr);
1003 call = build_call_expr_loc (input_location,
1004 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr,
1005 srcptr, size);
1006 gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
1007 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
1009 tree tem = gfc_walk_alloc_comps (src, dest,
1010 OMP_CLAUSE_DECL (clause),
1011 WALK_ALLOC_COMPS_COPY_CTOR);
1012 gfc_add_expr_to_block (&cond_block, tem);
1014 then_b = gfc_finish_block (&cond_block);
1016 gfc_init_block (&cond_block);
1017 if (GFC_DESCRIPTOR_TYPE_P (type))
1018 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest),
1019 null_pointer_node);
1020 else
1021 gfc_add_modify (&cond_block, unshare_expr (dest),
1022 build_zero_cst (TREE_TYPE (dest)));
1023 else_b = gfc_finish_block (&cond_block);
1025 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1026 unshare_expr (srcptr), null_pointer_node);
1027 gfc_add_expr_to_block (&block,
1028 build3_loc (input_location, COND_EXPR,
1029 void_type_node, cond, then_b, else_b));
1030 /* Avoid -W*uninitialized warnings. */
1031 if (DECL_P (dest))
1032 suppress_warning (dest, OPT_Wuninitialized);
1034 return gfc_finish_block (&block);
1037 /* Similarly, except use an intrinsic or pointer assignment operator
1038 instead. */
1040 tree
1041 gfc_omp_clause_assign_op (tree clause, tree dest, tree src)
1043 tree type = TREE_TYPE (dest), ptr, size, call, nonalloc;
1044 tree cond, then_b, else_b;
1045 stmtblock_t block, cond_block, cond_block2, inner_block;
1047 if ((! GFC_DESCRIPTOR_TYPE_P (type)
1048 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
1049 && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
1050 || !POINTER_TYPE_P (type)))
1052 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
1054 gfc_start_block (&block);
1055 /* First dealloc any allocatable components in DEST. */
1056 tree tem = gfc_walk_alloc_comps (dest, NULL_TREE,
1057 OMP_CLAUSE_DECL (clause),
1058 WALK_ALLOC_COMPS_DTOR);
1059 gfc_add_expr_to_block (&block, tem);
1060 /* Then copy over toplevel data. */
1061 gfc_add_modify (&block, dest, src);
1062 /* Finally allocate any allocatable components and copy. */
1063 tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause),
1064 WALK_ALLOC_COMPS_COPY_CTOR);
1065 gfc_add_expr_to_block (&block, tem);
1066 return gfc_finish_block (&block);
1068 else
1069 return build2_v (MODIFY_EXPR, dest, src);
1072 gfc_start_block (&block);
1074 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
1076 then_b = gfc_walk_alloc_comps (dest, NULL_TREE, OMP_CLAUSE_DECL (clause),
1077 WALK_ALLOC_COMPS_DTOR);
1078 tree tem = fold_convert (pvoid_type_node,
1079 GFC_DESCRIPTOR_TYPE_P (type)
1080 ? gfc_conv_descriptor_data_get (dest) : dest);
1081 tem = unshare_expr (tem);
1082 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1083 tem, null_pointer_node);
1084 tem = build3_loc (input_location, COND_EXPR, void_type_node, cond,
1085 then_b, build_empty_stmt (input_location));
1086 gfc_add_expr_to_block (&block, tem);
1089 gfc_init_block (&cond_block);
1091 if (GFC_DESCRIPTOR_TYPE_P (type))
1093 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
1094 size = gfc_conv_descriptor_ubound_get (src, rank);
1095 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
1096 size,
1097 gfc_conv_descriptor_lbound_get (src, rank));
1098 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1099 size, gfc_index_one_node);
1100 if (GFC_TYPE_ARRAY_RANK (type) > 1)
1101 size = fold_build2_loc (input_location, MULT_EXPR,
1102 gfc_array_index_type, size,
1103 gfc_conv_descriptor_stride_get (src, rank));
1104 tree esize = fold_convert (gfc_array_index_type,
1105 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
1106 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1107 size, esize);
1108 size = unshare_expr (size);
1109 size = gfc_evaluate_now (fold_convert (size_type_node, size),
1110 &cond_block);
1112 else
1113 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
1114 ptr = gfc_create_var (pvoid_type_node, NULL);
1116 tree destptr = GFC_DESCRIPTOR_TYPE_P (type)
1117 ? gfc_conv_descriptor_data_get (dest) : dest;
1118 destptr = unshare_expr (destptr);
1119 destptr = fold_convert (pvoid_type_node, destptr);
1120 gfc_add_modify (&cond_block, ptr, destptr);
1122 nonalloc = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
1123 destptr, null_pointer_node);
1124 cond = nonalloc;
1125 if (GFC_DESCRIPTOR_TYPE_P (type))
1127 int i;
1128 for (i = 0; i < GFC_TYPE_ARRAY_RANK (type); i++)
1130 tree rank = gfc_rank_cst[i];
1131 tree tem = gfc_conv_descriptor_ubound_get (src, rank);
1132 tem = fold_build2_loc (input_location, MINUS_EXPR,
1133 gfc_array_index_type, tem,
1134 gfc_conv_descriptor_lbound_get (src, rank));
1135 tem = fold_build2_loc (input_location, PLUS_EXPR,
1136 gfc_array_index_type, tem,
1137 gfc_conv_descriptor_lbound_get (dest, rank));
1138 tem = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1139 tem, gfc_conv_descriptor_ubound_get (dest,
1140 rank));
1141 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1142 logical_type_node, cond, tem);
1146 gfc_init_block (&cond_block2);
1148 if (GFC_DESCRIPTOR_TYPE_P (type))
1150 gfc_init_block (&inner_block);
1151 gfc_allocate_using_malloc (&inner_block, ptr, size, NULL_TREE);
1152 then_b = gfc_finish_block (&inner_block);
1154 gfc_init_block (&inner_block);
1155 gfc_add_modify (&inner_block, ptr,
1156 gfc_call_realloc (&inner_block, ptr, size));
1157 else_b = gfc_finish_block (&inner_block);
1159 gfc_add_expr_to_block (&cond_block2,
1160 build3_loc (input_location, COND_EXPR,
1161 void_type_node,
1162 unshare_expr (nonalloc),
1163 then_b, else_b));
1164 gfc_add_modify (&cond_block2, dest, src);
1165 gfc_conv_descriptor_data_set (&cond_block2, unshare_expr (dest), ptr);
1167 else
1169 gfc_allocate_using_malloc (&cond_block2, ptr, size, NULL_TREE);
1170 gfc_add_modify (&cond_block2, unshare_expr (dest),
1171 fold_convert (type, ptr));
1173 then_b = gfc_finish_block (&cond_block2);
1174 else_b = build_empty_stmt (input_location);
1176 gfc_add_expr_to_block (&cond_block,
1177 build3_loc (input_location, COND_EXPR,
1178 void_type_node, unshare_expr (cond),
1179 then_b, else_b));
1181 tree srcptr = GFC_DESCRIPTOR_TYPE_P (type)
1182 ? gfc_conv_descriptor_data_get (src) : src;
1183 srcptr = unshare_expr (srcptr);
1184 srcptr = fold_convert (pvoid_type_node, srcptr);
1185 call = build_call_expr_loc (input_location,
1186 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr,
1187 srcptr, size);
1188 gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
1189 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
1191 tree tem = gfc_walk_alloc_comps (src, dest,
1192 OMP_CLAUSE_DECL (clause),
1193 WALK_ALLOC_COMPS_COPY_CTOR);
1194 gfc_add_expr_to_block (&cond_block, tem);
1196 then_b = gfc_finish_block (&cond_block);
1198 if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_COPYIN)
1200 gfc_init_block (&cond_block);
1201 if (GFC_DESCRIPTOR_TYPE_P (type))
1203 tree tmp = gfc_conv_descriptor_data_get (unshare_expr (dest));
1204 tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE,
1205 NULL_TREE, NULL_TREE, true, NULL,
1206 GFC_CAF_COARRAY_NOCOARRAY);
1207 gfc_add_expr_to_block (&cond_block, tmp);
1209 else
1211 destptr = gfc_evaluate_now (destptr, &cond_block);
1212 gfc_add_expr_to_block (&cond_block, gfc_call_free (destptr));
1213 gfc_add_modify (&cond_block, unshare_expr (dest),
1214 build_zero_cst (TREE_TYPE (dest)));
1216 else_b = gfc_finish_block (&cond_block);
1218 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1219 unshare_expr (srcptr), null_pointer_node);
1220 gfc_add_expr_to_block (&block,
1221 build3_loc (input_location, COND_EXPR,
1222 void_type_node, cond,
1223 then_b, else_b));
1225 else
1226 gfc_add_expr_to_block (&block, then_b);
1228 return gfc_finish_block (&block);
1231 static void
1232 gfc_omp_linear_clause_add_loop (stmtblock_t *block, tree dest, tree src,
1233 tree add, tree nelems)
1235 stmtblock_t tmpblock;
1236 tree desta, srca, index = gfc_create_var (gfc_array_index_type, "S");
1237 nelems = gfc_evaluate_now (nelems, block);
1239 gfc_init_block (&tmpblock);
1240 if (TREE_CODE (TREE_TYPE (dest)) == ARRAY_TYPE)
1242 desta = gfc_build_array_ref (dest, index, NULL);
1243 srca = gfc_build_array_ref (src, index, NULL);
1245 else
1247 gcc_assert (POINTER_TYPE_P (TREE_TYPE (dest)));
1248 tree idx = fold_build2 (MULT_EXPR, sizetype,
1249 fold_convert (sizetype, index),
1250 TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (dest))));
1251 desta = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR,
1252 TREE_TYPE (dest), dest,
1253 idx));
1254 srca = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR,
1255 TREE_TYPE (src), src,
1256 idx));
1258 gfc_add_modify (&tmpblock, desta,
1259 fold_build2 (PLUS_EXPR, TREE_TYPE (desta),
1260 srca, add));
1262 gfc_loopinfo loop;
1263 gfc_init_loopinfo (&loop);
1264 loop.dimen = 1;
1265 loop.from[0] = gfc_index_zero_node;
1266 loop.loopvar[0] = index;
1267 loop.to[0] = nelems;
1268 gfc_trans_scalarizing_loops (&loop, &tmpblock);
1269 gfc_add_block_to_block (block, &loop.pre);
1272 /* Build and return code for a constructor of DEST that initializes
1273 it to SRC plus ADD (ADD is scalar integer). */
1275 tree
1276 gfc_omp_clause_linear_ctor (tree clause, tree dest, tree src, tree add)
1278 tree type = TREE_TYPE (dest), ptr, size, nelems = NULL_TREE;
1279 stmtblock_t block;
1281 gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
1283 gfc_start_block (&block);
1284 add = gfc_evaluate_now (add, &block);
1286 if ((! GFC_DESCRIPTOR_TYPE_P (type)
1287 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
1288 && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
1289 || !POINTER_TYPE_P (type)))
1291 bool compute_nelts = false;
1292 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1293 if (!TYPE_DOMAIN (type)
1294 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE
1295 || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node
1296 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node)
1297 compute_nelts = true;
1298 else if (VAR_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
1300 tree a = DECL_ATTRIBUTES (TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
1301 if (lookup_attribute ("omp dummy var", a))
1302 compute_nelts = true;
1304 if (compute_nelts)
1306 nelems = fold_build2 (EXACT_DIV_EXPR, sizetype,
1307 TYPE_SIZE_UNIT (type),
1308 TYPE_SIZE_UNIT (TREE_TYPE (type)));
1309 nelems = size_binop (MINUS_EXPR, nelems, size_one_node);
1311 else
1312 nelems = array_type_nelts (type);
1313 nelems = fold_convert (gfc_array_index_type, nelems);
1315 gfc_omp_linear_clause_add_loop (&block, dest, src, add, nelems);
1316 return gfc_finish_block (&block);
1319 /* Allocatable arrays in LINEAR clauses need to be allocated
1320 and copied from SRC. */
1321 gfc_add_modify (&block, dest, src);
1322 if (GFC_DESCRIPTOR_TYPE_P (type))
1324 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
1325 size = gfc_conv_descriptor_ubound_get (dest, rank);
1326 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
1327 size,
1328 gfc_conv_descriptor_lbound_get (dest, rank));
1329 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1330 size, gfc_index_one_node);
1331 if (GFC_TYPE_ARRAY_RANK (type) > 1)
1332 size = fold_build2_loc (input_location, MULT_EXPR,
1333 gfc_array_index_type, size,
1334 gfc_conv_descriptor_stride_get (dest, rank));
1335 tree esize = fold_convert (gfc_array_index_type,
1336 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
1337 nelems = gfc_evaluate_now (unshare_expr (size), &block);
1338 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1339 nelems, unshare_expr (esize));
1340 size = gfc_evaluate_now (fold_convert (size_type_node, size),
1341 &block);
1342 nelems = fold_build2_loc (input_location, MINUS_EXPR,
1343 gfc_array_index_type, nelems,
1344 gfc_index_one_node);
1346 else
1347 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
1348 ptr = gfc_create_var (pvoid_type_node, NULL);
1349 gfc_allocate_using_malloc (&block, ptr, size, NULL_TREE);
1350 if (GFC_DESCRIPTOR_TYPE_P (type))
1352 gfc_conv_descriptor_data_set (&block, unshare_expr (dest), ptr);
1353 tree etype = gfc_get_element_type (type);
1354 ptr = fold_convert (build_pointer_type (etype), ptr);
1355 tree srcptr = gfc_conv_descriptor_data_get (unshare_expr (src));
1356 srcptr = fold_convert (build_pointer_type (etype), srcptr);
1357 gfc_omp_linear_clause_add_loop (&block, ptr, srcptr, add, nelems);
1359 else
1361 gfc_add_modify (&block, unshare_expr (dest),
1362 fold_convert (TREE_TYPE (dest), ptr));
1363 ptr = fold_convert (TREE_TYPE (dest), ptr);
1364 tree dstm = build_fold_indirect_ref (ptr);
1365 tree srcm = build_fold_indirect_ref (unshare_expr (src));
1366 gfc_add_modify (&block, dstm,
1367 fold_build2 (PLUS_EXPR, TREE_TYPE (add), srcm, add));
1369 return gfc_finish_block (&block);
1372 /* Build and return code destructing DECL. Return NULL if nothing
1373 to be done. */
1375 tree
1376 gfc_omp_clause_dtor (tree clause, tree decl)
1378 tree type = TREE_TYPE (decl), tem;
1379 tree decl_type = TREE_TYPE (OMP_CLAUSE_DECL (clause));
1381 /* Only pointer was privatized; cf. gfc_omp_clause_copy_ctor. */
1382 if (DECL_P (OMP_CLAUSE_DECL (clause))
1383 && GFC_DECL_ASSOCIATE_VAR_P (OMP_CLAUSE_DECL (clause)))
1384 return NULL_TREE;
1386 if (DECL_ARTIFICIAL (OMP_CLAUSE_DECL (clause))
1387 && DECL_LANG_SPECIFIC (OMP_CLAUSE_DECL (clause))
1388 && GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause)))
1389 decl_type
1390 = TREE_TYPE (GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause)));
1391 if (gfc_is_polymorphic_nonptr (decl_type))
1393 if (POINTER_TYPE_P (decl_type))
1394 decl_type = TREE_TYPE (decl_type);
1395 decl_type = TREE_TYPE (TYPE_FIELDS (decl_type));
1396 if (GFC_DESCRIPTOR_TYPE_P (decl_type) || GFC_ARRAY_TYPE_P (decl_type))
1397 fatal_error (input_location,
1398 "Sorry, polymorphic arrays not yet supported for "
1399 "firstprivate");
1400 stmtblock_t block, cond_block;
1401 gfc_start_block (&block);
1402 gfc_init_block (&cond_block);
1403 tree final = gfc_class_vtab_final_get (decl);
1404 tree size = fold_convert (size_type_node, gfc_class_vtab_size_get (decl));
1405 gfc_se se;
1406 gfc_init_se (&se, NULL);
1407 symbol_attribute attr = {};
1408 tree data = gfc_class_data_get (decl);
1409 tree desc = gfc_conv_scalar_to_descriptor (&se, data, attr);
1411 /* Call class->_vpt->_finalize + free. */
1412 tree call = build_fold_indirect_ref (final);
1413 call = build_call_expr_loc (input_location, call, 3,
1414 gfc_build_addr_expr (NULL, desc),
1415 size, boolean_false_node);
1416 gfc_add_block_to_block (&cond_block, &se.pre);
1417 gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
1418 gfc_add_block_to_block (&cond_block, &se.post);
1419 /* Create: if (_vtab && _final) <cond_block> */
1420 tree cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1421 gfc_class_vptr_get (decl),
1422 null_pointer_node);
1423 tree cond2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1424 final, null_pointer_node);
1425 cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
1426 boolean_type_node, cond, cond2);
1427 gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR,
1428 void_type_node, cond,
1429 gfc_finish_block (&cond_block), NULL_TREE));
1430 call = builtin_decl_explicit (BUILT_IN_FREE);
1431 call = build_call_expr_loc (input_location, call, 1, data);
1432 gfc_add_expr_to_block (&block, fold_convert (void_type_node, call));
1433 return gfc_finish_block (&block);
1436 if ((! GFC_DESCRIPTOR_TYPE_P (type)
1437 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
1438 && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
1439 || !POINTER_TYPE_P (type)))
1441 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
1442 return gfc_walk_alloc_comps (decl, NULL_TREE,
1443 OMP_CLAUSE_DECL (clause),
1444 WALK_ALLOC_COMPS_DTOR);
1445 return NULL_TREE;
1448 if (GFC_DESCRIPTOR_TYPE_P (type))
1450 /* Allocatable arrays in FIRSTPRIVATE/LASTPRIVATE etc. clauses need
1451 to be deallocated if they were allocated. */
1452 tem = gfc_conv_descriptor_data_get (decl);
1453 tem = gfc_deallocate_with_status (tem, NULL_TREE, NULL_TREE, NULL_TREE,
1454 NULL_TREE, true, NULL,
1455 GFC_CAF_COARRAY_NOCOARRAY);
1457 else
1458 tem = gfc_call_free (decl);
1459 tem = gfc_omp_unshare_expr (tem);
1461 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
1463 stmtblock_t block;
1464 tree then_b;
1466 gfc_init_block (&block);
1467 gfc_add_expr_to_block (&block,
1468 gfc_walk_alloc_comps (decl, NULL_TREE,
1469 OMP_CLAUSE_DECL (clause),
1470 WALK_ALLOC_COMPS_DTOR));
1471 gfc_add_expr_to_block (&block, tem);
1472 then_b = gfc_finish_block (&block);
1474 tem = fold_convert (pvoid_type_node,
1475 GFC_DESCRIPTOR_TYPE_P (type)
1476 ? gfc_conv_descriptor_data_get (decl) : decl);
1477 tem = unshare_expr (tem);
1478 tree cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1479 tem, null_pointer_node);
1480 tem = build3_loc (input_location, COND_EXPR, void_type_node, cond,
1481 then_b, build_empty_stmt (input_location));
1483 return tem;
1486 /* Build a conditional expression in BLOCK. If COND_VAL is not
1487 null, then the block THEN_B is executed, otherwise ELSE_VAL
1488 is assigned to VAL. */
1490 static void
1491 gfc_build_cond_assign (stmtblock_t *block, tree val, tree cond_val,
1492 tree then_b, tree else_val)
1494 stmtblock_t cond_block;
1495 tree else_b = NULL_TREE;
1496 tree val_ty = TREE_TYPE (val);
1498 if (else_val)
1500 gfc_init_block (&cond_block);
1501 gfc_add_modify (&cond_block, val, fold_convert (val_ty, else_val));
1502 else_b = gfc_finish_block (&cond_block);
1504 gfc_add_expr_to_block (block,
1505 build3_loc (input_location, COND_EXPR, void_type_node,
1506 cond_val, then_b, else_b));
1509 /* Build a conditional expression in BLOCK, returning a temporary
1510 variable containing the result. If COND_VAL is not null, then
1511 THEN_VAL will be assigned to the variable, otherwise ELSE_VAL
1512 is assigned.
1515 static tree
1516 gfc_build_cond_assign_expr (stmtblock_t *block, tree cond_val,
1517 tree then_val, tree else_val)
1519 tree val;
1520 tree val_ty = TREE_TYPE (then_val);
1521 stmtblock_t cond_block;
1523 val = create_tmp_var (val_ty);
1525 gfc_init_block (&cond_block);
1526 gfc_add_modify (&cond_block, val, then_val);
1527 tree then_b = gfc_finish_block (&cond_block);
1529 gfc_build_cond_assign (block, val, cond_val, then_b, else_val);
1531 return val;
1534 void
1535 gfc_omp_finish_clause (tree c, gimple_seq *pre_p, bool openacc)
1537 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
1538 return;
1540 tree decl = OMP_CLAUSE_DECL (c);
1542 /* Assumed-size arrays can't be mapped implicitly, they have to be
1543 mapped explicitly using array sections. */
1544 if (TREE_CODE (decl) == PARM_DECL
1545 && GFC_ARRAY_TYPE_P (TREE_TYPE (decl))
1546 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN
1547 && GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (decl),
1548 GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)) - 1)
1549 == NULL)
1551 error_at (OMP_CLAUSE_LOCATION (c),
1552 "implicit mapping of assumed size array %qD", decl);
1553 return;
1556 tree c2 = NULL_TREE, c3 = NULL_TREE, c4 = NULL_TREE;
1557 tree present = gfc_omp_check_optional_argument (decl, true);
1558 if (POINTER_TYPE_P (TREE_TYPE (decl)))
1560 if (!gfc_omp_privatize_by_reference (decl)
1561 && !GFC_DECL_GET_SCALAR_POINTER (decl)
1562 && !GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
1563 && !GFC_DECL_CRAY_POINTEE (decl)
1564 && !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
1565 return;
1566 tree orig_decl = decl;
1568 c4 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
1569 OMP_CLAUSE_SET_MAP_KIND (c4, GOMP_MAP_POINTER);
1570 OMP_CLAUSE_DECL (c4) = decl;
1571 OMP_CLAUSE_SIZE (c4) = size_int (0);
1572 decl = build_fold_indirect_ref (decl);
1573 if (present
1574 && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
1575 || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
1577 c2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
1578 OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER);
1579 OMP_CLAUSE_DECL (c2) = decl;
1580 OMP_CLAUSE_SIZE (c2) = size_int (0);
1582 stmtblock_t block;
1583 gfc_start_block (&block);
1584 tree ptr = decl;
1585 ptr = gfc_build_cond_assign_expr (&block, present, decl,
1586 null_pointer_node);
1587 gimplify_and_add (gfc_finish_block (&block), pre_p);
1588 ptr = build_fold_indirect_ref (ptr);
1589 OMP_CLAUSE_DECL (c) = ptr;
1590 OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
1592 else
1594 OMP_CLAUSE_DECL (c) = decl;
1595 OMP_CLAUSE_SIZE (c) = NULL_TREE;
1597 if (TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE
1598 && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
1599 || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
1601 c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
1602 OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_POINTER);
1603 OMP_CLAUSE_DECL (c3) = unshare_expr (decl);
1604 OMP_CLAUSE_SIZE (c3) = size_int (0);
1605 decl = build_fold_indirect_ref (decl);
1606 OMP_CLAUSE_DECL (c) = decl;
1609 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
1611 stmtblock_t block;
1612 gfc_start_block (&block);
1613 tree type = TREE_TYPE (decl);
1614 tree ptr = gfc_conv_descriptor_data_get (decl);
1616 /* OpenMP: automatically map pointer targets with the pointer;
1617 hence, always update the descriptor/pointer itself.
1618 NOTE: This also remaps the pointer for allocatable arrays with
1619 'target' attribute which also don't have the 'restrict' qualifier. */
1620 bool always_modifier = false;
1622 if (!openacc
1623 && !(TYPE_QUALS (TREE_TYPE (ptr)) & TYPE_QUAL_RESTRICT))
1624 always_modifier = true;
1626 if (present)
1627 ptr = gfc_build_cond_assign_expr (&block, present, ptr,
1628 null_pointer_node);
1629 gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
1630 ptr = build_fold_indirect_ref (ptr);
1631 OMP_CLAUSE_DECL (c) = ptr;
1632 c2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
1633 OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_TO_PSET);
1634 if (present)
1636 ptr = create_tmp_var (TREE_TYPE (TREE_OPERAND (decl, 0)));
1637 gfc_add_modify (&block, ptr, TREE_OPERAND (decl, 0));
1639 OMP_CLAUSE_DECL (c2) = build_fold_indirect_ref (ptr);
1641 else
1642 OMP_CLAUSE_DECL (c2) = decl;
1643 OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (type);
1644 c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
1645 OMP_CLAUSE_SET_MAP_KIND (c3, always_modifier ? GOMP_MAP_ALWAYS_POINTER
1646 : GOMP_MAP_POINTER);
1647 if (present)
1649 ptr = gfc_conv_descriptor_data_get (decl);
1650 ptr = gfc_build_addr_expr (NULL, ptr);
1651 ptr = gfc_build_cond_assign_expr (&block, present,
1652 ptr, null_pointer_node);
1653 ptr = build_fold_indirect_ref (ptr);
1654 OMP_CLAUSE_DECL (c3) = ptr;
1656 else
1657 OMP_CLAUSE_DECL (c3) = gfc_conv_descriptor_data_get (decl);
1658 OMP_CLAUSE_SIZE (c3) = size_int (0);
1659 tree size = create_tmp_var (gfc_array_index_type);
1660 tree elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
1661 elemsz = fold_convert (gfc_array_index_type, elemsz);
1662 if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
1663 || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER
1664 || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT)
1666 stmtblock_t cond_block;
1667 tree tem, then_b, else_b, zero, cond;
1669 gfc_init_block (&cond_block);
1670 tem = gfc_full_array_size (&cond_block, decl,
1671 GFC_TYPE_ARRAY_RANK (type));
1672 gfc_add_modify (&cond_block, size, tem);
1673 gfc_add_modify (&cond_block, size,
1674 fold_build2 (MULT_EXPR, gfc_array_index_type,
1675 size, elemsz));
1676 then_b = gfc_finish_block (&cond_block);
1677 gfc_init_block (&cond_block);
1678 zero = build_int_cst (gfc_array_index_type, 0);
1679 gfc_add_modify (&cond_block, size, zero);
1680 else_b = gfc_finish_block (&cond_block);
1681 tem = gfc_conv_descriptor_data_get (decl);
1682 tem = fold_convert (pvoid_type_node, tem);
1683 cond = fold_build2_loc (input_location, NE_EXPR,
1684 boolean_type_node, tem, null_pointer_node);
1685 if (present)
1687 cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
1688 boolean_type_node, present, cond);
1690 gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR,
1691 void_type_node, cond,
1692 then_b, else_b));
1694 else if (present)
1696 stmtblock_t cond_block;
1697 tree then_b;
1699 gfc_init_block (&cond_block);
1700 gfc_add_modify (&cond_block, size,
1701 gfc_full_array_size (&cond_block, decl,
1702 GFC_TYPE_ARRAY_RANK (type)));
1703 gfc_add_modify (&cond_block, size,
1704 fold_build2 (MULT_EXPR, gfc_array_index_type,
1705 size, elemsz));
1706 then_b = gfc_finish_block (&cond_block);
1708 gfc_build_cond_assign (&block, size, present, then_b,
1709 build_int_cst (gfc_array_index_type, 0));
1711 else
1713 gfc_add_modify (&block, size,
1714 gfc_full_array_size (&block, decl,
1715 GFC_TYPE_ARRAY_RANK (type)));
1716 gfc_add_modify (&block, size,
1717 fold_build2 (MULT_EXPR, gfc_array_index_type,
1718 size, elemsz));
1720 OMP_CLAUSE_SIZE (c) = size;
1721 tree stmt = gfc_finish_block (&block);
1722 gimplify_and_add (stmt, pre_p);
1724 tree last = c;
1725 if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
1726 OMP_CLAUSE_SIZE (c)
1727 = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
1728 : TYPE_SIZE_UNIT (TREE_TYPE (decl));
1729 if (gimplify_expr (&OMP_CLAUSE_SIZE (c), pre_p,
1730 NULL, is_gimple_val, fb_rvalue) == GS_ERROR)
1731 OMP_CLAUSE_SIZE (c) = size_int (0);
1732 if (c2)
1734 OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (last);
1735 OMP_CLAUSE_CHAIN (last) = c2;
1736 last = c2;
1738 if (c3)
1740 OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (last);
1741 OMP_CLAUSE_CHAIN (last) = c3;
1742 last = c3;
1744 if (c4)
1746 OMP_CLAUSE_CHAIN (c4) = OMP_CLAUSE_CHAIN (last);
1747 OMP_CLAUSE_CHAIN (last) = c4;
1752 /* Return true if DECL is a scalar variable (for the purpose of
1753 implicit firstprivatization/mapping). Only if 'ptr_alloc_ok.'
1754 is true, allocatables and pointers are permitted. */
1756 bool
1757 gfc_omp_scalar_p (tree decl, bool ptr_alloc_ok)
1759 tree type = TREE_TYPE (decl);
1760 if (TREE_CODE (type) == REFERENCE_TYPE)
1761 type = TREE_TYPE (type);
1762 if (TREE_CODE (type) == POINTER_TYPE)
1764 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
1765 || GFC_DECL_GET_SCALAR_POINTER (decl))
1767 if (!ptr_alloc_ok)
1768 return false;
1769 type = TREE_TYPE (type);
1771 if (GFC_ARRAY_TYPE_P (type)
1772 || GFC_CLASS_TYPE_P (type))
1773 return false;
1775 if ((TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == INTEGER_TYPE)
1776 && TYPE_STRING_FLAG (type))
1777 return false;
1778 if (INTEGRAL_TYPE_P (type)
1779 || SCALAR_FLOAT_TYPE_P (type)
1780 || COMPLEX_FLOAT_TYPE_P (type))
1781 return true;
1782 return false;
1786 /* Return true if DECL is a scalar with target attribute but does not have the
1787 allocatable (or pointer) attribute (for the purpose of implicit mapping). */
1789 bool
1790 gfc_omp_scalar_target_p (tree decl)
1792 return (DECL_P (decl) && GFC_DECL_GET_SCALAR_TARGET (decl)
1793 && gfc_omp_scalar_p (decl, false));
1797 /* Return true if DECL's DECL_VALUE_EXPR (if any) should be
1798 disregarded in OpenMP construct, because it is going to be
1799 remapped during OpenMP lowering. SHARED is true if DECL
1800 is going to be shared, false if it is going to be privatized. */
1802 bool
1803 gfc_omp_disregard_value_expr (tree decl, bool shared)
1805 if (GFC_DECL_COMMON_OR_EQUIV (decl)
1806 && DECL_HAS_VALUE_EXPR_P (decl))
1808 tree value = DECL_VALUE_EXPR (decl);
1810 if (TREE_CODE (value) == COMPONENT_REF
1811 && VAR_P (TREE_OPERAND (value, 0))
1812 && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
1814 /* If variable in COMMON or EQUIVALENCE is privatized, return
1815 true, as just that variable is supposed to be privatized,
1816 not the whole COMMON or whole EQUIVALENCE.
1817 For shared variables in COMMON or EQUIVALENCE, let them be
1818 gimplified to DECL_VALUE_EXPR, so that for multiple shared vars
1819 from the same COMMON or EQUIVALENCE just one sharing of the
1820 whole COMMON or EQUIVALENCE is enough. */
1821 return ! shared;
1825 if (GFC_DECL_RESULT (decl) && DECL_HAS_VALUE_EXPR_P (decl))
1826 return ! shared;
1828 return false;
1831 /* Return true if DECL that is shared iff SHARED is true should
1832 be put into OMP_CLAUSE_PRIVATE with OMP_CLAUSE_PRIVATE_DEBUG
1833 flag set. */
1835 bool
1836 gfc_omp_private_debug_clause (tree decl, bool shared)
1838 if (GFC_DECL_CRAY_POINTEE (decl))
1839 return true;
1841 if (GFC_DECL_COMMON_OR_EQUIV (decl)
1842 && DECL_HAS_VALUE_EXPR_P (decl))
1844 tree value = DECL_VALUE_EXPR (decl);
1846 if (TREE_CODE (value) == COMPONENT_REF
1847 && VAR_P (TREE_OPERAND (value, 0))
1848 && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
1849 return shared;
1852 return false;
1855 /* Register language specific type size variables as potentially OpenMP
1856 firstprivate variables. */
1858 void
1859 gfc_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
1861 if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
1863 int r;
1865 gcc_assert (TYPE_LANG_SPECIFIC (type) != NULL);
1866 for (r = 0; r < GFC_TYPE_ARRAY_RANK (type); r++)
1868 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_LBOUND (type, r));
1869 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_UBOUND (type, r));
1870 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_STRIDE (type, r));
1872 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_SIZE (type));
1873 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_OFFSET (type));
1878 static inline tree
1879 gfc_trans_add_clause (tree node, tree tail)
1881 OMP_CLAUSE_CHAIN (node) = tail;
1882 return node;
1885 static tree
1886 gfc_trans_omp_variable (gfc_symbol *sym, bool declare_simd)
1888 if (declare_simd)
1890 int cnt = 0;
1891 gfc_symbol *proc_sym;
1892 gfc_formal_arglist *f;
1894 gcc_assert (sym->attr.dummy);
1895 proc_sym = sym->ns->proc_name;
1896 if (proc_sym->attr.entry_master)
1897 ++cnt;
1898 if (gfc_return_by_reference (proc_sym))
1900 ++cnt;
1901 if (proc_sym->ts.type == BT_CHARACTER)
1902 ++cnt;
1904 for (f = gfc_sym_get_dummy_args (proc_sym); f; f = f->next)
1905 if (f->sym == sym)
1906 break;
1907 else if (f->sym)
1908 ++cnt;
1909 gcc_assert (f);
1910 return build_int_cst (integer_type_node, cnt);
1913 tree t = gfc_get_symbol_decl (sym);
1914 tree parent_decl;
1915 int parent_flag;
1916 bool return_value;
1917 bool alternate_entry;
1918 bool entry_master;
1920 return_value = sym->attr.function && sym->result == sym;
1921 alternate_entry = sym->attr.function && sym->attr.entry
1922 && sym->result == sym;
1923 entry_master = sym->attr.result
1924 && sym->ns->proc_name->attr.entry_master
1925 && !gfc_return_by_reference (sym->ns->proc_name);
1926 parent_decl = current_function_decl
1927 ? DECL_CONTEXT (current_function_decl) : NULL_TREE;
1929 if ((t == parent_decl && return_value)
1930 || (sym->ns && sym->ns->proc_name
1931 && sym->ns->proc_name->backend_decl == parent_decl
1932 && (alternate_entry || entry_master)))
1933 parent_flag = 1;
1934 else
1935 parent_flag = 0;
1937 /* Special case for assigning the return value of a function.
1938 Self recursive functions must have an explicit return value. */
1939 if (return_value && (t == current_function_decl || parent_flag))
1940 t = gfc_get_fake_result_decl (sym, parent_flag);
1942 /* Similarly for alternate entry points. */
1943 else if (alternate_entry
1944 && (sym->ns->proc_name->backend_decl == current_function_decl
1945 || parent_flag))
1947 gfc_entry_list *el = NULL;
1949 for (el = sym->ns->entries; el; el = el->next)
1950 if (sym == el->sym)
1952 t = gfc_get_fake_result_decl (sym, parent_flag);
1953 break;
1957 else if (entry_master
1958 && (sym->ns->proc_name->backend_decl == current_function_decl
1959 || parent_flag))
1960 t = gfc_get_fake_result_decl (sym, parent_flag);
1962 return t;
1965 static tree
1966 gfc_trans_omp_variable_list (enum omp_clause_code code,
1967 gfc_omp_namelist *namelist, tree list,
1968 bool declare_simd)
1970 for (; namelist != NULL; namelist = namelist->next)
1971 if (namelist->sym->attr.referenced || declare_simd)
1973 tree t = gfc_trans_omp_variable (namelist->sym, declare_simd);
1974 if (t != error_mark_node)
1976 tree node;
1977 node = build_omp_clause (input_location, code);
1978 OMP_CLAUSE_DECL (node) = t;
1979 list = gfc_trans_add_clause (node, list);
1981 if (code == OMP_CLAUSE_LASTPRIVATE
1982 && namelist->u.lastprivate_conditional)
1983 OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (node) = 1;
1986 return list;
1989 struct omp_udr_find_orig_data
1991 gfc_omp_udr *omp_udr;
1992 bool omp_orig_seen;
1995 static int
1996 omp_udr_find_orig (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
1997 void *data)
1999 struct omp_udr_find_orig_data *cd = (struct omp_udr_find_orig_data *) data;
2000 if ((*e)->expr_type == EXPR_VARIABLE
2001 && (*e)->symtree->n.sym == cd->omp_udr->omp_orig)
2002 cd->omp_orig_seen = true;
2004 return 0;
2007 static void
2008 gfc_trans_omp_array_reduction_or_udr (tree c, gfc_omp_namelist *n, locus where)
2010 gfc_symbol *sym = n->sym;
2011 gfc_symtree *root1 = NULL, *root2 = NULL, *root3 = NULL, *root4 = NULL;
2012 gfc_symtree *symtree1, *symtree2, *symtree3, *symtree4 = NULL;
2013 gfc_symbol init_val_sym, outer_sym, intrinsic_sym;
2014 gfc_symbol omp_var_copy[4];
2015 gfc_expr *e1, *e2, *e3, *e4;
2016 gfc_ref *ref;
2017 tree decl, backend_decl, stmt, type, outer_decl;
2018 locus old_loc = gfc_current_locus;
2019 const char *iname;
2020 bool t;
2021 gfc_omp_udr *udr = n->u2.udr ? n->u2.udr->udr : NULL;
2023 decl = OMP_CLAUSE_DECL (c);
2024 gfc_current_locus = where;
2025 type = TREE_TYPE (decl);
2026 outer_decl = create_tmp_var_raw (type);
2027 if (TREE_CODE (decl) == PARM_DECL
2028 && TREE_CODE (type) == REFERENCE_TYPE
2029 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type))
2030 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (type)) == GFC_ARRAY_ALLOCATABLE)
2032 decl = build_fold_indirect_ref (decl);
2033 type = TREE_TYPE (type);
2036 /* Create a fake symbol for init value. */
2037 memset (&init_val_sym, 0, sizeof (init_val_sym));
2038 init_val_sym.ns = sym->ns;
2039 init_val_sym.name = sym->name;
2040 init_val_sym.ts = sym->ts;
2041 init_val_sym.attr.referenced = 1;
2042 init_val_sym.declared_at = where;
2043 init_val_sym.attr.flavor = FL_VARIABLE;
2044 if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK)
2045 backend_decl = omp_reduction_init (c, gfc_sym_type (&init_val_sym));
2046 else if (udr->initializer_ns)
2047 backend_decl = NULL;
2048 else
2049 switch (sym->ts.type)
2051 case BT_LOGICAL:
2052 case BT_INTEGER:
2053 case BT_REAL:
2054 case BT_COMPLEX:
2055 backend_decl = build_zero_cst (gfc_sym_type (&init_val_sym));
2056 break;
2057 default:
2058 backend_decl = NULL_TREE;
2059 break;
2061 init_val_sym.backend_decl = backend_decl;
2063 /* Create a fake symbol for the outer array reference. */
2064 outer_sym = *sym;
2065 if (sym->as)
2066 outer_sym.as = gfc_copy_array_spec (sym->as);
2067 outer_sym.attr.dummy = 0;
2068 outer_sym.attr.result = 0;
2069 outer_sym.attr.flavor = FL_VARIABLE;
2070 outer_sym.backend_decl = outer_decl;
2071 if (decl != OMP_CLAUSE_DECL (c))
2072 outer_sym.backend_decl = build_fold_indirect_ref (outer_decl);
2074 /* Create fake symtrees for it. */
2075 symtree1 = gfc_new_symtree (&root1, sym->name);
2076 symtree1->n.sym = sym;
2077 gcc_assert (symtree1 == root1);
2079 symtree2 = gfc_new_symtree (&root2, sym->name);
2080 symtree2->n.sym = &init_val_sym;
2081 gcc_assert (symtree2 == root2);
2083 symtree3 = gfc_new_symtree (&root3, sym->name);
2084 symtree3->n.sym = &outer_sym;
2085 gcc_assert (symtree3 == root3);
2087 memset (omp_var_copy, 0, sizeof omp_var_copy);
2088 if (udr)
2090 omp_var_copy[0] = *udr->omp_out;
2091 omp_var_copy[1] = *udr->omp_in;
2092 *udr->omp_out = outer_sym;
2093 *udr->omp_in = *sym;
2094 if (udr->initializer_ns)
2096 omp_var_copy[2] = *udr->omp_priv;
2097 omp_var_copy[3] = *udr->omp_orig;
2098 *udr->omp_priv = *sym;
2099 *udr->omp_orig = outer_sym;
2103 /* Create expressions. */
2104 e1 = gfc_get_expr ();
2105 e1->expr_type = EXPR_VARIABLE;
2106 e1->where = where;
2107 e1->symtree = symtree1;
2108 e1->ts = sym->ts;
2109 if (sym->attr.dimension)
2111 e1->ref = ref = gfc_get_ref ();
2112 ref->type = REF_ARRAY;
2113 ref->u.ar.where = where;
2114 ref->u.ar.as = sym->as;
2115 ref->u.ar.type = AR_FULL;
2116 ref->u.ar.dimen = 0;
2118 t = gfc_resolve_expr (e1);
2119 gcc_assert (t);
2121 e2 = NULL;
2122 if (backend_decl != NULL_TREE)
2124 e2 = gfc_get_expr ();
2125 e2->expr_type = EXPR_VARIABLE;
2126 e2->where = where;
2127 e2->symtree = symtree2;
2128 e2->ts = sym->ts;
2129 t = gfc_resolve_expr (e2);
2130 gcc_assert (t);
2132 else if (udr->initializer_ns == NULL)
2134 gcc_assert (sym->ts.type == BT_DERIVED);
2135 e2 = gfc_default_initializer (&sym->ts);
2136 gcc_assert (e2);
2137 t = gfc_resolve_expr (e2);
2138 gcc_assert (t);
2140 else if (n->u2.udr->initializer->op == EXEC_ASSIGN)
2142 e2 = gfc_copy_expr (n->u2.udr->initializer->expr2);
2143 t = gfc_resolve_expr (e2);
2144 gcc_assert (t);
2146 if (udr && udr->initializer_ns)
2148 struct omp_udr_find_orig_data cd;
2149 cd.omp_udr = udr;
2150 cd.omp_orig_seen = false;
2151 gfc_code_walker (&n->u2.udr->initializer,
2152 gfc_dummy_code_callback, omp_udr_find_orig, &cd);
2153 if (cd.omp_orig_seen)
2154 OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c) = 1;
2157 e3 = gfc_copy_expr (e1);
2158 e3->symtree = symtree3;
2159 t = gfc_resolve_expr (e3);
2160 gcc_assert (t);
2162 iname = NULL;
2163 e4 = NULL;
2164 switch (OMP_CLAUSE_REDUCTION_CODE (c))
2166 case PLUS_EXPR:
2167 case MINUS_EXPR:
2168 e4 = gfc_add (e3, e1);
2169 break;
2170 case MULT_EXPR:
2171 e4 = gfc_multiply (e3, e1);
2172 break;
2173 case TRUTH_ANDIF_EXPR:
2174 e4 = gfc_and (e3, e1);
2175 break;
2176 case TRUTH_ORIF_EXPR:
2177 e4 = gfc_or (e3, e1);
2178 break;
2179 case EQ_EXPR:
2180 e4 = gfc_eqv (e3, e1);
2181 break;
2182 case NE_EXPR:
2183 e4 = gfc_neqv (e3, e1);
2184 break;
2185 case MIN_EXPR:
2186 iname = "min";
2187 break;
2188 case MAX_EXPR:
2189 iname = "max";
2190 break;
2191 case BIT_AND_EXPR:
2192 iname = "iand";
2193 break;
2194 case BIT_IOR_EXPR:
2195 iname = "ior";
2196 break;
2197 case BIT_XOR_EXPR:
2198 iname = "ieor";
2199 break;
2200 case ERROR_MARK:
2201 if (n->u2.udr->combiner->op == EXEC_ASSIGN)
2203 gfc_free_expr (e3);
2204 e3 = gfc_copy_expr (n->u2.udr->combiner->expr1);
2205 e4 = gfc_copy_expr (n->u2.udr->combiner->expr2);
2206 t = gfc_resolve_expr (e3);
2207 gcc_assert (t);
2208 t = gfc_resolve_expr (e4);
2209 gcc_assert (t);
2211 break;
2212 default:
2213 gcc_unreachable ();
2215 if (iname != NULL)
2217 memset (&intrinsic_sym, 0, sizeof (intrinsic_sym));
2218 intrinsic_sym.ns = sym->ns;
2219 intrinsic_sym.name = iname;
2220 intrinsic_sym.ts = sym->ts;
2221 intrinsic_sym.attr.referenced = 1;
2222 intrinsic_sym.attr.intrinsic = 1;
2223 intrinsic_sym.attr.function = 1;
2224 intrinsic_sym.attr.implicit_type = 1;
2225 intrinsic_sym.result = &intrinsic_sym;
2226 intrinsic_sym.declared_at = where;
2228 symtree4 = gfc_new_symtree (&root4, iname);
2229 symtree4->n.sym = &intrinsic_sym;
2230 gcc_assert (symtree4 == root4);
2232 e4 = gfc_get_expr ();
2233 e4->expr_type = EXPR_FUNCTION;
2234 e4->where = where;
2235 e4->symtree = symtree4;
2236 e4->value.function.actual = gfc_get_actual_arglist ();
2237 e4->value.function.actual->expr = e3;
2238 e4->value.function.actual->next = gfc_get_actual_arglist ();
2239 e4->value.function.actual->next->expr = e1;
2241 if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK)
2243 /* e1 and e3 have been stored as arguments of e4, avoid sharing. */
2244 e1 = gfc_copy_expr (e1);
2245 e3 = gfc_copy_expr (e3);
2246 t = gfc_resolve_expr (e4);
2247 gcc_assert (t);
2250 /* Create the init statement list. */
2251 pushlevel ();
2252 if (e2)
2253 stmt = gfc_trans_assignment (e1, e2, false, false);
2254 else
2255 stmt = gfc_trans_call (n->u2.udr->initializer, false,
2256 NULL_TREE, NULL_TREE, false);
2257 if (TREE_CODE (stmt) != BIND_EXPR)
2258 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
2259 else
2260 poplevel (0, 0);
2261 OMP_CLAUSE_REDUCTION_INIT (c) = stmt;
2263 /* Create the merge statement list. */
2264 pushlevel ();
2265 if (e4)
2266 stmt = gfc_trans_assignment (e3, e4, false, true);
2267 else
2268 stmt = gfc_trans_call (n->u2.udr->combiner, false,
2269 NULL_TREE, NULL_TREE, false);
2270 if (TREE_CODE (stmt) != BIND_EXPR)
2271 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
2272 else
2273 poplevel (0, 0);
2274 OMP_CLAUSE_REDUCTION_MERGE (c) = stmt;
2276 /* And stick the placeholder VAR_DECL into the clause as well. */
2277 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = outer_decl;
2279 gfc_current_locus = old_loc;
2281 gfc_free_expr (e1);
2282 if (e2)
2283 gfc_free_expr (e2);
2284 gfc_free_expr (e3);
2285 if (e4)
2286 gfc_free_expr (e4);
2287 free (symtree1);
2288 free (symtree2);
2289 free (symtree3);
2290 free (symtree4);
2291 if (outer_sym.as)
2292 gfc_free_array_spec (outer_sym.as);
2294 if (udr)
2296 *udr->omp_out = omp_var_copy[0];
2297 *udr->omp_in = omp_var_copy[1];
2298 if (udr->initializer_ns)
2300 *udr->omp_priv = omp_var_copy[2];
2301 *udr->omp_orig = omp_var_copy[3];
2306 static tree
2307 gfc_trans_omp_reduction_list (int kind, gfc_omp_namelist *namelist, tree list,
2308 locus where, bool mark_addressable)
2310 omp_clause_code clause = OMP_CLAUSE_REDUCTION;
2311 switch (kind)
2313 case OMP_LIST_REDUCTION:
2314 case OMP_LIST_REDUCTION_INSCAN:
2315 case OMP_LIST_REDUCTION_TASK:
2316 break;
2317 case OMP_LIST_IN_REDUCTION:
2318 clause = OMP_CLAUSE_IN_REDUCTION;
2319 break;
2320 case OMP_LIST_TASK_REDUCTION:
2321 clause = OMP_CLAUSE_TASK_REDUCTION;
2322 break;
2323 default:
2324 gcc_unreachable ();
2326 for (; namelist != NULL; namelist = namelist->next)
2327 if (namelist->sym->attr.referenced)
2329 tree t = gfc_trans_omp_variable (namelist->sym, false);
2330 if (t != error_mark_node)
2332 tree node = build_omp_clause (gfc_get_location (&namelist->where),
2333 clause);
2334 OMP_CLAUSE_DECL (node) = t;
2335 if (mark_addressable)
2336 TREE_ADDRESSABLE (t) = 1;
2337 if (kind == OMP_LIST_REDUCTION_INSCAN)
2338 OMP_CLAUSE_REDUCTION_INSCAN (node) = 1;
2339 if (kind == OMP_LIST_REDUCTION_TASK)
2340 OMP_CLAUSE_REDUCTION_TASK (node) = 1;
2341 switch (namelist->u.reduction_op)
2343 case OMP_REDUCTION_PLUS:
2344 OMP_CLAUSE_REDUCTION_CODE (node) = PLUS_EXPR;
2345 break;
2346 case OMP_REDUCTION_MINUS:
2347 OMP_CLAUSE_REDUCTION_CODE (node) = MINUS_EXPR;
2348 break;
2349 case OMP_REDUCTION_TIMES:
2350 OMP_CLAUSE_REDUCTION_CODE (node) = MULT_EXPR;
2351 break;
2352 case OMP_REDUCTION_AND:
2353 OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ANDIF_EXPR;
2354 break;
2355 case OMP_REDUCTION_OR:
2356 OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ORIF_EXPR;
2357 break;
2358 case OMP_REDUCTION_EQV:
2359 OMP_CLAUSE_REDUCTION_CODE (node) = EQ_EXPR;
2360 break;
2361 case OMP_REDUCTION_NEQV:
2362 OMP_CLAUSE_REDUCTION_CODE (node) = NE_EXPR;
2363 break;
2364 case OMP_REDUCTION_MAX:
2365 OMP_CLAUSE_REDUCTION_CODE (node) = MAX_EXPR;
2366 break;
2367 case OMP_REDUCTION_MIN:
2368 OMP_CLAUSE_REDUCTION_CODE (node) = MIN_EXPR;
2369 break;
2370 case OMP_REDUCTION_IAND:
2371 OMP_CLAUSE_REDUCTION_CODE (node) = BIT_AND_EXPR;
2372 break;
2373 case OMP_REDUCTION_IOR:
2374 OMP_CLAUSE_REDUCTION_CODE (node) = BIT_IOR_EXPR;
2375 break;
2376 case OMP_REDUCTION_IEOR:
2377 OMP_CLAUSE_REDUCTION_CODE (node) = BIT_XOR_EXPR;
2378 break;
2379 case OMP_REDUCTION_USER:
2380 OMP_CLAUSE_REDUCTION_CODE (node) = ERROR_MARK;
2381 break;
2382 default:
2383 gcc_unreachable ();
2385 if (namelist->sym->attr.dimension
2386 || namelist->u.reduction_op == OMP_REDUCTION_USER
2387 || namelist->sym->attr.allocatable)
2388 gfc_trans_omp_array_reduction_or_udr (node, namelist, where);
2389 list = gfc_trans_add_clause (node, list);
2392 return list;
2395 static inline tree
2396 gfc_convert_expr_to_tree (stmtblock_t *block, gfc_expr *expr)
2398 gfc_se se;
2399 tree result;
2401 gfc_init_se (&se, NULL );
2402 gfc_conv_expr (&se, expr);
2403 gfc_add_block_to_block (block, &se.pre);
2404 result = gfc_evaluate_now (se.expr, block);
2405 gfc_add_block_to_block (block, &se.post);
2407 return result;
2410 static vec<tree, va_heap, vl_embed> *doacross_steps;
2413 /* Translate an array section or array element. */
2415 static void
2416 gfc_trans_omp_array_section (stmtblock_t *block, gfc_exec_op op,
2417 gfc_omp_namelist *n, tree decl, bool element,
2418 bool openmp, gomp_map_kind ptr_kind, tree &node,
2419 tree &node2, tree &node3, tree &node4)
2421 gfc_se se;
2422 tree ptr, ptr2;
2423 tree elemsz = NULL_TREE;
2425 gfc_init_se (&se, NULL);
2426 if (element)
2428 gfc_conv_expr_reference (&se, n->expr);
2429 gfc_add_block_to_block (block, &se.pre);
2430 ptr = se.expr;
2432 else
2434 gfc_conv_expr_descriptor (&se, n->expr);
2435 ptr = gfc_conv_array_data (se.expr);
2437 if (n->expr->ts.type == BT_CHARACTER && n->expr->ts.deferred)
2439 gcc_assert (se.string_length);
2440 tree len = gfc_evaluate_now (se.string_length, block);
2441 elemsz = gfc_get_char_type (n->expr->ts.kind);
2442 elemsz = TYPE_SIZE_UNIT (elemsz);
2443 elemsz = fold_build2 (MULT_EXPR, size_type_node,
2444 fold_convert (size_type_node, len), elemsz);
2446 if (element)
2448 if (!elemsz)
2449 elemsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ptr)));
2450 OMP_CLAUSE_SIZE (node) = elemsz;
2452 else
2454 tree type = TREE_TYPE (se.expr);
2455 gfc_add_block_to_block (block, &se.pre);
2456 OMP_CLAUSE_SIZE (node) = gfc_full_array_size (block, se.expr,
2457 GFC_TYPE_ARRAY_RANK (type));
2458 if (!elemsz)
2459 elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
2460 elemsz = fold_convert (gfc_array_index_type, elemsz);
2461 OMP_CLAUSE_SIZE (node) = fold_build2 (MULT_EXPR, gfc_array_index_type,
2462 OMP_CLAUSE_SIZE (node), elemsz);
2464 gcc_assert (se.post.head == NULL_TREE);
2465 gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
2466 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
2467 ptr = fold_convert (ptrdiff_type_node, ptr);
2469 if (POINTER_TYPE_P (TREE_TYPE (decl))
2470 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
2471 && ptr_kind == GOMP_MAP_POINTER
2472 && op != EXEC_OMP_TARGET_EXIT_DATA
2473 && OMP_CLAUSE_MAP_KIND (node) != GOMP_MAP_RELEASE
2474 && OMP_CLAUSE_MAP_KIND (node) != GOMP_MAP_DELETE)
2477 node4 = build_omp_clause (input_location,
2478 OMP_CLAUSE_MAP);
2479 OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER);
2480 OMP_CLAUSE_DECL (node4) = decl;
2481 OMP_CLAUSE_SIZE (node4) = size_int (0);
2482 decl = build_fold_indirect_ref (decl);
2484 else if (ptr_kind == GOMP_MAP_ALWAYS_POINTER
2485 && n->expr->ts.type == BT_CHARACTER
2486 && n->expr->ts.deferred)
2488 gomp_map_kind map_kind;
2489 if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DELETE)
2490 map_kind = OMP_CLAUSE_MAP_KIND (node);
2491 else if (op == EXEC_OMP_TARGET_EXIT_DATA
2492 || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_RELEASE)
2493 map_kind = GOMP_MAP_RELEASE;
2494 else
2495 map_kind = GOMP_MAP_TO;
2496 gcc_assert (se.string_length);
2497 node4 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
2498 OMP_CLAUSE_SET_MAP_KIND (node4, map_kind);
2499 OMP_CLAUSE_DECL (node4) = se.string_length;
2500 OMP_CLAUSE_SIZE (node4) = TYPE_SIZE_UNIT (gfc_charlen_type_node);
2502 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
2504 tree type = TREE_TYPE (decl);
2505 ptr2 = gfc_conv_descriptor_data_get (decl);
2506 node2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
2507 OMP_CLAUSE_DECL (node2) = decl;
2508 OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
2509 if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DELETE
2510 || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_RELEASE
2511 || op == EXEC_OMP_TARGET_EXIT_DATA
2512 || op == EXEC_OACC_EXIT_DATA)
2514 gomp_map_kind map_kind
2515 = OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DELETE ? GOMP_MAP_DELETE
2516 : GOMP_MAP_RELEASE;
2517 OMP_CLAUSE_SET_MAP_KIND (node2, map_kind);
2518 OMP_CLAUSE_RELEASE_DESCRIPTOR (node2) = 1;
2520 else
2521 OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
2522 node3 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
2523 OMP_CLAUSE_SET_MAP_KIND (node3, ptr_kind);
2524 OMP_CLAUSE_DECL (node3) = gfc_conv_descriptor_data_get (decl);
2525 /* This purposely does not include GOMP_MAP_ALWAYS_POINTER. The extra
2526 cast prevents gimplify.cc from recognising it as being part of the
2527 struct - and adding an 'alloc: for the 'desc.data' pointer, which
2528 would break as the 'desc' (the descriptor) is also mapped
2529 (see node4 above). */
2530 if (ptr_kind == GOMP_MAP_ATTACH_DETACH && !openmp)
2531 STRIP_NOPS (OMP_CLAUSE_DECL (node3));
2533 else
2535 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2537 tree offset;
2538 ptr2 = build_fold_addr_expr (decl);
2539 offset = fold_build2 (MINUS_EXPR, ptrdiff_type_node, ptr,
2540 fold_convert (ptrdiff_type_node, ptr2));
2541 offset = build2 (TRUNC_DIV_EXPR, ptrdiff_type_node,
2542 offset, fold_convert (ptrdiff_type_node, elemsz));
2543 offset = build4_loc (input_location, ARRAY_REF,
2544 TREE_TYPE (TREE_TYPE (decl)),
2545 decl, offset, NULL_TREE, NULL_TREE);
2546 OMP_CLAUSE_DECL (node) = offset;
2548 if (ptr_kind == GOMP_MAP_ATTACH_DETACH && openmp)
2549 return;
2551 else
2553 gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl)));
2554 ptr2 = decl;
2556 node3 = build_omp_clause (input_location,
2557 OMP_CLAUSE_MAP);
2558 OMP_CLAUSE_SET_MAP_KIND (node3, ptr_kind);
2559 OMP_CLAUSE_DECL (node3) = decl;
2561 ptr2 = fold_convert (ptrdiff_type_node, ptr2);
2562 OMP_CLAUSE_SIZE (node3) = fold_build2 (MINUS_EXPR, ptrdiff_type_node,
2563 ptr, ptr2);
2566 static tree
2567 handle_iterator (gfc_namespace *ns, stmtblock_t *iter_block, tree block)
2569 tree list = NULL_TREE;
2570 for (gfc_symbol *sym = ns->omp_affinity_iterators; sym; sym = sym->tlink)
2572 gfc_constructor *c;
2573 gfc_se se;
2575 tree last = make_tree_vec (6);
2576 tree iter_var = gfc_get_symbol_decl (sym);
2577 tree type = TREE_TYPE (iter_var);
2578 TREE_VEC_ELT (last, 0) = iter_var;
2579 DECL_CHAIN (iter_var) = BLOCK_VARS (block);
2580 BLOCK_VARS (block) = iter_var;
2582 /* begin */
2583 c = gfc_constructor_first (sym->value->value.constructor);
2584 gfc_init_se (&se, NULL);
2585 gfc_conv_expr (&se, c->expr);
2586 gfc_add_block_to_block (iter_block, &se.pre);
2587 gfc_add_block_to_block (iter_block, &se.post);
2588 TREE_VEC_ELT (last, 1) = fold_convert (type,
2589 gfc_evaluate_now (se.expr,
2590 iter_block));
2591 /* end */
2592 c = gfc_constructor_next (c);
2593 gfc_init_se (&se, NULL);
2594 gfc_conv_expr (&se, c->expr);
2595 gfc_add_block_to_block (iter_block, &se.pre);
2596 gfc_add_block_to_block (iter_block, &se.post);
2597 TREE_VEC_ELT (last, 2) = fold_convert (type,
2598 gfc_evaluate_now (se.expr,
2599 iter_block));
2600 /* step */
2601 c = gfc_constructor_next (c);
2602 tree step;
2603 if (c)
2605 gfc_init_se (&se, NULL);
2606 gfc_conv_expr (&se, c->expr);
2607 gfc_add_block_to_block (iter_block, &se.pre);
2608 gfc_add_block_to_block (iter_block, &se.post);
2609 gfc_conv_expr (&se, c->expr);
2610 step = fold_convert (type,
2611 gfc_evaluate_now (se.expr,
2612 iter_block));
2614 else
2615 step = build_int_cst (type, 1);
2616 TREE_VEC_ELT (last, 3) = step;
2617 /* orig_step */
2618 TREE_VEC_ELT (last, 4) = save_expr (step);
2619 TREE_CHAIN (last) = list;
2620 list = last;
2622 return list;
2625 /* To alleviate quadratic behaviour in checking each entry of a
2626 gfc_omp_namelist against every other entry, we build a hashtable indexed by
2627 gfc_symbol pointer, which we can use in the usual case that a map
2628 expression has a symbol as its root term. Return a namelist based on the
2629 root symbol used by N, building a new table in SYM_ROOTED_NL using the
2630 gfc_omp_namelist N2 (all clauses) if we haven't done so already. */
2632 static gfc_omp_namelist *
2633 get_symbol_rooted_namelist (hash_map<gfc_symbol *,
2634 gfc_omp_namelist *> *&sym_rooted_nl,
2635 gfc_omp_namelist *n,
2636 gfc_omp_namelist *n2, bool *sym_based)
2638 /* Early-out if we have a NULL clause list (e.g. for OpenACC). */
2639 if (!n2)
2640 return NULL;
2642 gfc_symbol *use_sym = NULL;
2644 /* We're only interested in cases where we have an expression, e.g. a
2645 component access. */
2646 if (n->expr && n->expr->expr_type == EXPR_VARIABLE && n->expr->symtree)
2647 use_sym = n->expr->symtree->n.sym;
2649 *sym_based = false;
2651 if (!use_sym)
2652 return n2;
2654 if (!sym_rooted_nl)
2656 sym_rooted_nl = new hash_map<gfc_symbol *, gfc_omp_namelist *> ();
2658 for (; n2 != NULL; n2 = n2->next)
2660 if (!n2->expr
2661 || n2->expr->expr_type != EXPR_VARIABLE
2662 || !n2->expr->symtree)
2663 continue;
2665 gfc_omp_namelist *nl_copy = gfc_get_omp_namelist ();
2666 memcpy (nl_copy, n2, sizeof *nl_copy);
2667 nl_copy->u2.duplicate_of = n2;
2668 nl_copy->next = NULL;
2670 gfc_symbol *idx_sym = n2->expr->symtree->n.sym;
2672 bool existed;
2673 gfc_omp_namelist *&entry
2674 = sym_rooted_nl->get_or_insert (idx_sym, &existed);
2675 if (existed)
2676 nl_copy->next = entry;
2677 entry = nl_copy;
2681 gfc_omp_namelist **n2_sym = sym_rooted_nl->get (use_sym);
2683 if (n2_sym)
2685 *sym_based = true;
2686 return *n2_sym;
2689 return NULL;
2692 static tree
2693 gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
2694 locus where, bool declare_simd = false,
2695 bool openacc = false, gfc_exec_op op = EXEC_NOP)
2697 tree omp_clauses = NULL_TREE, prev_clauses, chunk_size, c;
2698 tree iterator = NULL_TREE;
2699 tree tree_block = NULL_TREE;
2700 stmtblock_t iter_block;
2701 int list, ifc;
2702 enum omp_clause_code clause_code;
2703 gfc_omp_namelist *prev = NULL;
2704 gfc_se se;
2706 if (clauses == NULL)
2707 return NULL_TREE;
2709 hash_map<gfc_symbol *, gfc_omp_namelist *> *sym_rooted_nl = NULL;
2711 for (list = 0; list < OMP_LIST_NUM; list++)
2713 gfc_omp_namelist *n = clauses->lists[list];
2715 if (n == NULL)
2716 continue;
2717 switch (list)
2719 case OMP_LIST_REDUCTION:
2720 case OMP_LIST_REDUCTION_INSCAN:
2721 case OMP_LIST_REDUCTION_TASK:
2722 case OMP_LIST_IN_REDUCTION:
2723 case OMP_LIST_TASK_REDUCTION:
2724 /* An OpenACC async clause indicates the need to set reduction
2725 arguments addressable, to allow asynchronous copy-out. */
2726 omp_clauses = gfc_trans_omp_reduction_list (list, n, omp_clauses,
2727 where, clauses->async);
2728 break;
2729 case OMP_LIST_PRIVATE:
2730 clause_code = OMP_CLAUSE_PRIVATE;
2731 goto add_clause;
2732 case OMP_LIST_SHARED:
2733 clause_code = OMP_CLAUSE_SHARED;
2734 goto add_clause;
2735 case OMP_LIST_FIRSTPRIVATE:
2736 clause_code = OMP_CLAUSE_FIRSTPRIVATE;
2737 goto add_clause;
2738 case OMP_LIST_LASTPRIVATE:
2739 clause_code = OMP_CLAUSE_LASTPRIVATE;
2740 goto add_clause;
2741 case OMP_LIST_COPYIN:
2742 clause_code = OMP_CLAUSE_COPYIN;
2743 goto add_clause;
2744 case OMP_LIST_COPYPRIVATE:
2745 clause_code = OMP_CLAUSE_COPYPRIVATE;
2746 goto add_clause;
2747 case OMP_LIST_UNIFORM:
2748 clause_code = OMP_CLAUSE_UNIFORM;
2749 goto add_clause;
2750 case OMP_LIST_USE_DEVICE:
2751 case OMP_LIST_USE_DEVICE_PTR:
2752 clause_code = OMP_CLAUSE_USE_DEVICE_PTR;
2753 goto add_clause;
2754 case OMP_LIST_USE_DEVICE_ADDR:
2755 clause_code = OMP_CLAUSE_USE_DEVICE_ADDR;
2756 goto add_clause;
2757 case OMP_LIST_IS_DEVICE_PTR:
2758 clause_code = OMP_CLAUSE_IS_DEVICE_PTR;
2759 goto add_clause;
2760 case OMP_LIST_HAS_DEVICE_ADDR:
2761 clause_code = OMP_CLAUSE_HAS_DEVICE_ADDR;
2762 goto add_clause;
2763 case OMP_LIST_NONTEMPORAL:
2764 clause_code = OMP_CLAUSE_NONTEMPORAL;
2765 goto add_clause;
2766 case OMP_LIST_SCAN_IN:
2767 clause_code = OMP_CLAUSE_INCLUSIVE;
2768 goto add_clause;
2769 case OMP_LIST_SCAN_EX:
2770 clause_code = OMP_CLAUSE_EXCLUSIVE;
2771 goto add_clause;
2773 add_clause:
2774 omp_clauses
2775 = gfc_trans_omp_variable_list (clause_code, n, omp_clauses,
2776 declare_simd);
2777 break;
2778 case OMP_LIST_ALIGNED:
2779 for (; n != NULL; n = n->next)
2780 if (n->sym->attr.referenced || declare_simd)
2782 tree t = gfc_trans_omp_variable (n->sym, declare_simd);
2783 if (t != error_mark_node)
2785 tree node = build_omp_clause (input_location,
2786 OMP_CLAUSE_ALIGNED);
2787 OMP_CLAUSE_DECL (node) = t;
2788 if (n->expr)
2790 tree alignment_var;
2792 if (declare_simd)
2793 alignment_var = gfc_conv_constant_to_tree (n->expr);
2794 else
2796 gfc_init_se (&se, NULL);
2797 gfc_conv_expr (&se, n->expr);
2798 gfc_add_block_to_block (block, &se.pre);
2799 alignment_var = gfc_evaluate_now (se.expr, block);
2800 gfc_add_block_to_block (block, &se.post);
2802 OMP_CLAUSE_ALIGNED_ALIGNMENT (node) = alignment_var;
2804 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2807 break;
2808 case OMP_LIST_ALLOCATE:
2810 tree allocator_ = NULL_TREE;
2811 gfc_expr *alloc_expr = NULL;
2812 for (; n != NULL; n = n->next)
2813 if (n->sym->attr.referenced)
2815 tree t = gfc_trans_omp_variable (n->sym, false);
2816 if (t != error_mark_node)
2818 tree node = build_omp_clause (input_location,
2819 OMP_CLAUSE_ALLOCATE);
2820 OMP_CLAUSE_DECL (node) = t;
2821 if (n->u2.allocator)
2823 if (alloc_expr != n->u2.allocator)
2825 gfc_init_se (&se, NULL);
2826 gfc_conv_expr (&se, n->u2.allocator);
2827 gfc_add_block_to_block (block, &se.pre);
2828 allocator_ = gfc_evaluate_now (se.expr, block);
2829 gfc_add_block_to_block (block, &se.post);
2831 OMP_CLAUSE_ALLOCATE_ALLOCATOR (node) = allocator_;
2833 alloc_expr = n->u2.allocator;
2834 if (n->u.align)
2836 tree align_;
2837 gfc_init_se (&se, NULL);
2838 gfc_conv_expr (&se, n->u.align);
2839 gcc_assert (CONSTANT_CLASS_P (se.expr)
2840 && se.pre.head == NULL
2841 && se.post.head == NULL);
2842 align_ = se.expr;
2843 OMP_CLAUSE_ALLOCATE_ALIGN (node) = align_;
2845 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2848 else
2849 alloc_expr = n->u2.allocator;
2851 break;
2852 case OMP_LIST_LINEAR:
2854 gfc_expr *last_step_expr = NULL;
2855 tree last_step = NULL_TREE;
2856 bool last_step_parm = false;
2858 for (; n != NULL; n = n->next)
2860 if (n->expr)
2862 last_step_expr = n->expr;
2863 last_step = NULL_TREE;
2864 last_step_parm = false;
2866 if (n->sym->attr.referenced || declare_simd)
2868 tree t = gfc_trans_omp_variable (n->sym, declare_simd);
2869 if (t != error_mark_node)
2871 tree node = build_omp_clause (input_location,
2872 OMP_CLAUSE_LINEAR);
2873 OMP_CLAUSE_DECL (node) = t;
2874 omp_clause_linear_kind kind;
2875 switch (n->u.linear.op)
2877 case OMP_LINEAR_DEFAULT:
2878 kind = OMP_CLAUSE_LINEAR_DEFAULT;
2879 break;
2880 case OMP_LINEAR_REF:
2881 kind = OMP_CLAUSE_LINEAR_REF;
2882 break;
2883 case OMP_LINEAR_VAL:
2884 kind = OMP_CLAUSE_LINEAR_VAL;
2885 break;
2886 case OMP_LINEAR_UVAL:
2887 kind = OMP_CLAUSE_LINEAR_UVAL;
2888 break;
2889 default:
2890 gcc_unreachable ();
2892 OMP_CLAUSE_LINEAR_KIND (node) = kind;
2893 OMP_CLAUSE_LINEAR_OLD_LINEAR_MODIFIER (node)
2894 = n->u.linear.old_modifier;
2895 if (last_step_expr && last_step == NULL_TREE)
2897 if (!declare_simd)
2899 gfc_init_se (&se, NULL);
2900 gfc_conv_expr (&se, last_step_expr);
2901 gfc_add_block_to_block (block, &se.pre);
2902 last_step = gfc_evaluate_now (se.expr, block);
2903 gfc_add_block_to_block (block, &se.post);
2905 else if (last_step_expr->expr_type == EXPR_VARIABLE)
2907 gfc_symbol *s = last_step_expr->symtree->n.sym;
2908 last_step = gfc_trans_omp_variable (s, true);
2909 last_step_parm = true;
2911 else
2912 last_step
2913 = gfc_conv_constant_to_tree (last_step_expr);
2915 if (last_step_parm)
2917 OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (node) = 1;
2918 OMP_CLAUSE_LINEAR_STEP (node) = last_step;
2920 else
2922 if (kind == OMP_CLAUSE_LINEAR_REF)
2924 tree type;
2925 if (n->sym->attr.flavor == FL_PROCEDURE)
2927 type = gfc_get_function_type (n->sym);
2928 type = build_pointer_type (type);
2930 else
2931 type = gfc_sym_type (n->sym);
2932 if (POINTER_TYPE_P (type))
2933 type = TREE_TYPE (type);
2934 /* Otherwise to be determined what exactly
2935 should be done. */
2936 tree t = fold_convert (sizetype, last_step);
2937 t = size_binop (MULT_EXPR, t,
2938 TYPE_SIZE_UNIT (type));
2939 OMP_CLAUSE_LINEAR_STEP (node) = t;
2941 else
2943 tree type
2944 = gfc_typenode_for_spec (&n->sym->ts);
2945 OMP_CLAUSE_LINEAR_STEP (node)
2946 = fold_convert (type, last_step);
2949 if (n->sym->attr.dimension || n->sym->attr.allocatable)
2950 OMP_CLAUSE_LINEAR_ARRAY (node) = 1;
2951 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2956 break;
2957 case OMP_LIST_AFFINITY:
2958 case OMP_LIST_DEPEND:
2959 iterator = NULL_TREE;
2960 prev = NULL;
2961 prev_clauses = omp_clauses;
2962 for (; n != NULL; n = n->next)
2964 if (iterator && prev->u2.ns != n->u2.ns)
2966 BLOCK_SUBBLOCKS (tree_block) = gfc_finish_block (&iter_block);
2967 TREE_VEC_ELT (iterator, 5) = tree_block;
2968 for (tree c = omp_clauses; c != prev_clauses;
2969 c = OMP_CLAUSE_CHAIN (c))
2970 OMP_CLAUSE_DECL (c) = build_tree_list (iterator,
2971 OMP_CLAUSE_DECL (c));
2972 prev_clauses = omp_clauses;
2973 iterator = NULL_TREE;
2975 if (n->u2.ns && (!prev || prev->u2.ns != n->u2.ns))
2977 gfc_init_block (&iter_block);
2978 tree_block = make_node (BLOCK);
2979 TREE_USED (tree_block) = 1;
2980 BLOCK_VARS (tree_block) = NULL_TREE;
2981 iterator = handle_iterator (n->u2.ns, block,
2982 tree_block);
2984 if (!iterator)
2985 gfc_init_block (&iter_block);
2986 prev = n;
2987 if (list == OMP_LIST_DEPEND
2988 && (n->u.depend_doacross_op == OMP_DOACROSS_SINK_FIRST
2989 || n->u.depend_doacross_op == OMP_DEPEND_SINK_FIRST))
2991 tree vec = NULL_TREE;
2992 unsigned int i;
2993 bool is_depend
2994 = n->u.depend_doacross_op == OMP_DEPEND_SINK_FIRST;
2995 for (i = 0; ; i++)
2997 tree addend = integer_zero_node, t;
2998 bool neg = false;
2999 if (n->sym && n->expr)
3001 addend = gfc_conv_constant_to_tree (n->expr);
3002 if (TREE_CODE (addend) == INTEGER_CST
3003 && tree_int_cst_sgn (addend) == -1)
3005 neg = true;
3006 addend = const_unop (NEGATE_EXPR,
3007 TREE_TYPE (addend), addend);
3011 if (n->sym == NULL)
3012 t = null_pointer_node; /* "omp_cur_iteration - 1". */
3013 else
3014 t = gfc_trans_omp_variable (n->sym, false);
3015 if (t != error_mark_node)
3017 if (i < vec_safe_length (doacross_steps)
3018 && !integer_zerop (addend)
3019 && (*doacross_steps)[i])
3021 tree step = (*doacross_steps)[i];
3022 addend = fold_convert (TREE_TYPE (step), addend);
3023 addend = build2 (TRUNC_DIV_EXPR,
3024 TREE_TYPE (step), addend, step);
3026 vec = tree_cons (addend, t, vec);
3027 if (neg)
3028 OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1;
3030 if (n->next == NULL
3031 || n->next->u.depend_doacross_op != OMP_DOACROSS_SINK)
3032 break;
3033 n = n->next;
3035 if (vec == NULL_TREE)
3036 continue;
3038 tree node = build_omp_clause (input_location,
3039 OMP_CLAUSE_DOACROSS);
3040 OMP_CLAUSE_DOACROSS_KIND (node) = OMP_CLAUSE_DOACROSS_SINK;
3041 OMP_CLAUSE_DOACROSS_DEPEND (node) = is_depend;
3042 OMP_CLAUSE_DECL (node) = nreverse (vec);
3043 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
3044 continue;
3047 if (n->sym && !n->sym->attr.referenced)
3048 continue;
3050 tree node = build_omp_clause (input_location,
3051 list == OMP_LIST_DEPEND
3052 ? OMP_CLAUSE_DEPEND
3053 : OMP_CLAUSE_AFFINITY);
3054 if (n->sym == NULL) /* omp_all_memory */
3055 OMP_CLAUSE_DECL (node) = null_pointer_node;
3056 else if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
3058 tree decl = gfc_trans_omp_variable (n->sym, false);
3059 if (gfc_omp_privatize_by_reference (decl))
3060 decl = build_fold_indirect_ref (decl);
3061 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
3063 decl = gfc_conv_descriptor_data_get (decl);
3064 gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl)));
3065 decl = build_fold_indirect_ref (decl);
3067 else if (n->sym->attr.allocatable || n->sym->attr.pointer)
3068 decl = build_fold_indirect_ref (decl);
3069 else if (DECL_P (decl))
3070 TREE_ADDRESSABLE (decl) = 1;
3071 OMP_CLAUSE_DECL (node) = decl;
3073 else
3075 tree ptr;
3076 gfc_init_se (&se, NULL);
3077 if (n->expr->ref->u.ar.type == AR_ELEMENT)
3079 gfc_conv_expr_reference (&se, n->expr);
3080 ptr = se.expr;
3082 else
3084 gfc_conv_expr_descriptor (&se, n->expr);
3085 ptr = gfc_conv_array_data (se.expr);
3087 gfc_add_block_to_block (&iter_block, &se.pre);
3088 gfc_add_block_to_block (&iter_block, &se.post);
3089 gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
3090 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
3092 if (list == OMP_LIST_DEPEND)
3093 switch (n->u.depend_doacross_op)
3095 case OMP_DEPEND_IN:
3096 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_IN;
3097 break;
3098 case OMP_DEPEND_OUT:
3099 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_OUT;
3100 break;
3101 case OMP_DEPEND_INOUT:
3102 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_INOUT;
3103 break;
3104 case OMP_DEPEND_INOUTSET:
3105 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_INOUTSET;
3106 break;
3107 case OMP_DEPEND_MUTEXINOUTSET:
3108 OMP_CLAUSE_DEPEND_KIND (node)
3109 = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
3110 break;
3111 case OMP_DEPEND_DEPOBJ:
3112 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_DEPOBJ;
3113 break;
3114 default:
3115 gcc_unreachable ();
3117 if (!iterator)
3118 gfc_add_block_to_block (block, &iter_block);
3119 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
3121 if (iterator)
3123 BLOCK_SUBBLOCKS (tree_block) = gfc_finish_block (&iter_block);
3124 TREE_VEC_ELT (iterator, 5) = tree_block;
3125 for (tree c = omp_clauses; c != prev_clauses;
3126 c = OMP_CLAUSE_CHAIN (c))
3127 OMP_CLAUSE_DECL (c) = build_tree_list (iterator,
3128 OMP_CLAUSE_DECL (c));
3130 break;
3131 case OMP_LIST_MAP:
3132 for (; n != NULL; n = n->next)
3134 if (!n->sym->attr.referenced)
3135 continue;
3137 bool always_modifier = false;
3138 tree node = build_omp_clause (input_location, OMP_CLAUSE_MAP);
3139 tree node2 = NULL_TREE;
3140 tree node3 = NULL_TREE;
3141 tree node4 = NULL_TREE;
3142 tree node5 = NULL_TREE;
3144 /* OpenMP: automatically map pointer targets with the pointer;
3145 hence, always update the descriptor/pointer itself. */
3146 if (!openacc
3147 && ((n->expr == NULL && n->sym->attr.pointer)
3148 || (n->expr && gfc_expr_attr (n->expr).pointer)))
3149 always_modifier = true;
3151 if (n->u.map.readonly)
3152 OMP_CLAUSE_MAP_READONLY (node) = 1;
3154 switch (n->u.map.op)
3156 case OMP_MAP_ALLOC:
3157 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALLOC);
3158 break;
3159 case OMP_MAP_IF_PRESENT:
3160 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_IF_PRESENT);
3161 break;
3162 case OMP_MAP_ATTACH:
3163 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ATTACH);
3164 break;
3165 case OMP_MAP_TO:
3166 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TO);
3167 break;
3168 case OMP_MAP_FROM:
3169 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FROM);
3170 break;
3171 case OMP_MAP_TOFROM:
3172 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TOFROM);
3173 break;
3174 case OMP_MAP_ALWAYS_TO:
3175 always_modifier = true;
3176 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TO);
3177 break;
3178 case OMP_MAP_ALWAYS_FROM:
3179 always_modifier = true;
3180 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_FROM);
3181 break;
3182 case OMP_MAP_ALWAYS_TOFROM:
3183 always_modifier = true;
3184 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TOFROM);
3185 break;
3186 case OMP_MAP_PRESENT_ALLOC:
3187 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_PRESENT_ALLOC);
3188 break;
3189 case OMP_MAP_PRESENT_TO:
3190 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_PRESENT_TO);
3191 break;
3192 case OMP_MAP_PRESENT_FROM:
3193 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_PRESENT_FROM);
3194 break;
3195 case OMP_MAP_PRESENT_TOFROM:
3196 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_PRESENT_TOFROM);
3197 break;
3198 case OMP_MAP_ALWAYS_PRESENT_TO:
3199 always_modifier = true;
3200 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_PRESENT_TO);
3201 break;
3202 case OMP_MAP_ALWAYS_PRESENT_FROM:
3203 always_modifier = true;
3204 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_PRESENT_FROM);
3205 break;
3206 case OMP_MAP_ALWAYS_PRESENT_TOFROM:
3207 always_modifier = true;
3208 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_PRESENT_TOFROM);
3209 break;
3210 case OMP_MAP_RELEASE:
3211 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_RELEASE);
3212 break;
3213 case OMP_MAP_DELETE:
3214 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_DELETE);
3215 break;
3216 case OMP_MAP_DETACH:
3217 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_DETACH);
3218 break;
3219 case OMP_MAP_FORCE_ALLOC:
3220 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_ALLOC);
3221 break;
3222 case OMP_MAP_FORCE_TO:
3223 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TO);
3224 break;
3225 case OMP_MAP_FORCE_FROM:
3226 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_FROM);
3227 break;
3228 case OMP_MAP_FORCE_TOFROM:
3229 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TOFROM);
3230 break;
3231 case OMP_MAP_FORCE_PRESENT:
3232 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_PRESENT);
3233 break;
3234 case OMP_MAP_FORCE_DEVICEPTR:
3235 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_DEVICEPTR);
3236 break;
3237 default:
3238 gcc_unreachable ();
3241 tree decl = gfc_trans_omp_variable (n->sym, false);
3242 if (DECL_P (decl))
3243 TREE_ADDRESSABLE (decl) = 1;
3245 gfc_ref *lastref = NULL;
3247 if (n->expr)
3248 for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
3249 if (ref->type == REF_COMPONENT || ref->type == REF_ARRAY)
3250 lastref = ref;
3252 bool allocatable = false, pointer = false;
3254 if (lastref && lastref->type == REF_COMPONENT)
3256 gfc_component *c = lastref->u.c.component;
3258 if (c->ts.type == BT_CLASS)
3260 pointer = CLASS_DATA (c)->attr.class_pointer;
3261 allocatable = CLASS_DATA (c)->attr.allocatable;
3263 else
3265 pointer = c->attr.pointer;
3266 allocatable = c->attr.allocatable;
3270 if (n->expr == NULL
3271 || (n->expr->ref->type == REF_ARRAY
3272 && n->expr->ref->u.ar.type == AR_FULL))
3274 gomp_map_kind map_kind;
3275 tree type = TREE_TYPE (decl);
3276 if (n->sym->ts.type == BT_CHARACTER
3277 && n->sym->ts.deferred
3278 && n->sym->attr.omp_declare_target
3279 && (always_modifier || n->sym->attr.pointer)
3280 && op != EXEC_OMP_TARGET_EXIT_DATA
3281 && n->u.map.op != OMP_MAP_DELETE
3282 && n->u.map.op != OMP_MAP_RELEASE)
3284 gcc_assert (n->sym->ts.u.cl->backend_decl);
3285 node5 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
3286 OMP_CLAUSE_SET_MAP_KIND (node5, GOMP_MAP_ALWAYS_TO);
3287 OMP_CLAUSE_DECL (node5) = n->sym->ts.u.cl->backend_decl;
3288 OMP_CLAUSE_SIZE (node5)
3289 = TYPE_SIZE_UNIT (gfc_charlen_type_node);
3292 tree present = gfc_omp_check_optional_argument (decl, true);
3293 if (openacc && n->sym->ts.type == BT_CLASS)
3295 if (n->sym->attr.optional)
3296 sorry ("optional class parameter");
3297 tree ptr = gfc_class_data_get (decl);
3298 ptr = build_fold_indirect_ref (ptr);
3299 OMP_CLAUSE_DECL (node) = ptr;
3300 OMP_CLAUSE_SIZE (node) = gfc_class_vtab_size_get (decl);
3301 node2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
3302 OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_ATTACH_DETACH);
3303 OMP_CLAUSE_DECL (node2) = gfc_class_data_get (decl);
3304 OMP_CLAUSE_SIZE (node2) = size_int (0);
3305 goto finalize_map_clause;
3307 else if (POINTER_TYPE_P (type)
3308 && (gfc_omp_privatize_by_reference (decl)
3309 || GFC_DECL_GET_SCALAR_POINTER (decl)
3310 || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
3311 || GFC_DECL_CRAY_POINTEE (decl)
3312 || GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type))
3313 || (n->sym->ts.type == BT_DERIVED
3314 && (n->sym->ts.u.derived->ts.f90_type
3315 != BT_VOID))))
3317 tree orig_decl = decl;
3319 /* For nonallocatable, nonpointer arrays, a temporary
3320 variable is generated, but this one is only defined if
3321 the variable is present; hence, we now set it to NULL
3322 to avoid accessing undefined variables. We cannot use
3323 a temporary variable here as otherwise the replacement
3324 of the variables in omp-low.cc will not work. */
3325 if (present && GFC_ARRAY_TYPE_P (type))
3327 tree tmp = fold_build2_loc (input_location,
3328 MODIFY_EXPR,
3329 void_type_node, decl,
3330 null_pointer_node);
3331 tree cond = fold_build1_loc (input_location,
3332 TRUTH_NOT_EXPR,
3333 boolean_type_node,
3334 present);
3335 gfc_add_expr_to_block (block,
3336 build3_loc (input_location,
3337 COND_EXPR,
3338 void_type_node,
3339 cond, tmp,
3340 NULL_TREE));
3342 /* For descriptor types, the unmapping happens below. */
3343 if (op != EXEC_OMP_TARGET_EXIT_DATA
3344 || !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
3346 enum gomp_map_kind gmk = GOMP_MAP_POINTER;
3347 if (op == EXEC_OMP_TARGET_EXIT_DATA
3348 && n->u.map.op == OMP_MAP_DELETE)
3349 gmk = GOMP_MAP_DELETE;
3350 else if (op == EXEC_OMP_TARGET_EXIT_DATA)
3351 gmk = GOMP_MAP_RELEASE;
3352 tree size;
3353 if (gmk == GOMP_MAP_RELEASE || gmk == GOMP_MAP_DELETE)
3354 size = TYPE_SIZE_UNIT (TREE_TYPE (decl));
3355 else
3356 size = size_int (0);
3357 node4 = build_omp_clause (input_location,
3358 OMP_CLAUSE_MAP);
3359 OMP_CLAUSE_SET_MAP_KIND (node4, gmk);
3360 OMP_CLAUSE_DECL (node4) = decl;
3361 OMP_CLAUSE_SIZE (node4) = size;
3363 decl = build_fold_indirect_ref (decl);
3364 if ((TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE
3365 || gfc_omp_is_optional_argument (orig_decl))
3366 && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
3367 || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
3369 enum gomp_map_kind gmk;
3370 if (op == EXEC_OMP_TARGET_EXIT_DATA
3371 && n->u.map.op == OMP_MAP_DELETE)
3372 gmk = GOMP_MAP_DELETE;
3373 else if (op == EXEC_OMP_TARGET_EXIT_DATA)
3374 gmk = GOMP_MAP_RELEASE;
3375 else
3376 gmk = GOMP_MAP_POINTER;
3377 tree size;
3378 if (gmk == GOMP_MAP_RELEASE || gmk == GOMP_MAP_DELETE)
3379 size = TYPE_SIZE_UNIT (TREE_TYPE (decl));
3380 else
3381 size = size_int (0);
3382 node3 = build_omp_clause (input_location,
3383 OMP_CLAUSE_MAP);
3384 OMP_CLAUSE_SET_MAP_KIND (node3, gmk);
3385 OMP_CLAUSE_DECL (node3) = decl;
3386 OMP_CLAUSE_SIZE (node3) = size;
3387 decl = build_fold_indirect_ref (decl);
3390 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
3392 tree type = TREE_TYPE (decl);
3393 tree ptr = gfc_conv_descriptor_data_get (decl);
3394 if (present)
3395 ptr = gfc_build_cond_assign_expr (block, present, ptr,
3396 null_pointer_node);
3397 gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
3398 ptr = build_fold_indirect_ref (ptr);
3399 OMP_CLAUSE_DECL (node) = ptr;
3400 node2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
3401 OMP_CLAUSE_DECL (node2) = decl;
3402 OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
3403 if (n->u.map.op == OMP_MAP_DELETE)
3404 map_kind = GOMP_MAP_DELETE;
3405 else if (op == EXEC_OMP_TARGET_EXIT_DATA
3406 || n->u.map.op == OMP_MAP_RELEASE)
3407 map_kind = GOMP_MAP_RELEASE;
3408 else
3409 map_kind = GOMP_MAP_TO_PSET;
3410 OMP_CLAUSE_SET_MAP_KIND (node2, map_kind);
3412 if (op != EXEC_OMP_TARGET_EXIT_DATA
3413 && n->u.map.op != OMP_MAP_DELETE
3414 && n->u.map.op != OMP_MAP_RELEASE)
3416 node3 = build_omp_clause (input_location,
3417 OMP_CLAUSE_MAP);
3418 if (present)
3420 ptr = gfc_conv_descriptor_data_get (decl);
3421 ptr = gfc_build_addr_expr (NULL, ptr);
3422 ptr = gfc_build_cond_assign_expr (
3423 block, present, ptr, null_pointer_node);
3424 ptr = build_fold_indirect_ref (ptr);
3425 OMP_CLAUSE_DECL (node3) = ptr;
3427 else
3428 OMP_CLAUSE_DECL (node3)
3429 = gfc_conv_descriptor_data_get (decl);
3430 OMP_CLAUSE_SIZE (node3) = size_int (0);
3432 if (n->u.map.op == OMP_MAP_ATTACH)
3434 /* Standalone attach clauses used with arrays with
3435 descriptors must copy the descriptor to the
3436 target, else they won't have anything to
3437 perform the attachment onto (see OpenACC 2.6,
3438 "2.6.3. Data Structures with Pointers"). */
3439 OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_ATTACH);
3440 /* We don't want to map PTR at all in this case,
3441 so delete its node and shuffle the others
3442 down. */
3443 node = node2;
3444 node2 = node3;
3445 node3 = NULL;
3446 goto finalize_map_clause;
3448 else if (n->u.map.op == OMP_MAP_DETACH)
3450 OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_DETACH);
3451 /* Similarly to above, we don't want to unmap PTR
3452 here. */
3453 node = node2;
3454 node2 = node3;
3455 node3 = NULL;
3456 goto finalize_map_clause;
3458 else
3459 OMP_CLAUSE_SET_MAP_KIND (node3,
3460 always_modifier
3461 ? GOMP_MAP_ALWAYS_POINTER
3462 : GOMP_MAP_POINTER);
3465 /* We have to check for n->sym->attr.dimension because
3466 of scalar coarrays. */
3467 if ((n->sym->attr.pointer || n->sym->attr.allocatable)
3468 && n->sym->attr.dimension)
3470 stmtblock_t cond_block;
3471 tree size
3472 = gfc_create_var (gfc_array_index_type, NULL);
3473 tree tem, then_b, else_b, zero, cond;
3475 gfc_init_block (&cond_block);
3477 = gfc_full_array_size (&cond_block, decl,
3478 GFC_TYPE_ARRAY_RANK (type));
3479 tree elemsz;
3480 if (n->sym->ts.type == BT_CHARACTER
3481 && n->sym->ts.deferred)
3483 tree len = n->sym->ts.u.cl->backend_decl;
3484 len = fold_convert (size_type_node, len);
3485 elemsz = gfc_get_char_type (n->sym->ts.kind);
3486 elemsz = TYPE_SIZE_UNIT (elemsz);
3487 elemsz = fold_build2 (MULT_EXPR, size_type_node,
3488 len, elemsz);
3490 else
3491 elemsz
3492 = TYPE_SIZE_UNIT (gfc_get_element_type (type));
3493 elemsz = fold_convert (gfc_array_index_type, elemsz);
3494 tem = fold_build2 (MULT_EXPR, gfc_array_index_type,
3495 tem, elemsz);
3496 gfc_add_modify (&cond_block, size, tem);
3497 then_b = gfc_finish_block (&cond_block);
3498 gfc_init_block (&cond_block);
3499 zero = build_int_cst (gfc_array_index_type, 0);
3500 gfc_add_modify (&cond_block, size, zero);
3501 else_b = gfc_finish_block (&cond_block);
3502 tem = gfc_conv_descriptor_data_get (decl);
3503 tem = fold_convert (pvoid_type_node, tem);
3504 cond = fold_build2_loc (input_location, NE_EXPR,
3505 boolean_type_node,
3506 tem, null_pointer_node);
3507 if (present)
3508 cond = fold_build2_loc (input_location,
3509 TRUTH_ANDIF_EXPR,
3510 boolean_type_node,
3511 present, cond);
3512 gfc_add_expr_to_block (block,
3513 build3_loc (input_location,
3514 COND_EXPR,
3515 void_type_node,
3516 cond, then_b,
3517 else_b));
3518 OMP_CLAUSE_SIZE (node) = size;
3520 else if (n->sym->attr.dimension)
3522 stmtblock_t cond_block;
3523 gfc_init_block (&cond_block);
3524 tree size = gfc_full_array_size (&cond_block, decl,
3525 GFC_TYPE_ARRAY_RANK (type));
3526 tree elemsz
3527 = TYPE_SIZE_UNIT (gfc_get_element_type (type));
3528 elemsz = fold_convert (gfc_array_index_type, elemsz);
3529 size = fold_build2 (MULT_EXPR, gfc_array_index_type,
3530 size, elemsz);
3531 size = gfc_evaluate_now (size, &cond_block);
3532 if (present)
3534 tree var = gfc_create_var (gfc_array_index_type,
3535 NULL);
3536 gfc_add_modify (&cond_block, var, size);
3537 tree cond_body = gfc_finish_block (&cond_block);
3538 tree cond = build3_loc (input_location, COND_EXPR,
3539 void_type_node, present,
3540 cond_body, NULL_TREE);
3541 gfc_add_expr_to_block (block, cond);
3542 OMP_CLAUSE_SIZE (node) = var;
3544 else
3546 gfc_add_block_to_block (block, &cond_block);
3547 OMP_CLAUSE_SIZE (node) = size;
3551 else if (present
3552 && INDIRECT_REF_P (decl)
3553 && INDIRECT_REF_P (TREE_OPERAND (decl, 0)))
3555 /* A single indirectref is handled by the middle end. */
3556 gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
3557 decl = TREE_OPERAND (decl, 0);
3558 decl = gfc_build_cond_assign_expr (block, present, decl,
3559 null_pointer_node);
3560 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (decl);
3562 else
3563 OMP_CLAUSE_DECL (node) = decl;
3565 if (!n->sym->attr.dimension
3566 && n->sym->ts.type == BT_CHARACTER
3567 && n->sym->ts.deferred)
3569 if (!DECL_P (decl))
3571 gcc_assert (TREE_CODE (decl) == INDIRECT_REF);
3572 decl = TREE_OPERAND (decl, 0);
3574 tree cond = fold_build2_loc (input_location, NE_EXPR,
3575 boolean_type_node,
3576 decl, null_pointer_node);
3577 if (present)
3578 cond = fold_build2_loc (input_location,
3579 TRUTH_ANDIF_EXPR,
3580 boolean_type_node,
3581 present, cond);
3582 tree len = n->sym->ts.u.cl->backend_decl;
3583 len = fold_convert (size_type_node, len);
3584 tree size = gfc_get_char_type (n->sym->ts.kind);
3585 size = TYPE_SIZE_UNIT (size);
3586 size = fold_build2 (MULT_EXPR, size_type_node, len, size);
3587 size = build3_loc (input_location,
3588 COND_EXPR,
3589 size_type_node,
3590 cond, size,
3591 size_zero_node);
3592 size = gfc_evaluate_now (size, block);
3593 OMP_CLAUSE_SIZE (node) = size;
3596 else if (n->expr
3597 && n->expr->expr_type == EXPR_VARIABLE
3598 && n->expr->ref->type == REF_ARRAY
3599 && !n->expr->ref->next)
3601 /* An array element or array section which is not part of a
3602 derived type, etc. */
3603 bool element = n->expr->ref->u.ar.type == AR_ELEMENT;
3604 tree type = TREE_TYPE (decl);
3605 gomp_map_kind k = GOMP_MAP_POINTER;
3606 if (!openacc
3607 && !GFC_DESCRIPTOR_TYPE_P (type)
3608 && !(POINTER_TYPE_P (type)
3609 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type))))
3610 k = GOMP_MAP_FIRSTPRIVATE_POINTER;
3611 gfc_trans_omp_array_section (block, op, n, decl, element,
3612 !openacc, k, node, node2,
3613 node3, node4);
3615 else if (n->expr
3616 && n->expr->expr_type == EXPR_VARIABLE
3617 && (n->expr->ref->type == REF_COMPONENT
3618 || n->expr->ref->type == REF_ARRAY)
3619 && lastref
3620 && lastref->type == REF_COMPONENT
3621 && lastref->u.c.component->ts.type != BT_CLASS
3622 && lastref->u.c.component->ts.type != BT_DERIVED
3623 && !lastref->u.c.component->attr.dimension)
3625 /* Derived type access with last component being a scalar. */
3626 gfc_init_se (&se, NULL);
3628 gfc_conv_expr (&se, n->expr);
3629 gfc_add_block_to_block (block, &se.pre);
3630 /* For BT_CHARACTER a pointer is returned. */
3631 OMP_CLAUSE_DECL (node)
3632 = POINTER_TYPE_P (TREE_TYPE (se.expr))
3633 ? build_fold_indirect_ref (se.expr) : se.expr;
3634 gfc_add_block_to_block (block, &se.post);
3635 if (pointer || allocatable)
3637 /* If it's a bare attach/detach clause, we just want
3638 to perform a single attach/detach operation, of the
3639 pointer itself, not of the pointed-to object. */
3640 if (openacc
3641 && (n->u.map.op == OMP_MAP_ATTACH
3642 || n->u.map.op == OMP_MAP_DETACH))
3644 OMP_CLAUSE_DECL (node)
3645 = build_fold_addr_expr (OMP_CLAUSE_DECL (node));
3646 OMP_CLAUSE_SIZE (node) = size_zero_node;
3647 goto finalize_map_clause;
3650 node2 = build_omp_clause (input_location,
3651 OMP_CLAUSE_MAP);
3652 OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_ATTACH_DETACH);
3653 OMP_CLAUSE_DECL (node2)
3654 = POINTER_TYPE_P (TREE_TYPE (se.expr))
3655 ? se.expr
3656 : gfc_build_addr_expr (NULL, se.expr);
3657 OMP_CLAUSE_SIZE (node2) = size_int (0);
3658 if (!openacc
3659 && n->expr->ts.type == BT_CHARACTER
3660 && n->expr->ts.deferred)
3662 gcc_assert (se.string_length);
3663 tree tmp
3664 = gfc_get_char_type (n->expr->ts.kind);
3665 OMP_CLAUSE_SIZE (node)
3666 = fold_build2 (MULT_EXPR, size_type_node,
3667 fold_convert (size_type_node,
3668 se.string_length),
3669 TYPE_SIZE_UNIT (tmp));
3670 gomp_map_kind kind;
3671 if (n->u.map.op == OMP_MAP_DELETE)
3672 kind = GOMP_MAP_DELETE;
3673 else if (op == EXEC_OMP_TARGET_EXIT_DATA)
3674 kind = GOMP_MAP_RELEASE;
3675 else
3676 kind = GOMP_MAP_TO;
3677 node3 = build_omp_clause (input_location,
3678 OMP_CLAUSE_MAP);
3679 OMP_CLAUSE_SET_MAP_KIND (node3, kind);
3680 OMP_CLAUSE_DECL (node3) = se.string_length;
3681 OMP_CLAUSE_SIZE (node3)
3682 = TYPE_SIZE_UNIT (gfc_charlen_type_node);
3686 else if (n->expr
3687 && n->expr->expr_type == EXPR_VARIABLE
3688 && (n->expr->ref->type == REF_COMPONENT
3689 || n->expr->ref->type == REF_ARRAY))
3691 gfc_init_se (&se, NULL);
3692 se.expr = gfc_maybe_dereference_var (n->sym, decl);
3694 for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
3696 if (ref->type == REF_COMPONENT)
3698 if (ref->u.c.sym->attr.extension)
3699 conv_parent_component_references (&se, ref);
3701 gfc_conv_component_ref (&se, ref);
3703 else if (ref->type == REF_ARRAY)
3705 if (ref->u.ar.type == AR_ELEMENT && ref->next)
3706 gfc_conv_array_ref (&se, &ref->u.ar, n->expr,
3707 &n->expr->where);
3708 else
3709 gcc_assert (!ref->next);
3711 else
3712 sorry ("unhandled expression type");
3715 tree inner = se.expr;
3717 /* Last component is a derived type or class pointer. */
3718 if (lastref->type == REF_COMPONENT
3719 && (lastref->u.c.component->ts.type == BT_DERIVED
3720 || lastref->u.c.component->ts.type == BT_CLASS))
3722 if (pointer || (openacc && allocatable))
3724 /* If it's a bare attach/detach clause, we just want
3725 to perform a single attach/detach operation, of the
3726 pointer itself, not of the pointed-to object. */
3727 if (openacc
3728 && (n->u.map.op == OMP_MAP_ATTACH
3729 || n->u.map.op == OMP_MAP_DETACH))
3731 OMP_CLAUSE_DECL (node)
3732 = build_fold_addr_expr (inner);
3733 OMP_CLAUSE_SIZE (node) = size_zero_node;
3734 goto finalize_map_clause;
3737 gfc_omp_namelist *n2
3738 = openacc ? NULL : clauses->lists[OMP_LIST_MAP];
3740 bool sym_based;
3741 n2 = get_symbol_rooted_namelist (sym_rooted_nl, n,
3742 n2, &sym_based);
3744 /* If the last reference is a pointer to a derived
3745 type ("foo%dt_ptr"), check if any subcomponents
3746 of the same derived type member are being mapped
3747 elsewhere in the clause list ("foo%dt_ptr%x",
3748 etc.). If we have such subcomponent mappings,
3749 we only create an ALLOC node for the pointer
3750 itself, and inhibit mapping the whole derived
3751 type. */
3753 for (; n2 != NULL; n2 = n2->next)
3755 if ((!sym_based && n == n2)
3756 || (sym_based && n == n2->u2.duplicate_of)
3757 || !n2->expr)
3758 continue;
3760 if (!gfc_omp_expr_prefix_same (n->expr,
3761 n2->expr))
3762 continue;
3764 gfc_ref *ref1 = n->expr->ref;
3765 gfc_ref *ref2 = n2->expr->ref;
3767 while (ref1->next && ref2->next)
3769 ref1 = ref1->next;
3770 ref2 = ref2->next;
3773 if (ref2->next)
3775 inner = build_fold_addr_expr (inner);
3776 OMP_CLAUSE_SET_MAP_KIND (node,
3777 GOMP_MAP_ALLOC);
3778 OMP_CLAUSE_DECL (node) = inner;
3779 OMP_CLAUSE_SIZE (node)
3780 = TYPE_SIZE_UNIT (TREE_TYPE (inner));
3781 goto finalize_map_clause;
3785 tree data, size;
3787 if (lastref->u.c.component->ts.type == BT_CLASS)
3789 data = gfc_class_data_get (inner);
3790 gcc_assert (POINTER_TYPE_P (TREE_TYPE (data)));
3791 data = build_fold_indirect_ref (data);
3792 size = gfc_class_vtab_size_get (inner);
3794 else /* BT_DERIVED. */
3796 data = inner;
3797 size = TYPE_SIZE_UNIT (TREE_TYPE (inner));
3800 OMP_CLAUSE_DECL (node) = data;
3801 OMP_CLAUSE_SIZE (node) = size;
3802 node2 = build_omp_clause (input_location,
3803 OMP_CLAUSE_MAP);
3804 OMP_CLAUSE_SET_MAP_KIND (node2,
3805 GOMP_MAP_ATTACH_DETACH);
3806 OMP_CLAUSE_DECL (node2) = build_fold_addr_expr (data);
3807 OMP_CLAUSE_SIZE (node2) = size_int (0);
3809 else
3811 OMP_CLAUSE_DECL (node) = inner;
3812 OMP_CLAUSE_SIZE (node)
3813 = TYPE_SIZE_UNIT (TREE_TYPE (inner));
3816 else if (lastref->type == REF_ARRAY
3817 && lastref->u.ar.type == AR_FULL)
3819 /* Bare attach and detach clauses don't want any
3820 additional nodes. */
3821 if ((n->u.map.op == OMP_MAP_ATTACH
3822 || n->u.map.op == OMP_MAP_DETACH)
3823 && (POINTER_TYPE_P (TREE_TYPE (inner))
3824 || GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (inner))))
3826 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (inner)))
3828 tree ptr = gfc_conv_descriptor_data_get (inner);
3829 OMP_CLAUSE_DECL (node) = ptr;
3831 else
3832 OMP_CLAUSE_DECL (node) = inner;
3833 OMP_CLAUSE_SIZE (node) = size_zero_node;
3834 goto finalize_map_clause;
3837 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (inner)))
3839 gomp_map_kind map_kind;
3840 tree type = TREE_TYPE (inner);
3841 tree ptr = gfc_conv_descriptor_data_get (inner);
3842 ptr = build_fold_indirect_ref (ptr);
3843 OMP_CLAUSE_DECL (node) = ptr;
3844 int rank = GFC_TYPE_ARRAY_RANK (type);
3845 OMP_CLAUSE_SIZE (node)
3846 = gfc_full_array_size (block, inner, rank);
3847 tree elemsz
3848 = TYPE_SIZE_UNIT (gfc_get_element_type (type));
3849 map_kind = OMP_CLAUSE_MAP_KIND (node);
3850 if (GOMP_MAP_COPY_TO_P (map_kind)
3851 || map_kind == GOMP_MAP_ALLOC)
3852 map_kind = ((GOMP_MAP_ALWAYS_P (map_kind)
3853 || gfc_expr_attr (n->expr).pointer)
3854 ? GOMP_MAP_ALWAYS_TO : GOMP_MAP_TO);
3855 else if (n->u.map.op == OMP_MAP_RELEASE
3856 || n->u.map.op == OMP_MAP_DELETE)
3858 else if (op == EXEC_OMP_TARGET_EXIT_DATA
3859 || op == EXEC_OACC_EXIT_DATA)
3860 map_kind = GOMP_MAP_RELEASE;
3861 else
3862 map_kind = GOMP_MAP_ALLOC;
3863 if (!openacc
3864 && n->expr->ts.type == BT_CHARACTER
3865 && n->expr->ts.deferred)
3867 gcc_assert (se.string_length);
3868 tree len = fold_convert (size_type_node,
3869 se.string_length);
3870 elemsz = gfc_get_char_type (n->expr->ts.kind);
3871 elemsz = TYPE_SIZE_UNIT (elemsz);
3872 elemsz = fold_build2 (MULT_EXPR, size_type_node,
3873 len, elemsz);
3874 node4 = build_omp_clause (input_location,
3875 OMP_CLAUSE_MAP);
3876 OMP_CLAUSE_SET_MAP_KIND (node4, map_kind);
3877 OMP_CLAUSE_DECL (node4) = se.string_length;
3878 OMP_CLAUSE_SIZE (node4)
3879 = TYPE_SIZE_UNIT (gfc_charlen_type_node);
3881 elemsz = fold_convert (gfc_array_index_type, elemsz);
3882 OMP_CLAUSE_SIZE (node)
3883 = fold_build2 (MULT_EXPR, gfc_array_index_type,
3884 OMP_CLAUSE_SIZE (node), elemsz);
3885 node2 = build_omp_clause (input_location,
3886 OMP_CLAUSE_MAP);
3887 if (map_kind == GOMP_MAP_RELEASE
3888 || map_kind == GOMP_MAP_DELETE)
3890 OMP_CLAUSE_SET_MAP_KIND (node2, map_kind);
3891 OMP_CLAUSE_RELEASE_DESCRIPTOR (node2) = 1;
3893 else
3894 OMP_CLAUSE_SET_MAP_KIND (node2,
3895 GOMP_MAP_TO_PSET);
3896 OMP_CLAUSE_DECL (node2) = inner;
3897 OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
3898 if (!openacc)
3900 gfc_omp_namelist *n2
3901 = clauses->lists[OMP_LIST_MAP];
3903 /* If we don't have a mapping of a smaller part
3904 of the array -- or we can't prove that we do
3905 statically -- set this flag. If there is a
3906 mapping of a smaller part of the array after
3907 all, this will turn into a no-op at
3908 runtime. */
3909 OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (node) = 1;
3911 bool sym_based;
3912 n2 = get_symbol_rooted_namelist (sym_rooted_nl,
3913 n, n2,
3914 &sym_based);
3916 bool drop_mapping = false;
3918 for (; n2 != NULL; n2 = n2->next)
3920 if ((!sym_based && n == n2)
3921 || (sym_based && n == n2->u2.duplicate_of)
3922 || !n2->expr)
3923 continue;
3925 if (!gfc_omp_expr_prefix_same (n->expr,
3926 n2->expr))
3927 continue;
3929 gfc_ref *ref1 = n->expr->ref;
3930 gfc_ref *ref2 = n2->expr->ref;
3932 /* We know ref1 and ref2 overlap. We're
3933 interested in whether ref2 describes a
3934 smaller part of the array than ref1, which
3935 we already know refers to the full
3936 array. */
3938 while (ref1->next && ref2->next)
3940 ref1 = ref1->next;
3941 ref2 = ref2->next;
3944 if (ref2->next
3945 || (ref2->type == REF_ARRAY
3946 && (ref2->u.ar.type == AR_ELEMENT
3947 || (ref2->u.ar.type
3948 == AR_SECTION))))
3950 drop_mapping = true;
3951 break;
3954 if (drop_mapping)
3955 continue;
3957 node3 = build_omp_clause (input_location,
3958 OMP_CLAUSE_MAP);
3959 OMP_CLAUSE_SET_MAP_KIND (node3,
3960 GOMP_MAP_ATTACH_DETACH);
3961 OMP_CLAUSE_DECL (node3)
3962 = gfc_conv_descriptor_data_get (inner);
3963 /* Similar to gfc_trans_omp_array_section (details
3964 there), we add/keep the cast for OpenMP to prevent
3965 that an 'alloc:' gets added for node3 ('desc.data')
3966 as that is part of the whole descriptor (node3).
3967 TODO: Remove once the ME handles this properly. */
3968 if (!openacc)
3969 OMP_CLAUSE_DECL (node3)
3970 = fold_convert (TREE_TYPE (TREE_OPERAND(ptr, 0)),
3971 OMP_CLAUSE_DECL (node3));
3972 else
3973 STRIP_NOPS (OMP_CLAUSE_DECL (node3));
3974 OMP_CLAUSE_SIZE (node3) = size_int (0);
3976 else
3977 OMP_CLAUSE_DECL (node) = inner;
3979 else if (lastref->type == REF_ARRAY)
3981 /* An array element or section. */
3982 bool element = lastref->u.ar.type == AR_ELEMENT;
3983 gomp_map_kind kind = GOMP_MAP_ATTACH_DETACH;
3984 gfc_trans_omp_array_section (block, op, n, inner, element,
3985 !openacc, kind, node, node2,
3986 node3, node4);
3988 else
3989 gcc_unreachable ();
3991 else
3992 sorry ("unhandled expression");
3994 finalize_map_clause:
3996 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
3997 if (node2)
3998 omp_clauses = gfc_trans_add_clause (node2, omp_clauses);
3999 if (node3)
4000 omp_clauses = gfc_trans_add_clause (node3, omp_clauses);
4001 if (node4)
4002 omp_clauses = gfc_trans_add_clause (node4, omp_clauses);
4003 if (node5)
4004 omp_clauses = gfc_trans_add_clause (node5, omp_clauses);
4006 break;
4007 case OMP_LIST_TO:
4008 case OMP_LIST_FROM:
4009 case OMP_LIST_CACHE:
4010 for (; n != NULL; n = n->next)
4012 if (!n->sym->attr.referenced)
4013 continue;
4015 switch (list)
4017 case OMP_LIST_TO:
4018 clause_code = OMP_CLAUSE_TO;
4019 break;
4020 case OMP_LIST_FROM:
4021 clause_code = OMP_CLAUSE_FROM;
4022 break;
4023 case OMP_LIST_CACHE:
4024 clause_code = OMP_CLAUSE__CACHE_;
4025 break;
4026 default:
4027 gcc_unreachable ();
4029 tree node = build_omp_clause (input_location, clause_code);
4030 if (n->expr == NULL
4031 || (n->expr->ref->type == REF_ARRAY
4032 && n->expr->ref->u.ar.type == AR_FULL
4033 && n->expr->ref->next == NULL))
4035 tree decl = gfc_trans_omp_variable (n->sym, false);
4036 if (gfc_omp_privatize_by_reference (decl))
4038 if (gfc_omp_is_allocatable_or_ptr (decl))
4039 decl = build_fold_indirect_ref (decl);
4040 decl = build_fold_indirect_ref (decl);
4042 else if (DECL_P (decl))
4043 TREE_ADDRESSABLE (decl) = 1;
4044 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
4046 tree type = TREE_TYPE (decl);
4047 tree ptr = gfc_conv_descriptor_data_get (decl);
4048 gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
4049 ptr = build_fold_indirect_ref (ptr);
4050 OMP_CLAUSE_DECL (node) = ptr;
4051 OMP_CLAUSE_SIZE (node)
4052 = gfc_full_array_size (block, decl,
4053 GFC_TYPE_ARRAY_RANK (type));
4054 tree elemsz
4055 = TYPE_SIZE_UNIT (gfc_get_element_type (type));
4056 elemsz = fold_convert (gfc_array_index_type, elemsz);
4057 OMP_CLAUSE_SIZE (node)
4058 = fold_build2 (MULT_EXPR, gfc_array_index_type,
4059 OMP_CLAUSE_SIZE (node), elemsz);
4061 else
4063 OMP_CLAUSE_DECL (node) = decl;
4064 if (gfc_omp_is_allocatable_or_ptr (decl))
4065 OMP_CLAUSE_SIZE (node)
4066 = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)));
4069 else
4071 tree ptr;
4072 gfc_init_se (&se, NULL);
4073 if (n->expr->rank == 0)
4075 gfc_conv_expr_reference (&se, n->expr);
4076 ptr = se.expr;
4077 gfc_add_block_to_block (block, &se.pre);
4078 OMP_CLAUSE_SIZE (node)
4079 = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ptr)));
4081 else
4083 gfc_conv_expr_descriptor (&se, n->expr);
4084 ptr = gfc_conv_array_data (se.expr);
4085 tree type = TREE_TYPE (se.expr);
4086 gfc_add_block_to_block (block, &se.pre);
4087 OMP_CLAUSE_SIZE (node)
4088 = gfc_full_array_size (block, se.expr,
4089 GFC_TYPE_ARRAY_RANK (type));
4090 tree elemsz
4091 = TYPE_SIZE_UNIT (gfc_get_element_type (type));
4092 elemsz = fold_convert (gfc_array_index_type, elemsz);
4093 OMP_CLAUSE_SIZE (node)
4094 = fold_build2 (MULT_EXPR, gfc_array_index_type,
4095 OMP_CLAUSE_SIZE (node), elemsz);
4097 gfc_add_block_to_block (block, &se.post);
4098 gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
4099 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
4101 if (n->u.present_modifier)
4102 OMP_CLAUSE_MOTION_PRESENT (node) = 1;
4103 if (list == OMP_LIST_CACHE && n->u.map.readonly)
4104 OMP_CLAUSE__CACHE__READONLY (node) = 1;
4105 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
4107 break;
4108 case OMP_LIST_USES_ALLOCATORS:
4109 /* Ignore pre-defined allocators as no special treatment is needed. */
4110 for (; n != NULL; n = n->next)
4111 if (n->sym->attr.flavor == FL_VARIABLE)
4112 break;
4113 if (n != NULL)
4114 sorry_at (input_location, "%<uses_allocators%> clause with traits "
4115 "and memory spaces");
4116 break;
4117 default:
4118 break;
4122 /* Free hashmap if we built it. */
4123 if (sym_rooted_nl)
4125 typedef hash_map<gfc_symbol *, gfc_omp_namelist *>::iterator hti;
4126 for (hti it = sym_rooted_nl->begin (); it != sym_rooted_nl->end (); ++it)
4128 gfc_omp_namelist *&nl = (*it).second;
4129 while (nl)
4131 gfc_omp_namelist *next = nl->next;
4132 free (nl);
4133 nl = next;
4136 delete sym_rooted_nl;
4139 if (clauses->if_expr)
4141 tree if_var;
4143 gfc_init_se (&se, NULL);
4144 gfc_conv_expr (&se, clauses->if_expr);
4145 gfc_add_block_to_block (block, &se.pre);
4146 if_var = gfc_evaluate_now (se.expr, block);
4147 gfc_add_block_to_block (block, &se.post);
4149 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF);
4150 OMP_CLAUSE_IF_MODIFIER (c) = ERROR_MARK;
4151 OMP_CLAUSE_IF_EXPR (c) = if_var;
4152 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4155 for (ifc = 0; ifc < OMP_IF_LAST; ifc++)
4156 if (clauses->if_exprs[ifc])
4158 tree if_var;
4160 gfc_init_se (&se, NULL);
4161 gfc_conv_expr (&se, clauses->if_exprs[ifc]);
4162 gfc_add_block_to_block (block, &se.pre);
4163 if_var = gfc_evaluate_now (se.expr, block);
4164 gfc_add_block_to_block (block, &se.post);
4166 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF);
4167 switch (ifc)
4169 case OMP_IF_CANCEL:
4170 OMP_CLAUSE_IF_MODIFIER (c) = VOID_CST;
4171 break;
4172 case OMP_IF_PARALLEL:
4173 OMP_CLAUSE_IF_MODIFIER (c) = OMP_PARALLEL;
4174 break;
4175 case OMP_IF_SIMD:
4176 OMP_CLAUSE_IF_MODIFIER (c) = OMP_SIMD;
4177 break;
4178 case OMP_IF_TASK:
4179 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TASK;
4180 break;
4181 case OMP_IF_TASKLOOP:
4182 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TASKLOOP;
4183 break;
4184 case OMP_IF_TARGET:
4185 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET;
4186 break;
4187 case OMP_IF_TARGET_DATA:
4188 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_DATA;
4189 break;
4190 case OMP_IF_TARGET_UPDATE:
4191 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_UPDATE;
4192 break;
4193 case OMP_IF_TARGET_ENTER_DATA:
4194 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_ENTER_DATA;
4195 break;
4196 case OMP_IF_TARGET_EXIT_DATA:
4197 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_EXIT_DATA;
4198 break;
4199 default:
4200 gcc_unreachable ();
4202 OMP_CLAUSE_IF_EXPR (c) = if_var;
4203 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4206 if (clauses->self_expr)
4208 tree self_var;
4210 gfc_init_se (&se, NULL);
4211 gfc_conv_expr (&se, clauses->self_expr);
4212 gfc_add_block_to_block (block, &se.pre);
4213 self_var = gfc_evaluate_now (se.expr, block);
4214 gfc_add_block_to_block (block, &se.post);
4216 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SELF);
4217 OMP_CLAUSE_SELF_EXPR (c) = self_var;
4218 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4221 if (clauses->final_expr)
4223 tree final_var;
4225 gfc_init_se (&se, NULL);
4226 gfc_conv_expr (&se, clauses->final_expr);
4227 gfc_add_block_to_block (block, &se.pre);
4228 final_var = gfc_evaluate_now (se.expr, block);
4229 gfc_add_block_to_block (block, &se.post);
4231 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FINAL);
4232 OMP_CLAUSE_FINAL_EXPR (c) = final_var;
4233 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4236 if (clauses->num_threads)
4238 tree num_threads;
4240 gfc_init_se (&se, NULL);
4241 gfc_conv_expr (&se, clauses->num_threads);
4242 gfc_add_block_to_block (block, &se.pre);
4243 num_threads = gfc_evaluate_now (se.expr, block);
4244 gfc_add_block_to_block (block, &se.post);
4246 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_THREADS);
4247 OMP_CLAUSE_NUM_THREADS_EXPR (c) = num_threads;
4248 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4251 chunk_size = NULL_TREE;
4252 if (clauses->chunk_size)
4254 gfc_init_se (&se, NULL);
4255 gfc_conv_expr (&se, clauses->chunk_size);
4256 gfc_add_block_to_block (block, &se.pre);
4257 chunk_size = gfc_evaluate_now (se.expr, block);
4258 gfc_add_block_to_block (block, &se.post);
4261 if (clauses->sched_kind != OMP_SCHED_NONE)
4263 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SCHEDULE);
4264 OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
4265 switch (clauses->sched_kind)
4267 case OMP_SCHED_STATIC:
4268 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
4269 break;
4270 case OMP_SCHED_DYNAMIC:
4271 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
4272 break;
4273 case OMP_SCHED_GUIDED:
4274 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
4275 break;
4276 case OMP_SCHED_RUNTIME:
4277 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
4278 break;
4279 case OMP_SCHED_AUTO:
4280 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
4281 break;
4282 default:
4283 gcc_unreachable ();
4285 if (clauses->sched_monotonic)
4286 OMP_CLAUSE_SCHEDULE_KIND (c)
4287 = (omp_clause_schedule_kind) (OMP_CLAUSE_SCHEDULE_KIND (c)
4288 | OMP_CLAUSE_SCHEDULE_MONOTONIC);
4289 else if (clauses->sched_nonmonotonic)
4290 OMP_CLAUSE_SCHEDULE_KIND (c)
4291 = (omp_clause_schedule_kind) (OMP_CLAUSE_SCHEDULE_KIND (c)
4292 | OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
4293 if (clauses->sched_simd)
4294 OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
4295 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4298 if (clauses->default_sharing != OMP_DEFAULT_UNKNOWN)
4300 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEFAULT);
4301 switch (clauses->default_sharing)
4303 case OMP_DEFAULT_NONE:
4304 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_NONE;
4305 break;
4306 case OMP_DEFAULT_SHARED:
4307 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_SHARED;
4308 break;
4309 case OMP_DEFAULT_PRIVATE:
4310 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRIVATE;
4311 break;
4312 case OMP_DEFAULT_FIRSTPRIVATE:
4313 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
4314 break;
4315 case OMP_DEFAULT_PRESENT:
4316 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRESENT;
4317 break;
4318 default:
4319 gcc_unreachable ();
4321 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4324 if (clauses->nowait)
4326 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOWAIT);
4327 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4330 if (clauses->full)
4332 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FULL);
4333 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4336 if (clauses->partial)
4338 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PARTIAL);
4339 OMP_CLAUSE_PARTIAL_EXPR (c)
4340 = (clauses->partial > 0
4341 ? build_int_cst (integer_type_node, clauses->partial)
4342 : NULL_TREE);
4343 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4346 if (clauses->sizes_list)
4348 tree list = NULL_TREE;
4349 for (gfc_expr_list *el = clauses->sizes_list; el; el = el->next)
4350 list = tree_cons (NULL_TREE, gfc_convert_expr_to_tree (block, el->expr),
4351 list);
4353 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIZES);
4354 OMP_CLAUSE_SIZES_LIST (c) = nreverse (list);
4355 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4358 if (clauses->ordered)
4360 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ORDERED);
4361 OMP_CLAUSE_ORDERED_EXPR (c)
4362 = clauses->orderedc ? build_int_cst (integer_type_node,
4363 clauses->orderedc) : NULL_TREE;
4364 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4367 if (clauses->order_concurrent)
4369 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ORDER);
4370 OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = clauses->order_unconstrained;
4371 OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = clauses->order_reproducible;
4372 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4375 if (clauses->untied)
4377 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_UNTIED);
4378 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4381 if (clauses->mergeable)
4383 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_MERGEABLE);
4384 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4387 if (clauses->collapse)
4389 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_COLLAPSE);
4390 OMP_CLAUSE_COLLAPSE_EXPR (c)
4391 = build_int_cst (integer_type_node, clauses->collapse);
4392 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4395 if (clauses->inbranch)
4397 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_INBRANCH);
4398 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4401 if (clauses->notinbranch)
4403 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOTINBRANCH);
4404 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4407 switch (clauses->cancel)
4409 case OMP_CANCEL_UNKNOWN:
4410 break;
4411 case OMP_CANCEL_PARALLEL:
4412 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PARALLEL);
4413 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4414 break;
4415 case OMP_CANCEL_SECTIONS:
4416 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SECTIONS);
4417 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4418 break;
4419 case OMP_CANCEL_DO:
4420 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FOR);
4421 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4422 break;
4423 case OMP_CANCEL_TASKGROUP:
4424 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_TASKGROUP);
4425 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4426 break;
4429 if (clauses->proc_bind != OMP_PROC_BIND_UNKNOWN)
4431 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PROC_BIND);
4432 switch (clauses->proc_bind)
4434 case OMP_PROC_BIND_PRIMARY:
4435 OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_PRIMARY;
4436 break;
4437 case OMP_PROC_BIND_MASTER:
4438 OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_MASTER;
4439 break;
4440 case OMP_PROC_BIND_SPREAD:
4441 OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_SPREAD;
4442 break;
4443 case OMP_PROC_BIND_CLOSE:
4444 OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_CLOSE;
4445 break;
4446 default:
4447 gcc_unreachable ();
4449 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4452 if (clauses->safelen_expr)
4454 tree safelen_var;
4456 gfc_init_se (&se, NULL);
4457 gfc_conv_expr (&se, clauses->safelen_expr);
4458 gfc_add_block_to_block (block, &se.pre);
4459 safelen_var = gfc_evaluate_now (se.expr, block);
4460 gfc_add_block_to_block (block, &se.post);
4462 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SAFELEN);
4463 OMP_CLAUSE_SAFELEN_EXPR (c) = safelen_var;
4464 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4467 if (clauses->simdlen_expr)
4469 if (declare_simd)
4471 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMDLEN);
4472 OMP_CLAUSE_SIMDLEN_EXPR (c)
4473 = gfc_conv_constant_to_tree (clauses->simdlen_expr);
4474 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4476 else
4478 tree simdlen_var;
4480 gfc_init_se (&se, NULL);
4481 gfc_conv_expr (&se, clauses->simdlen_expr);
4482 gfc_add_block_to_block (block, &se.pre);
4483 simdlen_var = gfc_evaluate_now (se.expr, block);
4484 gfc_add_block_to_block (block, &se.post);
4486 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMDLEN);
4487 OMP_CLAUSE_SIMDLEN_EXPR (c) = simdlen_var;
4488 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4492 if (clauses->num_teams_upper)
4494 tree num_teams_lower = NULL_TREE, num_teams_upper;
4496 gfc_init_se (&se, NULL);
4497 gfc_conv_expr (&se, clauses->num_teams_upper);
4498 gfc_add_block_to_block (block, &se.pre);
4499 num_teams_upper = gfc_evaluate_now (se.expr, block);
4500 gfc_add_block_to_block (block, &se.post);
4502 if (clauses->num_teams_lower)
4504 gfc_init_se (&se, NULL);
4505 gfc_conv_expr (&se, clauses->num_teams_lower);
4506 gfc_add_block_to_block (block, &se.pre);
4507 num_teams_lower = gfc_evaluate_now (se.expr, block);
4508 gfc_add_block_to_block (block, &se.post);
4510 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_TEAMS);
4511 OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = num_teams_lower;
4512 OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = num_teams_upper;
4513 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4516 if (clauses->device)
4518 tree device;
4520 gfc_init_se (&se, NULL);
4521 gfc_conv_expr (&se, clauses->device);
4522 gfc_add_block_to_block (block, &se.pre);
4523 device = gfc_evaluate_now (se.expr, block);
4524 gfc_add_block_to_block (block, &se.post);
4526 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEVICE);
4527 OMP_CLAUSE_DEVICE_ID (c) = device;
4529 if (clauses->ancestor)
4530 OMP_CLAUSE_DEVICE_ANCESTOR (c) = 1;
4532 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4535 if (clauses->thread_limit)
4537 tree thread_limit;
4539 gfc_init_se (&se, NULL);
4540 gfc_conv_expr (&se, clauses->thread_limit);
4541 gfc_add_block_to_block (block, &se.pre);
4542 thread_limit = gfc_evaluate_now (se.expr, block);
4543 gfc_add_block_to_block (block, &se.post);
4545 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_THREAD_LIMIT);
4546 OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = thread_limit;
4547 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4550 chunk_size = NULL_TREE;
4551 if (clauses->dist_chunk_size)
4553 gfc_init_se (&se, NULL);
4554 gfc_conv_expr (&se, clauses->dist_chunk_size);
4555 gfc_add_block_to_block (block, &se.pre);
4556 chunk_size = gfc_evaluate_now (se.expr, block);
4557 gfc_add_block_to_block (block, &se.post);
4560 if (clauses->dist_sched_kind != OMP_SCHED_NONE)
4562 c = build_omp_clause (gfc_get_location (&where),
4563 OMP_CLAUSE_DIST_SCHEDULE);
4564 OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
4565 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4568 if (clauses->grainsize)
4570 tree grainsize;
4572 gfc_init_se (&se, NULL);
4573 gfc_conv_expr (&se, clauses->grainsize);
4574 gfc_add_block_to_block (block, &se.pre);
4575 grainsize = gfc_evaluate_now (se.expr, block);
4576 gfc_add_block_to_block (block, &se.post);
4578 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_GRAINSIZE);
4579 OMP_CLAUSE_GRAINSIZE_EXPR (c) = grainsize;
4580 if (clauses->grainsize_strict)
4581 OMP_CLAUSE_GRAINSIZE_STRICT (c) = 1;
4582 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4585 if (clauses->num_tasks)
4587 tree num_tasks;
4589 gfc_init_se (&se, NULL);
4590 gfc_conv_expr (&se, clauses->num_tasks);
4591 gfc_add_block_to_block (block, &se.pre);
4592 num_tasks = gfc_evaluate_now (se.expr, block);
4593 gfc_add_block_to_block (block, &se.post);
4595 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_TASKS);
4596 OMP_CLAUSE_NUM_TASKS_EXPR (c) = num_tasks;
4597 if (clauses->num_tasks_strict)
4598 OMP_CLAUSE_NUM_TASKS_STRICT (c) = 1;
4599 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4602 if (clauses->priority)
4604 tree priority;
4606 gfc_init_se (&se, NULL);
4607 gfc_conv_expr (&se, clauses->priority);
4608 gfc_add_block_to_block (block, &se.pre);
4609 priority = gfc_evaluate_now (se.expr, block);
4610 gfc_add_block_to_block (block, &se.post);
4612 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PRIORITY);
4613 OMP_CLAUSE_PRIORITY_EXPR (c) = priority;
4614 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4617 if (clauses->detach)
4619 tree detach;
4621 gfc_init_se (&se, NULL);
4622 gfc_conv_expr (&se, clauses->detach);
4623 gfc_add_block_to_block (block, &se.pre);
4624 detach = se.expr;
4625 gfc_add_block_to_block (block, &se.post);
4627 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DETACH);
4628 TREE_ADDRESSABLE (detach) = 1;
4629 OMP_CLAUSE_DECL (c) = detach;
4630 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4633 if (clauses->filter)
4635 tree filter;
4637 gfc_init_se (&se, NULL);
4638 gfc_conv_expr (&se, clauses->filter);
4639 gfc_add_block_to_block (block, &se.pre);
4640 filter = gfc_evaluate_now (se.expr, block);
4641 gfc_add_block_to_block (block, &se.post);
4643 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FILTER);
4644 OMP_CLAUSE_FILTER_EXPR (c) = filter;
4645 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4648 if (clauses->hint)
4650 tree hint;
4652 gfc_init_se (&se, NULL);
4653 gfc_conv_expr (&se, clauses->hint);
4654 gfc_add_block_to_block (block, &se.pre);
4655 hint = gfc_evaluate_now (se.expr, block);
4656 gfc_add_block_to_block (block, &se.post);
4658 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_HINT);
4659 OMP_CLAUSE_HINT_EXPR (c) = hint;
4660 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4663 if (clauses->simd)
4665 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMD);
4666 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4668 if (clauses->threads)
4670 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_THREADS);
4671 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4673 if (clauses->nogroup)
4675 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOGROUP);
4676 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4679 for (int i = 0; i < OMP_DEFAULTMAP_CAT_NUM; i++)
4681 if (clauses->defaultmap[i] == OMP_DEFAULTMAP_UNSET)
4682 continue;
4683 enum omp_clause_defaultmap_kind behavior, category;
4684 switch ((gfc_omp_defaultmap_category) i)
4686 case OMP_DEFAULTMAP_CAT_UNCATEGORIZED:
4687 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
4688 break;
4689 case OMP_DEFAULTMAP_CAT_ALL:
4690 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL;
4691 break;
4692 case OMP_DEFAULTMAP_CAT_SCALAR:
4693 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR;
4694 break;
4695 case OMP_DEFAULTMAP_CAT_AGGREGATE:
4696 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE;
4697 break;
4698 case OMP_DEFAULTMAP_CAT_ALLOCATABLE:
4699 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALLOCATABLE;
4700 break;
4701 case OMP_DEFAULTMAP_CAT_POINTER:
4702 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER;
4703 break;
4704 default: gcc_unreachable ();
4706 switch (clauses->defaultmap[i])
4708 case OMP_DEFAULTMAP_ALLOC:
4709 behavior = OMP_CLAUSE_DEFAULTMAP_ALLOC;
4710 break;
4711 case OMP_DEFAULTMAP_TO: behavior = OMP_CLAUSE_DEFAULTMAP_TO; break;
4712 case OMP_DEFAULTMAP_FROM: behavior = OMP_CLAUSE_DEFAULTMAP_FROM; break;
4713 case OMP_DEFAULTMAP_TOFROM:
4714 behavior = OMP_CLAUSE_DEFAULTMAP_TOFROM;
4715 break;
4716 case OMP_DEFAULTMAP_FIRSTPRIVATE:
4717 behavior = OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
4718 break;
4719 case OMP_DEFAULTMAP_PRESENT:
4720 behavior = OMP_CLAUSE_DEFAULTMAP_PRESENT;
4721 break;
4722 case OMP_DEFAULTMAP_NONE: behavior = OMP_CLAUSE_DEFAULTMAP_NONE; break;
4723 case OMP_DEFAULTMAP_DEFAULT:
4724 behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
4725 break;
4726 default: gcc_unreachable ();
4728 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEFAULTMAP);
4729 OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, behavior, category);
4730 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4733 if (clauses->doacross_source)
4735 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DOACROSS);
4736 OMP_CLAUSE_DOACROSS_KIND (c) = OMP_CLAUSE_DOACROSS_SOURCE;
4737 OMP_CLAUSE_DOACROSS_DEPEND (c) = clauses->depend_source;
4738 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4741 if (clauses->async)
4743 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ASYNC);
4744 if (clauses->async_expr)
4745 OMP_CLAUSE_ASYNC_EXPR (c)
4746 = gfc_convert_expr_to_tree (block, clauses->async_expr);
4747 else
4748 OMP_CLAUSE_ASYNC_EXPR (c) = NULL;
4749 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4751 if (clauses->seq)
4753 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SEQ);
4754 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4756 if (clauses->par_auto)
4758 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_AUTO);
4759 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4761 if (clauses->if_present)
4763 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF_PRESENT);
4764 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4766 if (clauses->finalize)
4768 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FINALIZE);
4769 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4771 if (clauses->independent)
4773 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_INDEPENDENT);
4774 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4776 if (clauses->wait_list)
4778 gfc_expr_list *el;
4780 for (el = clauses->wait_list; el; el = el->next)
4782 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_WAIT);
4783 OMP_CLAUSE_DECL (c) = gfc_convert_expr_to_tree (block, el->expr);
4784 OMP_CLAUSE_CHAIN (c) = omp_clauses;
4785 omp_clauses = c;
4788 if (clauses->num_gangs_expr)
4790 tree num_gangs_var
4791 = gfc_convert_expr_to_tree (block, clauses->num_gangs_expr);
4792 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_GANGS);
4793 OMP_CLAUSE_NUM_GANGS_EXPR (c) = num_gangs_var;
4794 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4796 if (clauses->num_workers_expr)
4798 tree num_workers_var
4799 = gfc_convert_expr_to_tree (block, clauses->num_workers_expr);
4800 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_WORKERS);
4801 OMP_CLAUSE_NUM_WORKERS_EXPR (c) = num_workers_var;
4802 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4804 if (clauses->vector_length_expr)
4806 tree vector_length_var
4807 = gfc_convert_expr_to_tree (block, clauses->vector_length_expr);
4808 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_VECTOR_LENGTH);
4809 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c) = vector_length_var;
4810 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4812 if (clauses->tile_list)
4814 tree list = NULL_TREE;
4815 for (gfc_expr_list *el = clauses->tile_list; el; el = el->next)
4816 list = tree_cons (NULL_TREE, gfc_convert_expr_to_tree (block, el->expr),
4817 list);
4819 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_TILE);
4820 OMP_CLAUSE_TILE_LIST (c) = nreverse (list);
4821 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4823 if (clauses->vector)
4825 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_VECTOR);
4826 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4828 if (clauses->vector_expr)
4830 tree vector_var
4831 = gfc_convert_expr_to_tree (block, clauses->vector_expr);
4832 OMP_CLAUSE_VECTOR_EXPR (c) = vector_var;
4834 /* TODO: We're not capturing location information for individual
4835 clauses. However, if we have an expression attached to the
4836 clause, that one provides better location information. */
4837 OMP_CLAUSE_LOCATION (c)
4838 = gfc_get_location (&clauses->vector_expr->where);
4841 if (clauses->worker)
4843 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_WORKER);
4844 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4846 if (clauses->worker_expr)
4848 tree worker_var
4849 = gfc_convert_expr_to_tree (block, clauses->worker_expr);
4850 OMP_CLAUSE_WORKER_EXPR (c) = worker_var;
4852 /* TODO: We're not capturing location information for individual
4853 clauses. However, if we have an expression attached to the
4854 clause, that one provides better location information. */
4855 OMP_CLAUSE_LOCATION (c)
4856 = gfc_get_location (&clauses->worker_expr->where);
4859 if (clauses->gang)
4861 tree arg;
4862 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_GANG);
4863 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4865 if (clauses->gang_num_expr)
4867 arg = gfc_convert_expr_to_tree (block, clauses->gang_num_expr);
4868 OMP_CLAUSE_GANG_EXPR (c) = arg;
4870 /* TODO: We're not capturing location information for individual
4871 clauses. However, if we have an expression attached to the
4872 clause, that one provides better location information. */
4873 OMP_CLAUSE_LOCATION (c)
4874 = gfc_get_location (&clauses->gang_num_expr->where);
4877 if (clauses->gang_static)
4879 arg = clauses->gang_static_expr
4880 ? gfc_convert_expr_to_tree (block, clauses->gang_static_expr)
4881 : integer_minus_one_node;
4882 OMP_CLAUSE_GANG_STATIC_EXPR (c) = arg;
4885 if (clauses->bind != OMP_BIND_UNSET)
4887 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_BIND);
4888 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4889 switch (clauses->bind)
4891 case OMP_BIND_TEAMS:
4892 OMP_CLAUSE_BIND_KIND (c) = OMP_CLAUSE_BIND_TEAMS;
4893 break;
4894 case OMP_BIND_PARALLEL:
4895 OMP_CLAUSE_BIND_KIND (c) = OMP_CLAUSE_BIND_PARALLEL;
4896 break;
4897 case OMP_BIND_THREAD:
4898 OMP_CLAUSE_BIND_KIND (c) = OMP_CLAUSE_BIND_THREAD;
4899 break;
4900 default:
4901 gcc_unreachable ();
4904 /* OpenACC 'nohost' clauses cannot appear here. */
4905 gcc_checking_assert (!clauses->nohost);
4907 return nreverse (omp_clauses);
4910 /* Like gfc_trans_code, but force creation of a BIND_EXPR around it. */
4912 static tree
4913 gfc_trans_omp_code (gfc_code *code, bool force_empty)
4915 tree stmt;
4917 pushlevel ();
4918 stmt = gfc_trans_code (code);
4919 if (TREE_CODE (stmt) != BIND_EXPR)
4921 if (!IS_EMPTY_STMT (stmt) || force_empty)
4923 tree block = poplevel (1, 0);
4924 stmt = build3_v (BIND_EXPR, NULL, stmt, block);
4926 else
4927 poplevel (0, 0);
4929 else
4930 poplevel (0, 0);
4931 return stmt;
4934 /* Translate OpenACC 'parallel', 'kernels', 'serial', 'data', 'host_data'
4935 construct. */
4937 static tree
4938 gfc_trans_oacc_construct (gfc_code *code)
4940 stmtblock_t block;
4941 tree stmt, oacc_clauses;
4942 enum tree_code construct_code;
4944 switch (code->op)
4946 case EXEC_OACC_PARALLEL:
4947 construct_code = OACC_PARALLEL;
4948 break;
4949 case EXEC_OACC_KERNELS:
4950 construct_code = OACC_KERNELS;
4951 break;
4952 case EXEC_OACC_SERIAL:
4953 construct_code = OACC_SERIAL;
4954 break;
4955 case EXEC_OACC_DATA:
4956 construct_code = OACC_DATA;
4957 break;
4958 case EXEC_OACC_HOST_DATA:
4959 construct_code = OACC_HOST_DATA;
4960 break;
4961 default:
4962 gcc_unreachable ();
4965 gfc_start_block (&block);
4966 oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
4967 code->loc, false, true);
4968 pushlevel ();
4969 stmt = gfc_trans_omp_code (code->block->next, true);
4970 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
4971 stmt = build2_loc (gfc_get_location (&code->loc), construct_code,
4972 void_type_node, stmt, oacc_clauses);
4973 gfc_add_expr_to_block (&block, stmt);
4974 return gfc_finish_block (&block);
4977 /* update, enter_data, exit_data, cache. */
4978 static tree
4979 gfc_trans_oacc_executable_directive (gfc_code *code)
4981 stmtblock_t block;
4982 tree stmt, oacc_clauses;
4983 enum tree_code construct_code;
4985 switch (code->op)
4987 case EXEC_OACC_UPDATE:
4988 construct_code = OACC_UPDATE;
4989 break;
4990 case EXEC_OACC_ENTER_DATA:
4991 construct_code = OACC_ENTER_DATA;
4992 break;
4993 case EXEC_OACC_EXIT_DATA:
4994 construct_code = OACC_EXIT_DATA;
4995 break;
4996 case EXEC_OACC_CACHE:
4997 construct_code = OACC_CACHE;
4998 break;
4999 default:
5000 gcc_unreachable ();
5003 gfc_start_block (&block);
5004 oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
5005 code->loc, false, true, code->op);
5006 stmt = build1_loc (input_location, construct_code, void_type_node,
5007 oacc_clauses);
5008 gfc_add_expr_to_block (&block, stmt);
5009 return gfc_finish_block (&block);
5012 static tree
5013 gfc_trans_oacc_wait_directive (gfc_code *code)
5015 stmtblock_t block;
5016 tree stmt, t;
5017 vec<tree, va_gc> *args;
5018 int nparms = 0;
5019 gfc_expr_list *el;
5020 gfc_omp_clauses *clauses = code->ext.omp_clauses;
5021 location_t loc = input_location;
5023 for (el = clauses->wait_list; el; el = el->next)
5024 nparms++;
5026 vec_alloc (args, nparms + 2);
5027 stmt = builtin_decl_explicit (BUILT_IN_GOACC_WAIT);
5029 gfc_start_block (&block);
5031 if (clauses->async_expr)
5032 t = gfc_convert_expr_to_tree (&block, clauses->async_expr);
5033 else
5034 t = build_int_cst (integer_type_node, -2);
5036 args->quick_push (t);
5037 args->quick_push (build_int_cst (integer_type_node, nparms));
5039 for (el = clauses->wait_list; el; el = el->next)
5040 args->quick_push (gfc_convert_expr_to_tree (&block, el->expr));
5042 stmt = build_call_expr_loc_vec (loc, stmt, args);
5043 gfc_add_expr_to_block (&block, stmt);
5045 vec_free (args);
5047 return gfc_finish_block (&block);
5050 static tree gfc_trans_omp_sections (gfc_code *, gfc_omp_clauses *);
5051 static tree gfc_trans_omp_workshare (gfc_code *, gfc_omp_clauses *);
5053 static tree
5054 gfc_trans_omp_allocators (gfc_code *code)
5056 static bool warned = false;
5057 gfc_omp_namelist *omp_allocate
5058 = code->ext.omp_clauses->lists[OMP_LIST_ALLOCATE];
5059 if (!flag_openmp_allocators && !warned)
5061 omp_allocate = NULL;
5062 gfc_error ("%<!$OMP %s%> at %L requires %<-fopenmp-allocators%>",
5063 code->op == EXEC_OMP_ALLOCATE ? "ALLOCATE" : "ALLOCATORS",
5064 &code->loc);
5065 warning (0, "All files that might deallocate such a variable must be "
5066 "compiled with %<-fopenmp-allocators%>");
5067 inform (UNKNOWN_LOCATION,
5068 "This includes explicit DEALLOCATE, reallocation on intrinsic "
5069 "assignment, INTENT(OUT) for allocatable dummy arguments, and "
5070 "reallocation of allocatable components allocated with an "
5071 "OpenMP allocator");
5072 warned = true;
5074 return gfc_trans_allocate (code->block->next, omp_allocate);
5077 static tree
5078 gfc_trans_omp_assume (gfc_code *code)
5080 stmtblock_t block;
5081 gfc_init_block (&block);
5082 gfc_omp_assumptions *assume = code->ext.omp_clauses->assume;
5083 if (assume)
5084 for (gfc_expr_list *el = assume->holds; el; el = el->next)
5086 location_t loc = gfc_get_location (&el->expr->where);
5087 gfc_se se;
5088 gfc_init_se (&se, NULL);
5089 gfc_conv_expr (&se, el->expr);
5090 tree t;
5091 if (se.pre.head == NULL_TREE && se.post.head == NULL_TREE)
5092 t = se.expr;
5093 else
5095 tree var = create_tmp_var_raw (boolean_type_node);
5096 DECL_CONTEXT (var) = current_function_decl;
5097 stmtblock_t block2;
5098 gfc_init_block (&block2);
5099 gfc_add_block_to_block (&block2, &se.pre);
5100 gfc_add_modify_loc (loc, &block2, var,
5101 fold_convert_loc (loc, boolean_type_node,
5102 se.expr));
5103 gfc_add_block_to_block (&block2, &se.post);
5104 t = gfc_finish_block (&block2);
5105 t = build4 (TARGET_EXPR, boolean_type_node, var, t, NULL, NULL);
5107 t = build_call_expr_internal_loc (loc, IFN_ASSUME,
5108 void_type_node, 1, t);
5109 gfc_add_expr_to_block (&block, t);
5111 gfc_add_expr_to_block (&block, gfc_trans_omp_code (code->block->next, true));
5112 return gfc_finish_block (&block);
5115 static tree
5116 gfc_trans_omp_atomic (gfc_code *code)
5118 gfc_code *atomic_code = code->block;
5119 gfc_se lse;
5120 gfc_se rse;
5121 gfc_se vse;
5122 gfc_expr *expr1, *expr2, *e, *capture_expr1 = NULL, *capture_expr2 = NULL;
5123 gfc_symbol *var;
5124 stmtblock_t block;
5125 tree lhsaddr, type, rhs, x, compare = NULL_TREE, comp_tgt = NULL_TREE;
5126 enum tree_code op = ERROR_MARK;
5127 enum tree_code aop = OMP_ATOMIC;
5128 bool var_on_left = false, else_branch = false;
5129 enum omp_memory_order mo, fail_mo;
5130 switch (atomic_code->ext.omp_clauses->memorder)
5132 case OMP_MEMORDER_UNSET: mo = OMP_MEMORY_ORDER_UNSPECIFIED; break;
5133 case OMP_MEMORDER_ACQ_REL: mo = OMP_MEMORY_ORDER_ACQ_REL; break;
5134 case OMP_MEMORDER_ACQUIRE: mo = OMP_MEMORY_ORDER_ACQUIRE; break;
5135 case OMP_MEMORDER_RELAXED: mo = OMP_MEMORY_ORDER_RELAXED; break;
5136 case OMP_MEMORDER_RELEASE: mo = OMP_MEMORY_ORDER_RELEASE; break;
5137 case OMP_MEMORDER_SEQ_CST: mo = OMP_MEMORY_ORDER_SEQ_CST; break;
5138 default: gcc_unreachable ();
5140 switch (atomic_code->ext.omp_clauses->fail)
5142 case OMP_MEMORDER_UNSET: fail_mo = OMP_FAIL_MEMORY_ORDER_UNSPECIFIED; break;
5143 case OMP_MEMORDER_ACQUIRE: fail_mo = OMP_FAIL_MEMORY_ORDER_ACQUIRE; break;
5144 case OMP_MEMORDER_RELAXED: fail_mo = OMP_FAIL_MEMORY_ORDER_RELAXED; break;
5145 case OMP_MEMORDER_SEQ_CST: fail_mo = OMP_FAIL_MEMORY_ORDER_SEQ_CST; break;
5146 default: gcc_unreachable ();
5148 mo = (omp_memory_order) (mo | fail_mo);
5150 code = code->block->next;
5151 if (atomic_code->ext.omp_clauses->compare)
5153 gfc_expr *comp_expr;
5154 if (code->op == EXEC_IF)
5156 comp_expr = code->block->expr1;
5157 gcc_assert (code->block->next->op == EXEC_ASSIGN);
5158 expr1 = code->block->next->expr1;
5159 expr2 = code->block->next->expr2;
5160 if (code->block->block)
5162 gcc_assert (atomic_code->ext.omp_clauses->capture
5163 && code->block->block->next->op == EXEC_ASSIGN);
5164 else_branch = true;
5165 aop = OMP_ATOMIC_CAPTURE_OLD;
5166 capture_expr1 = code->block->block->next->expr1;
5167 capture_expr2 = code->block->block->next->expr2;
5169 else if (atomic_code->ext.omp_clauses->capture)
5171 gcc_assert (code->next->op == EXEC_ASSIGN);
5172 aop = OMP_ATOMIC_CAPTURE_NEW;
5173 capture_expr1 = code->next->expr1;
5174 capture_expr2 = code->next->expr2;
5177 else
5179 gcc_assert (atomic_code->ext.omp_clauses->capture
5180 && code->op == EXEC_ASSIGN
5181 && code->next->op == EXEC_IF);
5182 aop = OMP_ATOMIC_CAPTURE_OLD;
5183 capture_expr1 = code->expr1;
5184 capture_expr2 = code->expr2;
5185 expr1 = code->next->block->next->expr1;
5186 expr2 = code->next->block->next->expr2;
5187 comp_expr = code->next->block->expr1;
5189 gfc_init_se (&lse, NULL);
5190 gfc_conv_expr (&lse, comp_expr->value.op.op2);
5191 gfc_add_block_to_block (&block, &lse.pre);
5192 compare = lse.expr;
5193 var = expr1->symtree->n.sym;
5195 else
5197 gcc_assert (code->op == EXEC_ASSIGN);
5198 expr1 = code->expr1;
5199 expr2 = code->expr2;
5200 if (atomic_code->ext.omp_clauses->capture
5201 && (expr2->expr_type == EXPR_VARIABLE
5202 || (expr2->expr_type == EXPR_FUNCTION
5203 && expr2->value.function.isym
5204 && expr2->value.function.isym->id == GFC_ISYM_CONVERSION
5205 && (expr2->value.function.actual->expr->expr_type
5206 == EXPR_VARIABLE))))
5208 capture_expr1 = expr1;
5209 capture_expr2 = expr2;
5210 expr1 = code->next->expr1;
5211 expr2 = code->next->expr2;
5212 aop = OMP_ATOMIC_CAPTURE_OLD;
5214 else if (atomic_code->ext.omp_clauses->capture)
5216 aop = OMP_ATOMIC_CAPTURE_NEW;
5217 capture_expr1 = code->next->expr1;
5218 capture_expr2 = code->next->expr2;
5220 var = expr1->symtree->n.sym;
5223 gfc_init_se (&lse, NULL);
5224 gfc_init_se (&rse, NULL);
5225 gfc_init_se (&vse, NULL);
5226 gfc_start_block (&block);
5228 if (((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
5229 != GFC_OMP_ATOMIC_WRITE)
5230 && expr2->expr_type == EXPR_FUNCTION
5231 && expr2->value.function.isym
5232 && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
5233 expr2 = expr2->value.function.actual->expr;
5235 if ((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
5236 == GFC_OMP_ATOMIC_READ)
5238 gfc_conv_expr (&vse, expr1);
5239 gfc_add_block_to_block (&block, &vse.pre);
5241 gfc_conv_expr (&lse, expr2);
5242 gfc_add_block_to_block (&block, &lse.pre);
5243 type = TREE_TYPE (lse.expr);
5244 lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
5246 x = build1 (OMP_ATOMIC_READ, type, lhsaddr);
5247 OMP_ATOMIC_MEMORY_ORDER (x) = mo;
5248 x = convert (TREE_TYPE (vse.expr), x);
5249 gfc_add_modify (&block, vse.expr, x);
5251 gfc_add_block_to_block (&block, &lse.pre);
5252 gfc_add_block_to_block (&block, &rse.pre);
5254 return gfc_finish_block (&block);
5257 if (capture_expr2
5258 && capture_expr2->expr_type == EXPR_FUNCTION
5259 && capture_expr2->value.function.isym
5260 && capture_expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
5261 capture_expr2 = capture_expr2->value.function.actual->expr;
5262 gcc_assert (!capture_expr2 || capture_expr2->expr_type == EXPR_VARIABLE);
5264 if (aop == OMP_ATOMIC_CAPTURE_OLD)
5266 gfc_conv_expr (&vse, capture_expr1);
5267 gfc_add_block_to_block (&block, &vse.pre);
5268 gfc_conv_expr (&lse, capture_expr2);
5269 gfc_add_block_to_block (&block, &lse.pre);
5270 gfc_init_se (&lse, NULL);
5273 gfc_conv_expr (&lse, expr1);
5274 gfc_add_block_to_block (&block, &lse.pre);
5275 type = TREE_TYPE (lse.expr);
5276 lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
5278 if (((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
5279 == GFC_OMP_ATOMIC_WRITE)
5280 || (atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_SWAP)
5281 || compare)
5283 gfc_conv_expr (&rse, expr2);
5284 gfc_add_block_to_block (&block, &rse.pre);
5286 else if (expr2->expr_type == EXPR_OP)
5288 gfc_expr *e;
5289 switch (expr2->value.op.op)
5291 case INTRINSIC_PLUS:
5292 op = PLUS_EXPR;
5293 break;
5294 case INTRINSIC_TIMES:
5295 op = MULT_EXPR;
5296 break;
5297 case INTRINSIC_MINUS:
5298 op = MINUS_EXPR;
5299 break;
5300 case INTRINSIC_DIVIDE:
5301 if (expr2->ts.type == BT_INTEGER)
5302 op = TRUNC_DIV_EXPR;
5303 else
5304 op = RDIV_EXPR;
5305 break;
5306 case INTRINSIC_AND:
5307 op = TRUTH_ANDIF_EXPR;
5308 break;
5309 case INTRINSIC_OR:
5310 op = TRUTH_ORIF_EXPR;
5311 break;
5312 case INTRINSIC_EQV:
5313 op = EQ_EXPR;
5314 break;
5315 case INTRINSIC_NEQV:
5316 op = NE_EXPR;
5317 break;
5318 default:
5319 gcc_unreachable ();
5321 e = expr2->value.op.op1;
5322 if (e->expr_type == EXPR_FUNCTION
5323 && e->value.function.isym
5324 && e->value.function.isym->id == GFC_ISYM_CONVERSION)
5325 e = e->value.function.actual->expr;
5326 if (e->expr_type == EXPR_VARIABLE
5327 && e->symtree != NULL
5328 && e->symtree->n.sym == var)
5330 expr2 = expr2->value.op.op2;
5331 var_on_left = true;
5333 else
5335 e = expr2->value.op.op2;
5336 if (e->expr_type == EXPR_FUNCTION
5337 && e->value.function.isym
5338 && e->value.function.isym->id == GFC_ISYM_CONVERSION)
5339 e = e->value.function.actual->expr;
5340 gcc_assert (e->expr_type == EXPR_VARIABLE
5341 && e->symtree != NULL
5342 && e->symtree->n.sym == var);
5343 expr2 = expr2->value.op.op1;
5344 var_on_left = false;
5346 gfc_conv_expr (&rse, expr2);
5347 gfc_add_block_to_block (&block, &rse.pre);
5349 else
5351 gcc_assert (expr2->expr_type == EXPR_FUNCTION);
5352 switch (expr2->value.function.isym->id)
5354 case GFC_ISYM_MIN:
5355 op = MIN_EXPR;
5356 break;
5357 case GFC_ISYM_MAX:
5358 op = MAX_EXPR;
5359 break;
5360 case GFC_ISYM_IAND:
5361 op = BIT_AND_EXPR;
5362 break;
5363 case GFC_ISYM_IOR:
5364 op = BIT_IOR_EXPR;
5365 break;
5366 case GFC_ISYM_IEOR:
5367 op = BIT_XOR_EXPR;
5368 break;
5369 default:
5370 gcc_unreachable ();
5372 e = expr2->value.function.actual->expr;
5373 if (e->expr_type == EXPR_FUNCTION
5374 && e->value.function.isym
5375 && e->value.function.isym->id == GFC_ISYM_CONVERSION)
5376 e = e->value.function.actual->expr;
5377 gcc_assert (e->expr_type == EXPR_VARIABLE
5378 && e->symtree != NULL
5379 && e->symtree->n.sym == var);
5381 gfc_conv_expr (&rse, expr2->value.function.actual->next->expr);
5382 gfc_add_block_to_block (&block, &rse.pre);
5383 if (expr2->value.function.actual->next->next != NULL)
5385 tree accum = gfc_create_var (TREE_TYPE (rse.expr), NULL);
5386 gfc_actual_arglist *arg;
5388 gfc_add_modify (&block, accum, rse.expr);
5389 for (arg = expr2->value.function.actual->next->next; arg;
5390 arg = arg->next)
5392 gfc_init_block (&rse.pre);
5393 gfc_conv_expr (&rse, arg->expr);
5394 gfc_add_block_to_block (&block, &rse.pre);
5395 x = fold_build2_loc (input_location, op, TREE_TYPE (accum),
5396 accum, rse.expr);
5397 gfc_add_modify (&block, accum, x);
5400 rse.expr = accum;
5403 expr2 = expr2->value.function.actual->next->expr;
5406 lhsaddr = save_expr (lhsaddr);
5407 if (TREE_CODE (lhsaddr) != SAVE_EXPR
5408 && (TREE_CODE (lhsaddr) != ADDR_EXPR
5409 || !VAR_P (TREE_OPERAND (lhsaddr, 0))))
5411 /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
5412 it even after unsharing function body. */
5413 tree var = create_tmp_var_raw (TREE_TYPE (lhsaddr));
5414 DECL_CONTEXT (var) = current_function_decl;
5415 lhsaddr = build4 (TARGET_EXPR, TREE_TYPE (lhsaddr), var, lhsaddr,
5416 NULL_TREE, NULL_TREE);
5419 if (compare)
5421 tree var = create_tmp_var_raw (TREE_TYPE (lhsaddr));
5422 DECL_CONTEXT (var) = current_function_decl;
5423 lhsaddr = build4 (TARGET_EXPR, TREE_TYPE (lhsaddr), var, lhsaddr, NULL,
5424 NULL);
5425 lse.expr = build_fold_indirect_ref_loc (input_location, lhsaddr);
5426 compare = convert (TREE_TYPE (lse.expr), compare);
5427 compare = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
5428 lse.expr, compare);
5431 if (expr2->expr_type == EXPR_VARIABLE || compare)
5432 rhs = rse.expr;
5433 else
5434 rhs = gfc_evaluate_now (rse.expr, &block);
5436 if (((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
5437 == GFC_OMP_ATOMIC_WRITE)
5438 || (atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_SWAP)
5439 || compare)
5440 x = rhs;
5441 else
5443 x = convert (TREE_TYPE (rhs),
5444 build_fold_indirect_ref_loc (input_location, lhsaddr));
5445 if (var_on_left)
5446 x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), x, rhs);
5447 else
5448 x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), rhs, x);
5451 if (TREE_CODE (TREE_TYPE (rhs)) == COMPLEX_TYPE
5452 && TREE_CODE (type) != COMPLEX_TYPE)
5453 x = fold_build1_loc (input_location, REALPART_EXPR,
5454 TREE_TYPE (TREE_TYPE (rhs)), x);
5456 gfc_add_block_to_block (&block, &lse.pre);
5457 gfc_add_block_to_block (&block, &rse.pre);
5459 if (aop == OMP_ATOMIC_CAPTURE_NEW)
5461 gfc_conv_expr (&vse, capture_expr1);
5462 gfc_add_block_to_block (&block, &vse.pre);
5463 gfc_add_block_to_block (&block, &lse.pre);
5466 if (compare && else_branch)
5468 tree var2 = create_tmp_var_raw (boolean_type_node);
5469 DECL_CONTEXT (var2) = current_function_decl;
5470 comp_tgt = build4 (TARGET_EXPR, boolean_type_node, var2,
5471 boolean_false_node, NULL, NULL);
5472 compare = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (var2),
5473 var2, compare);
5474 TREE_OPERAND (compare, 0) = comp_tgt;
5475 compare = omit_one_operand_loc (input_location, boolean_type_node,
5476 compare, comp_tgt);
5479 if (compare)
5480 x = build3_loc (input_location, COND_EXPR, type, compare,
5481 convert (type, x), lse.expr);
5483 if (aop == OMP_ATOMIC)
5485 x = build2_v (OMP_ATOMIC, lhsaddr, convert (type, x));
5486 OMP_ATOMIC_MEMORY_ORDER (x) = mo;
5487 OMP_ATOMIC_WEAK (x) = atomic_code->ext.omp_clauses->weak;
5488 gfc_add_expr_to_block (&block, x);
5490 else
5492 x = build2 (aop, type, lhsaddr, convert (type, x));
5493 OMP_ATOMIC_MEMORY_ORDER (x) = mo;
5494 OMP_ATOMIC_WEAK (x) = atomic_code->ext.omp_clauses->weak;
5495 if (compare && else_branch)
5497 tree vtmp = create_tmp_var_raw (TREE_TYPE (x));
5498 DECL_CONTEXT (vtmp) = current_function_decl;
5499 x = fold_build2_loc (input_location, MODIFY_EXPR,
5500 TREE_TYPE (vtmp), vtmp, x);
5501 vtmp = build4 (TARGET_EXPR, TREE_TYPE (vtmp), vtmp,
5502 build_zero_cst (TREE_TYPE (vtmp)), NULL, NULL);
5503 TREE_OPERAND (x, 0) = vtmp;
5504 tree x2 = convert (TREE_TYPE (vse.expr), vtmp);
5505 x2 = fold_build2_loc (input_location, MODIFY_EXPR,
5506 TREE_TYPE (vse.expr), vse.expr, x2);
5507 x2 = build3_loc (input_location, COND_EXPR, void_type_node, comp_tgt,
5508 void_node, x2);
5509 x = omit_one_operand_loc (input_location, TREE_TYPE (x2), x2, x);
5510 gfc_add_expr_to_block (&block, x);
5512 else
5514 x = convert (TREE_TYPE (vse.expr), x);
5515 gfc_add_modify (&block, vse.expr, x);
5519 return gfc_finish_block (&block);
5522 static tree
5523 gfc_trans_omp_barrier (void)
5525 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
5526 return build_call_expr_loc (input_location, decl, 0);
5529 static tree
5530 gfc_trans_omp_cancel (gfc_code *code)
5532 int mask = 0;
5533 tree ifc = boolean_true_node;
5534 stmtblock_t block;
5535 switch (code->ext.omp_clauses->cancel)
5537 case OMP_CANCEL_PARALLEL: mask = 1; break;
5538 case OMP_CANCEL_DO: mask = 2; break;
5539 case OMP_CANCEL_SECTIONS: mask = 4; break;
5540 case OMP_CANCEL_TASKGROUP: mask = 8; break;
5541 default: gcc_unreachable ();
5543 gfc_start_block (&block);
5544 if (code->ext.omp_clauses->if_expr
5545 || code->ext.omp_clauses->if_exprs[OMP_IF_CANCEL])
5547 gfc_se se;
5548 tree if_var;
5550 gcc_assert ((code->ext.omp_clauses->if_expr == NULL)
5551 ^ (code->ext.omp_clauses->if_exprs[OMP_IF_CANCEL] == NULL));
5552 gfc_init_se (&se, NULL);
5553 gfc_conv_expr (&se, code->ext.omp_clauses->if_expr != NULL
5554 ? code->ext.omp_clauses->if_expr
5555 : code->ext.omp_clauses->if_exprs[OMP_IF_CANCEL]);
5556 gfc_add_block_to_block (&block, &se.pre);
5557 if_var = gfc_evaluate_now (se.expr, &block);
5558 gfc_add_block_to_block (&block, &se.post);
5559 tree type = TREE_TYPE (if_var);
5560 ifc = fold_build2_loc (input_location, NE_EXPR,
5561 boolean_type_node, if_var,
5562 build_zero_cst (type));
5564 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
5565 tree c_bool_type = TREE_TYPE (TREE_TYPE (decl));
5566 ifc = fold_convert (c_bool_type, ifc);
5567 gfc_add_expr_to_block (&block,
5568 build_call_expr_loc (input_location, decl, 2,
5569 build_int_cst (integer_type_node,
5570 mask), ifc));
5571 return gfc_finish_block (&block);
5574 static tree
5575 gfc_trans_omp_cancellation_point (gfc_code *code)
5577 int mask = 0;
5578 switch (code->ext.omp_clauses->cancel)
5580 case OMP_CANCEL_PARALLEL: mask = 1; break;
5581 case OMP_CANCEL_DO: mask = 2; break;
5582 case OMP_CANCEL_SECTIONS: mask = 4; break;
5583 case OMP_CANCEL_TASKGROUP: mask = 8; break;
5584 default: gcc_unreachable ();
5586 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCELLATION_POINT);
5587 return build_call_expr_loc (input_location, decl, 1,
5588 build_int_cst (integer_type_node, mask));
5591 static tree
5592 gfc_trans_omp_critical (gfc_code *code)
5594 stmtblock_t block;
5595 tree stmt, name = NULL_TREE;
5596 if (code->ext.omp_clauses->critical_name != NULL)
5597 name = get_identifier (code->ext.omp_clauses->critical_name);
5598 gfc_start_block (&block);
5599 stmt = make_node (OMP_CRITICAL);
5600 SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
5601 TREE_TYPE (stmt) = void_type_node;
5602 OMP_CRITICAL_BODY (stmt) = gfc_trans_code (code->block->next);
5603 OMP_CRITICAL_NAME (stmt) = name;
5604 OMP_CRITICAL_CLAUSES (stmt) = gfc_trans_omp_clauses (&block,
5605 code->ext.omp_clauses,
5606 code->loc);
5607 gfc_add_expr_to_block (&block, stmt);
5608 return gfc_finish_block (&block);
5611 typedef struct dovar_init_d {
5612 gfc_symbol *sym;
5613 tree var;
5614 tree init;
5615 bool non_unit_iter;
5616 } dovar_init;
5618 static bool
5619 gfc_nonrect_loop_expr (stmtblock_t *pblock, gfc_se *sep, int loop_n,
5620 gfc_code *code, gfc_expr *expr, vec<dovar_init> *inits,
5621 int simple, gfc_expr *curr_loop_var)
5623 int i;
5624 for (i = 0; i < loop_n; i++)
5626 gcc_assert (code->ext.iterator->var->expr_type == EXPR_VARIABLE);
5627 if (gfc_find_sym_in_expr (code->ext.iterator->var->symtree->n.sym, expr))
5628 break;
5629 code = code->block->next;
5631 if (i >= loop_n)
5632 return false;
5634 /* Canonical format: TREE_VEC with [var, multiplier, offset]. */
5635 gfc_symbol *var = code->ext.iterator->var->symtree->n.sym;
5637 tree tree_var = NULL_TREE;
5638 tree a1 = integer_one_node;
5639 tree a2 = integer_zero_node;
5641 if (!simple)
5643 /* FIXME: Handle non-const iter steps, cf. PR fortran/110735. */
5644 sorry_at (gfc_get_location (&curr_loop_var->where),
5645 "non-rectangular loop nest with non-constant step for %qs",
5646 curr_loop_var->symtree->n.sym->name);
5647 return false;
5650 dovar_init *di;
5651 unsigned ix;
5652 FOR_EACH_VEC_ELT (*inits, ix, di)
5653 if (di->sym == var)
5655 if (!di->non_unit_iter)
5657 tree_var = di->init;
5658 gcc_assert (DECL_P (tree_var));
5659 break;
5661 else
5663 /* FIXME: Handle non-const iter steps, cf. PR fortran/110735. */
5664 sorry_at (gfc_get_location (&code->loc),
5665 "non-rectangular loop nest with non-constant step "
5666 "for %qs", var->name);
5667 inform (gfc_get_location (&expr->where), "Used here");
5668 return false;
5671 if (tree_var == NULL_TREE)
5672 tree_var = var->backend_decl;
5674 if (expr->expr_type == EXPR_VARIABLE)
5675 gcc_assert (expr->symtree->n.sym == var);
5676 else if (expr->expr_type != EXPR_OP
5677 || (expr->value.op.op != INTRINSIC_TIMES
5678 && expr->value.op.op != INTRINSIC_PLUS
5679 && expr->value.op.op != INTRINSIC_MINUS))
5680 gcc_unreachable ();
5681 else
5683 gfc_se se;
5684 gfc_expr *et = NULL, *eo = NULL, *e = expr;
5685 if (expr->value.op.op != INTRINSIC_TIMES)
5687 if (gfc_find_sym_in_expr (var, expr->value.op.op1))
5689 e = expr->value.op.op1;
5690 eo = expr->value.op.op2;
5692 else
5694 eo = expr->value.op.op1;
5695 e = expr->value.op.op2;
5698 if (e->value.op.op == INTRINSIC_TIMES)
5700 if (e->value.op.op1->expr_type == EXPR_VARIABLE
5701 && e->value.op.op1->symtree->n.sym == var)
5702 et = e->value.op.op2;
5703 else
5705 et = e->value.op.op1;
5706 gcc_assert (e->value.op.op2->expr_type == EXPR_VARIABLE
5707 && e->value.op.op2->symtree->n.sym == var);
5710 else
5711 gcc_assert (e->expr_type == EXPR_VARIABLE && e->symtree->n.sym == var);
5712 if (et != NULL)
5714 gfc_init_se (&se, NULL);
5715 gfc_conv_expr_val (&se, et);
5716 gfc_add_block_to_block (pblock, &se.pre);
5717 a1 = se.expr;
5719 if (eo != NULL)
5721 gfc_init_se (&se, NULL);
5722 gfc_conv_expr_val (&se, eo);
5723 gfc_add_block_to_block (pblock, &se.pre);
5724 a2 = se.expr;
5725 if (expr->value.op.op == INTRINSIC_MINUS && expr->value.op.op2 == eo)
5726 /* outer-var - a2. */
5727 a2 = fold_build1 (NEGATE_EXPR, TREE_TYPE (a2), a2);
5728 else if (expr->value.op.op == INTRINSIC_MINUS)
5729 /* a2 - outer-var. */
5730 a1 = fold_build1 (NEGATE_EXPR, TREE_TYPE (a1), a1);
5732 a1 = DECL_P (a1) ? a1 : gfc_evaluate_now (a1, pblock);
5733 a2 = DECL_P (a2) ? a2 : gfc_evaluate_now (a2, pblock);
5736 gfc_init_se (sep, NULL);
5737 sep->expr = make_tree_vec (3);
5738 TREE_VEC_ELT (sep->expr, 0) = tree_var;
5739 TREE_VEC_ELT (sep->expr, 1) = fold_convert (TREE_TYPE (tree_var), a1);
5740 TREE_VEC_ELT (sep->expr, 2) = fold_convert (TREE_TYPE (tree_var), a2);
5742 return true;
5746 gfc_expr_list_len (gfc_expr_list *list)
5748 unsigned len = 0;
5749 for (; list; list = list->next)
5750 len++;
5752 return len;
5755 static tree
5756 gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
5757 gfc_omp_clauses *do_clauses, tree par_clauses)
5759 gfc_se se;
5760 tree dovar, stmt, from, to, step, type, init, cond, incr, orig_decls;
5761 tree local_dovar = NULL_TREE, cycle_label, tmp, omp_clauses;
5762 stmtblock_t block;
5763 stmtblock_t body;
5764 gfc_omp_clauses *clauses = code->ext.omp_clauses;
5765 int i, collapse = clauses->collapse;
5766 vec<dovar_init> inits = vNULL;
5767 dovar_init *di;
5768 unsigned ix;
5769 vec<tree, va_heap, vl_embed> *saved_doacross_steps = doacross_steps;
5770 gfc_expr_list *oacc_tile
5771 = do_clauses ? do_clauses->tile_list : clauses->tile_list;
5772 gfc_expr_list *sizes
5773 = do_clauses ? do_clauses->sizes_list : clauses->sizes_list;
5774 gfc_code *orig_code = code;
5776 /* Both collapsed and tiled loops are lowered the same way. In
5777 OpenACC, those clauses are not compatible, so prioritize the tile
5778 clause, if present. */
5779 if (oacc_tile)
5780 collapse = gfc_expr_list_len (oacc_tile);
5781 else if (sizes)
5782 collapse = gfc_expr_list_len (sizes);
5784 doacross_steps = NULL;
5785 if (clauses->orderedc)
5786 collapse = clauses->orderedc;
5787 if (collapse <= 0)
5788 collapse = 1;
5790 code = code->block->next;
5792 init = make_tree_vec (collapse);
5793 cond = make_tree_vec (collapse);
5794 incr = make_tree_vec (collapse);
5795 orig_decls = clauses->ordered ? make_tree_vec (collapse) : NULL_TREE;
5797 if (pblock == NULL)
5799 gfc_start_block (&block);
5800 pblock = &block;
5803 /* simd schedule modifier is only useful for composite do simd and other
5804 constructs including that, where gfc_trans_omp_do is only called
5805 on the simd construct and DO's clauses are translated elsewhere. */
5806 do_clauses->sched_simd = false;
5808 omp_clauses = gfc_trans_omp_clauses (pblock, do_clauses, code->loc);
5810 for (i = 0; i < collapse; i++)
5812 int simple = 0;
5813 int dovar_found = 0;
5814 tree dovar_decl;
5816 if (code->op == EXEC_OMP_TILE || code->op == EXEC_OMP_UNROLL)
5818 TREE_VEC_ELT (init, i) = NULL_TREE;
5819 TREE_VEC_ELT (cond, i) = NULL_TREE;
5820 TREE_VEC_ELT (incr, i) = NULL_TREE;
5821 TREE_VEC_ELT (incr, i) = NULL_TREE;
5822 if (orig_decls)
5823 TREE_VEC_ELT (orig_decls, i) = NULL_TREE;
5824 continue;
5826 gcc_assert (code->op == EXEC_DO);
5827 if (clauses)
5829 gfc_omp_namelist *n = NULL;
5830 if (op == EXEC_OMP_SIMD && collapse == 1)
5831 for (n = clauses->lists[OMP_LIST_LINEAR];
5832 n != NULL; n = n->next)
5833 if (code->ext.iterator->var->symtree->n.sym == n->sym)
5835 dovar_found = 3;
5836 break;
5838 if (n == NULL && op != EXEC_OMP_DISTRIBUTE)
5839 for (n = clauses->lists[OMP_LIST_LASTPRIVATE];
5840 n != NULL; n = n->next)
5841 if (code->ext.iterator->var->symtree->n.sym == n->sym)
5843 dovar_found = 2;
5844 break;
5846 if (n == NULL)
5847 for (n = clauses->lists[OMP_LIST_PRIVATE]; n != NULL; n = n->next)
5848 if (code->ext.iterator->var->symtree->n.sym == n->sym)
5850 dovar_found = 1;
5851 break;
5855 /* Evaluate all the expressions in the iterator. */
5856 gfc_init_se (&se, NULL);
5857 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
5858 gfc_add_block_to_block (pblock, &se.pre);
5859 local_dovar = dovar_decl = dovar = se.expr;
5860 type = TREE_TYPE (dovar);
5861 gcc_assert (TREE_CODE (type) == INTEGER_TYPE);
5863 gfc_init_se (&se, NULL);
5864 gfc_conv_expr_val (&se, code->ext.iterator->step);
5865 gfc_add_block_to_block (pblock, &se.pre);
5866 step = gfc_evaluate_now (se.expr, pblock);
5868 if (TREE_CODE (step) == INTEGER_CST)
5869 simple = tree_int_cst_sgn (step);
5871 gfc_init_se (&se, NULL);
5872 if (!clauses->non_rectangular
5873 || !gfc_nonrect_loop_expr (pblock, &se, i, orig_code->block->next,
5874 code->ext.iterator->start, &inits, simple,
5875 code->ext.iterator->var))
5877 gfc_conv_expr_val (&se, code->ext.iterator->start);
5878 gfc_add_block_to_block (pblock, &se.pre);
5879 if (!DECL_P (se.expr))
5880 se.expr = gfc_evaluate_now (se.expr, pblock);
5882 from = se.expr;
5884 gfc_init_se (&se, NULL);
5885 if (!clauses->non_rectangular
5886 || !gfc_nonrect_loop_expr (pblock, &se, i, orig_code->block->next,
5887 code->ext.iterator->end, &inits, simple,
5888 code->ext.iterator->var))
5890 gfc_conv_expr_val (&se, code->ext.iterator->end);
5891 gfc_add_block_to_block (pblock, &se.pre);
5892 if (!DECL_P (se.expr))
5893 se.expr = gfc_evaluate_now (se.expr, pblock);
5895 to = se.expr;
5897 if (!DECL_P (dovar))
5898 dovar_decl
5899 = gfc_trans_omp_variable (code->ext.iterator->var->symtree->n.sym,
5900 false);
5901 if (simple && !DECL_P (dovar))
5903 const char *name = code->ext.iterator->var->symtree->n.sym->name;
5904 local_dovar = gfc_create_var (type, name);
5905 dovar_init e = {code->ext.iterator->var->symtree->n.sym,
5906 dovar, local_dovar, false};
5907 inits.safe_push (e);
5909 /* Loop body. */
5910 if (simple)
5912 TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, local_dovar, from);
5913 /* The condition should not be folded. */
5914 TREE_VEC_ELT (cond, i) = build2_loc (input_location, simple > 0
5915 ? LE_EXPR : GE_EXPR,
5916 logical_type_node, local_dovar,
5917 to);
5918 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR,
5919 type, local_dovar, step);
5920 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location,
5921 MODIFY_EXPR,
5922 type, local_dovar,
5923 TREE_VEC_ELT (incr, i));
5924 if (orig_decls && !clauses->orderedc)
5925 orig_decls = NULL;
5926 else if (orig_decls)
5927 TREE_VEC_ELT (orig_decls, i) = dovar_decl;
5929 else
5931 /* STEP is not 1 or -1. Use:
5932 for (count = 0; count < (to + step - from) / step; count++)
5934 dovar = from + count * step;
5935 body;
5936 cycle_label:;
5937 } */
5938 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, step, from);
5939 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, to, tmp);
5940 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, type, tmp,
5941 step);
5942 tmp = gfc_evaluate_now (tmp, pblock);
5943 local_dovar = gfc_create_var (type, "count");
5944 TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, local_dovar,
5945 build_int_cst (type, 0));
5946 /* The condition should not be folded. */
5947 TREE_VEC_ELT (cond, i) = build2_loc (input_location, LT_EXPR,
5948 logical_type_node,
5949 local_dovar, tmp);
5950 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR,
5951 type, local_dovar,
5952 build_int_cst (type, 1));
5953 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location,
5954 MODIFY_EXPR, type,
5955 local_dovar,
5956 TREE_VEC_ELT (incr, i));
5958 /* Initialize DOVAR. */
5959 tmp = fold_build2_loc (input_location, MULT_EXPR, type, local_dovar,
5960 step);
5961 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, from, tmp);
5962 dovar_init e = {code->ext.iterator->var->symtree->n.sym,
5963 dovar, tmp, true};
5964 inits.safe_push (e);
5965 if (clauses->orderedc)
5967 if (doacross_steps == NULL)
5968 vec_safe_grow_cleared (doacross_steps, clauses->orderedc, true);
5969 (*doacross_steps)[i] = step;
5971 if (orig_decls)
5972 TREE_VEC_ELT (orig_decls, i) = dovar_decl;
5975 if (dovar_found == 3
5976 && op == EXEC_OMP_SIMD
5977 && collapse == 1
5978 && local_dovar != dovar)
5980 for (tmp = omp_clauses; tmp; tmp = OMP_CLAUSE_CHAIN (tmp))
5981 if (OMP_CLAUSE_CODE (tmp) == OMP_CLAUSE_LINEAR
5982 && OMP_CLAUSE_DECL (tmp) == dovar)
5984 OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
5985 break;
5988 if (!dovar_found && op == EXEC_OMP_SIMD)
5990 if (collapse == 1)
5992 tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
5993 OMP_CLAUSE_LINEAR_STEP (tmp) = step;
5994 OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
5995 OMP_CLAUSE_DECL (tmp) = dovar_decl;
5996 omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
5997 if (local_dovar != dovar)
5998 dovar_found = 3;
6001 else if (!dovar_found && local_dovar != dovar)
6003 tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
6004 OMP_CLAUSE_DECL (tmp) = dovar_decl;
6005 omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
6007 if (dovar_found > 1)
6009 tree c = NULL;
6011 tmp = NULL;
6012 if (local_dovar != dovar)
6014 /* If dovar is lastprivate, but different counter is used,
6015 dovar += step needs to be added to
6016 OMP_CLAUSE_LASTPRIVATE_STMT, otherwise the copied dovar
6017 will have the value on entry of the last loop, rather
6018 than value after iterator increment. */
6019 if (clauses->orderedc)
6021 if (clauses->collapse <= 1 || i >= clauses->collapse)
6022 tmp = local_dovar;
6023 else
6024 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6025 type, local_dovar,
6026 build_one_cst (type));
6027 tmp = fold_build2_loc (input_location, MULT_EXPR, type,
6028 tmp, step);
6029 tmp = fold_build2_loc (input_location, PLUS_EXPR, type,
6030 from, tmp);
6032 else
6033 tmp = fold_build2_loc (input_location, PLUS_EXPR, type,
6034 dovar, step);
6035 tmp = fold_build2_loc (input_location, MODIFY_EXPR, type,
6036 dovar, tmp);
6037 for (c = omp_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6038 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
6039 && OMP_CLAUSE_DECL (c) == dovar_decl)
6041 OMP_CLAUSE_LASTPRIVATE_STMT (c) = tmp;
6042 break;
6044 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
6045 && OMP_CLAUSE_DECL (c) == dovar_decl)
6047 OMP_CLAUSE_LINEAR_STMT (c) = tmp;
6048 break;
6051 if (c == NULL && op == EXEC_OMP_DO && par_clauses != NULL)
6053 for (c = par_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6054 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
6055 && OMP_CLAUSE_DECL (c) == dovar_decl)
6057 tree l = build_omp_clause (input_location,
6058 OMP_CLAUSE_LASTPRIVATE);
6059 if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
6060 OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (l) = 1;
6061 OMP_CLAUSE_DECL (l) = dovar_decl;
6062 OMP_CLAUSE_CHAIN (l) = omp_clauses;
6063 OMP_CLAUSE_LASTPRIVATE_STMT (l) = tmp;
6064 omp_clauses = l;
6065 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_SHARED);
6066 break;
6069 gcc_assert (local_dovar == dovar || c != NULL);
6071 if (local_dovar != dovar)
6073 if (op != EXEC_OMP_SIMD || dovar_found == 1)
6074 tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
6075 else if (collapse == 1)
6077 tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
6078 OMP_CLAUSE_LINEAR_STEP (tmp) = build_int_cst (type, 1);
6079 OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
6080 OMP_CLAUSE_LINEAR_NO_COPYOUT (tmp) = 1;
6082 else
6083 tmp = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
6084 OMP_CLAUSE_DECL (tmp) = local_dovar;
6085 omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
6088 if (i + 1 < collapse)
6089 code = code->block->next;
6092 if (pblock != &block)
6094 pushlevel ();
6095 gfc_start_block (&block);
6098 gfc_start_block (&body);
6100 FOR_EACH_VEC_ELT (inits, ix, di)
6101 gfc_add_modify (&body, di->var, di->init);
6102 inits.release ();
6104 /* Cycle statement is implemented with a goto. Exit statement must not be
6105 present for this loop. */
6106 cycle_label = gfc_build_label_decl (NULL_TREE);
6108 /* Put these labels where they can be found later. */
6110 code->cycle_label = cycle_label;
6111 code->exit_label = NULL_TREE;
6113 /* Main loop body. */
6114 if (clauses->lists[OMP_LIST_REDUCTION_INSCAN])
6116 gfc_code *code1, *scan, *code2, *tmpcode;
6117 code1 = tmpcode = code->block->next;
6118 if (tmpcode && tmpcode->op != EXEC_OMP_SCAN)
6119 while (tmpcode && tmpcode->next && tmpcode->next->op != EXEC_OMP_SCAN)
6120 tmpcode = tmpcode->next;
6121 scan = tmpcode->op == EXEC_OMP_SCAN ? tmpcode : tmpcode->next;
6122 if (code1 != scan)
6123 tmpcode->next = NULL;
6124 code2 = scan->next;
6125 gcc_assert (scan->op == EXEC_OMP_SCAN);
6126 location_t loc = gfc_get_location (&scan->loc);
6128 tmp = code1 != scan ? gfc_trans_code (code1) : build_empty_stmt (loc);
6129 tmp = build2 (OMP_SCAN, void_type_node, tmp, NULL_TREE);
6130 SET_EXPR_LOCATION (tmp, loc);
6131 gfc_add_expr_to_block (&body, tmp);
6132 input_location = loc;
6133 tree c = gfc_trans_omp_clauses (&body, scan->ext.omp_clauses, scan->loc);
6134 tmp = code2 ? gfc_trans_code (code2) : build_empty_stmt (loc);
6135 tmp = build2 (OMP_SCAN, void_type_node, tmp, c);
6136 SET_EXPR_LOCATION (tmp, loc);
6137 if (code1 != scan)
6138 tmpcode->next = scan;
6140 else if (code->op == EXEC_OMP_TILE || code->op == EXEC_OMP_UNROLL)
6141 tmp = gfc_trans_omp_code (code, true);
6142 else
6143 tmp = gfc_trans_omp_code (code->block->next, true);
6144 gfc_add_expr_to_block (&body, tmp);
6146 /* Label for cycle statements (if needed). */
6147 if (TREE_USED (cycle_label))
6149 tmp = build1_v (LABEL_EXPR, cycle_label);
6150 gfc_add_expr_to_block (&body, tmp);
6153 /* End of loop body. */
6154 switch (op)
6156 case EXEC_OMP_SIMD: stmt = make_node (OMP_SIMD); break;
6157 case EXEC_OMP_DO: stmt = make_node (OMP_FOR); break;
6158 case EXEC_OMP_DISTRIBUTE: stmt = make_node (OMP_DISTRIBUTE); break;
6159 case EXEC_OMP_LOOP: stmt = make_node (OMP_LOOP); break;
6160 case EXEC_OMP_TASKLOOP: stmt = make_node (OMP_TASKLOOP); break;
6161 case EXEC_OACC_LOOP: stmt = make_node (OACC_LOOP); break;
6162 case EXEC_OMP_TILE: stmt = make_node (OMP_TILE); break;
6163 case EXEC_OMP_UNROLL: stmt = make_node (OMP_UNROLL); break;
6164 default: gcc_unreachable ();
6167 SET_EXPR_LOCATION (stmt, gfc_get_location (&orig_code->loc));
6168 TREE_TYPE (stmt) = void_type_node;
6169 OMP_FOR_BODY (stmt) = gfc_finish_block (&body);
6170 OMP_FOR_CLAUSES (stmt) = omp_clauses;
6171 OMP_FOR_INIT (stmt) = init;
6172 OMP_FOR_COND (stmt) = cond;
6173 OMP_FOR_INCR (stmt) = incr;
6174 if (orig_decls)
6175 OMP_FOR_ORIG_DECLS (stmt) = orig_decls;
6176 OMP_FOR_NON_RECTANGULAR (stmt) = clauses->non_rectangular;
6177 gfc_add_expr_to_block (&block, stmt);
6179 vec_free (doacross_steps);
6180 doacross_steps = saved_doacross_steps;
6182 return gfc_finish_block (&block);
6185 /* Translate combined OpenACC 'parallel loop', 'kernels loop', 'serial loop'
6186 construct. */
6188 static tree
6189 gfc_trans_oacc_combined_directive (gfc_code *code)
6191 stmtblock_t block, *pblock = NULL;
6192 gfc_omp_clauses construct_clauses, loop_clauses;
6193 tree stmt, oacc_clauses = NULL_TREE;
6194 enum tree_code construct_code;
6195 location_t loc = input_location;
6197 switch (code->op)
6199 case EXEC_OACC_PARALLEL_LOOP:
6200 construct_code = OACC_PARALLEL;
6201 break;
6202 case EXEC_OACC_KERNELS_LOOP:
6203 construct_code = OACC_KERNELS;
6204 break;
6205 case EXEC_OACC_SERIAL_LOOP:
6206 construct_code = OACC_SERIAL;
6207 break;
6208 default:
6209 gcc_unreachable ();
6212 gfc_start_block (&block);
6214 memset (&loop_clauses, 0, sizeof (loop_clauses));
6215 if (code->ext.omp_clauses != NULL)
6217 memcpy (&construct_clauses, code->ext.omp_clauses,
6218 sizeof (construct_clauses));
6219 loop_clauses.collapse = construct_clauses.collapse;
6220 loop_clauses.gang = construct_clauses.gang;
6221 loop_clauses.gang_static = construct_clauses.gang_static;
6222 loop_clauses.gang_num_expr = construct_clauses.gang_num_expr;
6223 loop_clauses.gang_static_expr = construct_clauses.gang_static_expr;
6224 loop_clauses.vector = construct_clauses.vector;
6225 loop_clauses.vector_expr = construct_clauses.vector_expr;
6226 loop_clauses.worker = construct_clauses.worker;
6227 loop_clauses.worker_expr = construct_clauses.worker_expr;
6228 loop_clauses.seq = construct_clauses.seq;
6229 loop_clauses.par_auto = construct_clauses.par_auto;
6230 loop_clauses.independent = construct_clauses.independent;
6231 loop_clauses.tile_list = construct_clauses.tile_list;
6232 loop_clauses.lists[OMP_LIST_PRIVATE]
6233 = construct_clauses.lists[OMP_LIST_PRIVATE];
6234 loop_clauses.lists[OMP_LIST_REDUCTION]
6235 = construct_clauses.lists[OMP_LIST_REDUCTION];
6236 construct_clauses.gang = false;
6237 construct_clauses.gang_static = false;
6238 construct_clauses.gang_num_expr = NULL;
6239 construct_clauses.gang_static_expr = NULL;
6240 construct_clauses.vector = false;
6241 construct_clauses.vector_expr = NULL;
6242 construct_clauses.worker = false;
6243 construct_clauses.worker_expr = NULL;
6244 construct_clauses.seq = false;
6245 construct_clauses.par_auto = false;
6246 construct_clauses.independent = false;
6247 construct_clauses.independent = false;
6248 construct_clauses.tile_list = NULL;
6249 construct_clauses.lists[OMP_LIST_PRIVATE] = NULL;
6250 if (construct_code == OACC_KERNELS)
6251 construct_clauses.lists[OMP_LIST_REDUCTION] = NULL;
6252 oacc_clauses = gfc_trans_omp_clauses (&block, &construct_clauses,
6253 code->loc, false, true);
6255 if (!loop_clauses.seq)
6256 pblock = &block;
6257 else
6258 pushlevel ();
6259 stmt = gfc_trans_omp_do (code, EXEC_OACC_LOOP, pblock, &loop_clauses, NULL);
6260 protected_set_expr_location (stmt, loc);
6261 if (TREE_CODE (stmt) != BIND_EXPR)
6262 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6263 else
6264 poplevel (0, 0);
6265 stmt = build2_loc (loc, construct_code, void_type_node, stmt, oacc_clauses);
6266 gfc_add_expr_to_block (&block, stmt);
6267 return gfc_finish_block (&block);
6270 static tree
6271 gfc_trans_omp_depobj (gfc_code *code)
6273 stmtblock_t block;
6274 gfc_se se;
6275 gfc_init_se (&se, NULL);
6276 gfc_init_block (&block);
6277 gfc_conv_expr (&se, code->ext.omp_clauses->depobj);
6278 gcc_assert (se.pre.head == NULL && se.post.head == NULL);
6279 tree depobj = se.expr;
6280 location_t loc = EXPR_LOCATION (depobj);
6281 if (!POINTER_TYPE_P (TREE_TYPE (depobj)))
6282 depobj = gfc_build_addr_expr (NULL, depobj);
6283 depobj = fold_convert (build_pointer_type_for_mode (ptr_type_node,
6284 TYPE_MODE (ptr_type_node),
6285 true), depobj);
6286 gfc_omp_namelist *n = code->ext.omp_clauses->lists[OMP_LIST_DEPEND];
6287 if (n)
6289 tree var;
6290 if (!n->sym) /* omp_all_memory. */
6291 var = null_pointer_node;
6292 else if (n->expr && n->expr->ref->u.ar.type != AR_FULL)
6294 gfc_init_se (&se, NULL);
6295 if (n->expr->ref->u.ar.type == AR_ELEMENT)
6297 gfc_conv_expr_reference (&se, n->expr);
6298 var = se.expr;
6300 else
6302 gfc_conv_expr_descriptor (&se, n->expr);
6303 var = gfc_conv_array_data (se.expr);
6305 gfc_add_block_to_block (&block, &se.pre);
6306 gfc_add_block_to_block (&block, &se.post);
6307 gcc_assert (POINTER_TYPE_P (TREE_TYPE (var)));
6309 else
6311 var = gfc_get_symbol_decl (n->sym);
6312 if (POINTER_TYPE_P (TREE_TYPE (var))
6313 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (var))))
6314 var = build_fold_indirect_ref (var);
6315 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (var)))
6317 var = gfc_conv_descriptor_data_get (var);
6318 gcc_assert (POINTER_TYPE_P (TREE_TYPE (var)));
6320 else if ((n->sym->attr.allocatable || n->sym->attr.pointer)
6321 && n->sym->attr.dummy)
6322 var = build_fold_indirect_ref (var);
6323 else if (!POINTER_TYPE_P (TREE_TYPE (var))
6324 || (n->sym->ts.f90_type == BT_VOID
6325 && !POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (var)))
6326 && !GFC_ARRAY_TYPE_P (TREE_TYPE (TREE_TYPE (var)))))
6328 TREE_ADDRESSABLE (var) = 1;
6329 var = gfc_build_addr_expr (NULL, var);
6332 depobj = save_expr (depobj);
6333 tree r = build_fold_indirect_ref_loc (loc, depobj);
6334 gfc_add_expr_to_block (&block,
6335 build2 (MODIFY_EXPR, void_type_node, r, var));
6338 /* Only one may be set. */
6339 gcc_assert (((int)(n != NULL) + (int)(code->ext.omp_clauses->destroy)
6340 + (int)(code->ext.omp_clauses->depobj_update != OMP_DEPEND_UNSET))
6341 == 1);
6342 int k = -1; /* omp_clauses->destroy */
6343 if (!code->ext.omp_clauses->destroy)
6344 switch (code->ext.omp_clauses->depobj_update != OMP_DEPEND_UNSET
6345 ? code->ext.omp_clauses->depobj_update : n->u.depend_doacross_op)
6347 case OMP_DEPEND_IN: k = GOMP_DEPEND_IN; break;
6348 case OMP_DEPEND_OUT: k = GOMP_DEPEND_OUT; break;
6349 case OMP_DEPEND_INOUT: k = GOMP_DEPEND_INOUT; break;
6350 case OMP_DEPEND_INOUTSET: k = GOMP_DEPEND_INOUTSET; break;
6351 case OMP_DEPEND_MUTEXINOUTSET: k = GOMP_DEPEND_MUTEXINOUTSET; break;
6352 default: gcc_unreachable ();
6354 tree t = build_int_cst (ptr_type_node, k);
6355 depobj = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (depobj), depobj,
6356 TYPE_SIZE_UNIT (ptr_type_node));
6357 depobj = build_fold_indirect_ref_loc (loc, depobj);
6358 gfc_add_expr_to_block (&block, build2 (MODIFY_EXPR, void_type_node, depobj, t));
6360 return gfc_finish_block (&block);
6363 static tree
6364 gfc_trans_omp_error (gfc_code *code)
6366 stmtblock_t block;
6367 gfc_se se;
6368 tree len, message;
6369 bool fatal = code->ext.omp_clauses->severity == OMP_SEVERITY_FATAL;
6370 tree fndecl = builtin_decl_explicit (fatal ? BUILT_IN_GOMP_ERROR
6371 : BUILT_IN_GOMP_WARNING);
6372 gfc_start_block (&block);
6373 gfc_init_se (&se, NULL );
6374 if (!code->ext.omp_clauses->message)
6376 message = null_pointer_node;
6377 len = build_int_cst (size_type_node, 0);
6379 else
6381 gfc_conv_expr (&se, code->ext.omp_clauses->message);
6382 message = se.expr;
6383 if (!POINTER_TYPE_P (TREE_TYPE (message)))
6384 /* To ensure an ARRAY_TYPE is not passed as such. */
6385 message = gfc_build_addr_expr (NULL, message);
6386 len = se.string_length;
6388 gfc_add_block_to_block (&block, &se.pre);
6389 gfc_add_expr_to_block (&block, build_call_expr_loc (input_location, fndecl,
6390 2, message, len));
6391 gfc_add_block_to_block (&block, &se.post);
6392 return gfc_finish_block (&block);
6395 static tree
6396 gfc_trans_omp_flush (gfc_code *code)
6398 tree call;
6399 if (!code->ext.omp_clauses
6400 || code->ext.omp_clauses->memorder == OMP_MEMORDER_UNSET
6401 || code->ext.omp_clauses->memorder == OMP_MEMORDER_SEQ_CST)
6403 call = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
6404 call = build_call_expr_loc (input_location, call, 0);
6406 else
6408 enum memmodel mo = MEMMODEL_LAST;
6409 switch (code->ext.omp_clauses->memorder)
6411 case OMP_MEMORDER_ACQ_REL: mo = MEMMODEL_ACQ_REL; break;
6412 case OMP_MEMORDER_RELEASE: mo = MEMMODEL_RELEASE; break;
6413 case OMP_MEMORDER_ACQUIRE: mo = MEMMODEL_ACQUIRE; break;
6414 default: gcc_unreachable (); break;
6416 call = builtin_decl_explicit (BUILT_IN_ATOMIC_THREAD_FENCE);
6417 call = build_call_expr_loc (input_location, call, 1,
6418 build_int_cst (integer_type_node, mo));
6420 return call;
6423 static tree
6424 gfc_trans_omp_master (gfc_code *code)
6426 tree stmt = gfc_trans_code (code->block->next);
6427 if (IS_EMPTY_STMT (stmt))
6428 return stmt;
6429 return build1_v (OMP_MASTER, stmt);
6432 static tree
6433 gfc_trans_omp_masked (gfc_code *code, gfc_omp_clauses *clauses)
6435 stmtblock_t block;
6436 tree body = gfc_trans_code (code->block->next);
6437 if (IS_EMPTY_STMT (body))
6438 return body;
6439 if (!clauses)
6440 clauses = code->ext.omp_clauses;
6441 gfc_start_block (&block);
6442 tree omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
6443 tree stmt = make_node (OMP_MASKED);
6444 SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
6445 TREE_TYPE (stmt) = void_type_node;
6446 OMP_MASKED_BODY (stmt) = body;
6447 OMP_MASKED_CLAUSES (stmt) = omp_clauses;
6448 gfc_add_expr_to_block (&block, stmt);
6449 return gfc_finish_block (&block);
6453 static tree
6454 gfc_trans_omp_ordered (gfc_code *code)
6456 if (!flag_openmp)
6458 if (!code->ext.omp_clauses->simd)
6459 return gfc_trans_code (code->block ? code->block->next : NULL);
6460 code->ext.omp_clauses->threads = 0;
6462 tree omp_clauses = gfc_trans_omp_clauses (NULL, code->ext.omp_clauses,
6463 code->loc);
6464 return build2_loc (input_location, OMP_ORDERED, void_type_node,
6465 code->block ? gfc_trans_code (code->block->next)
6466 : NULL_TREE, omp_clauses);
6469 static tree
6470 gfc_trans_omp_parallel (gfc_code *code)
6472 stmtblock_t block;
6473 tree stmt, omp_clauses;
6475 gfc_start_block (&block);
6476 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
6477 code->loc);
6478 pushlevel ();
6479 stmt = gfc_trans_omp_code (code->block->next, true);
6480 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6481 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
6482 omp_clauses);
6483 gfc_add_expr_to_block (&block, stmt);
6484 return gfc_finish_block (&block);
6487 enum
6489 GFC_OMP_SPLIT_SIMD,
6490 GFC_OMP_SPLIT_DO,
6491 GFC_OMP_SPLIT_PARALLEL,
6492 GFC_OMP_SPLIT_DISTRIBUTE,
6493 GFC_OMP_SPLIT_TEAMS,
6494 GFC_OMP_SPLIT_TARGET,
6495 GFC_OMP_SPLIT_TASKLOOP,
6496 GFC_OMP_SPLIT_MASKED,
6497 GFC_OMP_SPLIT_NUM
6500 enum
6502 GFC_OMP_MASK_SIMD = (1 << GFC_OMP_SPLIT_SIMD),
6503 GFC_OMP_MASK_DO = (1 << GFC_OMP_SPLIT_DO),
6504 GFC_OMP_MASK_PARALLEL = (1 << GFC_OMP_SPLIT_PARALLEL),
6505 GFC_OMP_MASK_DISTRIBUTE = (1 << GFC_OMP_SPLIT_DISTRIBUTE),
6506 GFC_OMP_MASK_TEAMS = (1 << GFC_OMP_SPLIT_TEAMS),
6507 GFC_OMP_MASK_TARGET = (1 << GFC_OMP_SPLIT_TARGET),
6508 GFC_OMP_MASK_TASKLOOP = (1 << GFC_OMP_SPLIT_TASKLOOP),
6509 GFC_OMP_MASK_MASKED = (1 << GFC_OMP_SPLIT_MASKED)
6512 /* If a var is in lastprivate/firstprivate/reduction but not in a
6513 data mapping/sharing clause, add it to 'map(tofrom:' if is_target
6514 and to 'shared' otherwise. */
6515 static void
6516 gfc_add_clause_implicitly (gfc_omp_clauses *clauses_out,
6517 gfc_omp_clauses *clauses_in,
6518 bool is_target, bool is_parallel_do)
6520 int clauselist_to_add = is_target ? OMP_LIST_MAP : OMP_LIST_SHARED;
6521 gfc_omp_namelist *tail = NULL;
6522 for (int i = 0; i < 5; ++i)
6524 gfc_omp_namelist *n;
6525 switch (i)
6527 case 0: n = clauses_in->lists[OMP_LIST_FIRSTPRIVATE]; break;
6528 case 1: n = clauses_in->lists[OMP_LIST_LASTPRIVATE]; break;
6529 case 2: n = clauses_in->lists[OMP_LIST_REDUCTION]; break;
6530 case 3: n = clauses_in->lists[OMP_LIST_REDUCTION_INSCAN]; break;
6531 case 4: n = clauses_in->lists[OMP_LIST_REDUCTION_TASK]; break;
6532 default: gcc_unreachable ();
6534 for (; n != NULL; n = n->next)
6536 gfc_omp_namelist *n2, **n_firstp = NULL, **n_lastp = NULL;
6537 for (int j = 0; j < 6; ++j)
6539 gfc_omp_namelist **n2ref = NULL, *prev2 = NULL;
6540 switch (j)
6542 case 0:
6543 n2ref = &clauses_out->lists[clauselist_to_add];
6544 break;
6545 case 1:
6546 n2ref = &clauses_out->lists[OMP_LIST_FIRSTPRIVATE];
6547 break;
6548 case 2:
6549 if (is_target)
6550 n2ref = &clauses_in->lists[OMP_LIST_LASTPRIVATE];
6551 else
6552 n2ref = &clauses_out->lists[OMP_LIST_LASTPRIVATE];
6553 break;
6554 case 3: n2ref = &clauses_out->lists[OMP_LIST_REDUCTION]; break;
6555 case 4:
6556 n2ref = &clauses_out->lists[OMP_LIST_REDUCTION_INSCAN];
6557 break;
6558 case 5:
6559 n2ref = &clauses_out->lists[OMP_LIST_REDUCTION_TASK];
6560 break;
6561 default: gcc_unreachable ();
6563 for (n2 = *n2ref; n2 != NULL; prev2 = n2, n2 = n2->next)
6564 if (n2->sym == n->sym)
6565 break;
6566 if (n2)
6568 if (j == 0 /* clauselist_to_add */)
6569 break; /* Already present. */
6570 if (j == 1 /* OMP_LIST_FIRSTPRIVATE */)
6572 n_firstp = prev2 ? &prev2->next : n2ref;
6573 continue;
6575 if (j == 2 /* OMP_LIST_LASTPRIVATE */)
6577 n_lastp = prev2 ? &prev2->next : n2ref;
6578 continue;
6580 break;
6583 if (n_firstp && n_lastp)
6585 /* For parallel do, GCC puts firstprivate/lastprivate
6586 on the parallel. */
6587 if (is_parallel_do)
6588 continue;
6589 *n_firstp = (*n_firstp)->next;
6590 if (!is_target)
6591 *n_lastp = (*n_lastp)->next;
6593 else if (is_target && n_lastp)
6595 else if (n2 || n_firstp || n_lastp)
6596 continue;
6597 if (clauses_out->lists[clauselist_to_add]
6598 && (clauses_out->lists[clauselist_to_add]
6599 == clauses_in->lists[clauselist_to_add]))
6601 gfc_omp_namelist *p = NULL;
6602 for (n2 = clauses_in->lists[clauselist_to_add]; n2; n2 = n2->next)
6604 if (p)
6606 p->next = gfc_get_omp_namelist ();
6607 p = p->next;
6609 else
6611 p = gfc_get_omp_namelist ();
6612 clauses_out->lists[clauselist_to_add] = p;
6614 *p = *n2;
6617 if (!tail)
6619 tail = clauses_out->lists[clauselist_to_add];
6620 for (; tail && tail->next; tail = tail->next)
6623 n2 = gfc_get_omp_namelist ();
6624 n2->where = n->where;
6625 n2->sym = n->sym;
6626 if (is_target)
6627 n2->u.map.op = OMP_MAP_TOFROM;
6628 if (tail)
6630 tail->next = n2;
6631 tail = n2;
6633 else
6634 clauses_out->lists[clauselist_to_add] = n2;
6639 /* Kind of opposite to above, add firstprivate to CLAUSES_OUT if it is mapped
6640 in CLAUSES_IN's FIRSTPRIVATE list but not its MAP list. */
6642 static void
6643 gfc_add_firstprivate_if_unmapped (gfc_omp_clauses *clauses_out,
6644 gfc_omp_clauses *clauses_in)
6646 gfc_omp_namelist *n = clauses_in->lists[OMP_LIST_FIRSTPRIVATE];
6647 gfc_omp_namelist **tail = NULL;
6649 for (; n != NULL; n = n->next)
6651 gfc_omp_namelist *n2 = clauses_out->lists[OMP_LIST_MAP];
6652 for (; n2 != NULL; n2 = n2->next)
6653 if (n->sym == n2->sym)
6654 break;
6655 if (n2 == NULL)
6657 gfc_omp_namelist *dup = gfc_get_omp_namelist ();
6658 *dup = *n;
6659 dup->next = NULL;
6660 if (!tail)
6662 tail = &clauses_out->lists[OMP_LIST_FIRSTPRIVATE];
6663 while (*tail && (*tail)->next)
6664 tail = &(*tail)->next;
6666 *tail = dup;
6667 tail = &(*tail)->next;
6672 static void
6673 gfc_free_split_omp_clauses (gfc_code *code, gfc_omp_clauses *clausesa)
6675 for (int i = 0; i < GFC_OMP_SPLIT_NUM; ++i)
6676 for (int j = 0; j < OMP_LIST_NUM; ++j)
6677 if (clausesa[i].lists[j] && clausesa[i].lists[j] != code->ext.omp_clauses->lists[j])
6678 for (gfc_omp_namelist *n = clausesa[i].lists[j]; n;)
6680 gfc_omp_namelist *p = n;
6681 n = n->next;
6682 free (p);
6686 static void
6687 gfc_split_omp_clauses (gfc_code *code,
6688 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM])
6690 int mask = 0, innermost = 0;
6691 bool is_loop = false;
6692 memset (clausesa, 0, GFC_OMP_SPLIT_NUM * sizeof (gfc_omp_clauses));
6693 switch (code->op)
6695 case EXEC_OMP_DISTRIBUTE:
6696 innermost = GFC_OMP_SPLIT_DISTRIBUTE;
6697 break;
6698 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
6699 mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
6700 innermost = GFC_OMP_SPLIT_DO;
6701 break;
6702 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
6703 mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL
6704 | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
6705 innermost = GFC_OMP_SPLIT_SIMD;
6706 break;
6707 case EXEC_OMP_DISTRIBUTE_SIMD:
6708 mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
6709 innermost = GFC_OMP_SPLIT_SIMD;
6710 break;
6711 case EXEC_OMP_DO:
6712 case EXEC_OMP_LOOP:
6713 innermost = GFC_OMP_SPLIT_DO;
6714 break;
6715 case EXEC_OMP_DO_SIMD:
6716 mask = GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
6717 innermost = GFC_OMP_SPLIT_SIMD;
6718 break;
6719 case EXEC_OMP_PARALLEL:
6720 innermost = GFC_OMP_SPLIT_PARALLEL;
6721 break;
6722 case EXEC_OMP_PARALLEL_DO:
6723 case EXEC_OMP_PARALLEL_LOOP:
6724 mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
6725 innermost = GFC_OMP_SPLIT_DO;
6726 break;
6727 case EXEC_OMP_PARALLEL_DO_SIMD:
6728 mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
6729 innermost = GFC_OMP_SPLIT_SIMD;
6730 break;
6731 case EXEC_OMP_PARALLEL_MASKED:
6732 mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_MASKED;
6733 innermost = GFC_OMP_SPLIT_MASKED;
6734 break;
6735 case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
6736 mask = (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_MASKED
6737 | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD);
6738 innermost = GFC_OMP_SPLIT_TASKLOOP;
6739 break;
6740 case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
6741 mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
6742 innermost = GFC_OMP_SPLIT_TASKLOOP;
6743 break;
6744 case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
6745 mask = (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_MASKED
6746 | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD);
6747 innermost = GFC_OMP_SPLIT_SIMD;
6748 break;
6749 case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
6750 mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
6751 innermost = GFC_OMP_SPLIT_SIMD;
6752 break;
6753 case EXEC_OMP_SIMD:
6754 innermost = GFC_OMP_SPLIT_SIMD;
6755 break;
6756 case EXEC_OMP_TARGET:
6757 innermost = GFC_OMP_SPLIT_TARGET;
6758 break;
6759 case EXEC_OMP_TARGET_PARALLEL:
6760 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL;
6761 innermost = GFC_OMP_SPLIT_PARALLEL;
6762 break;
6763 case EXEC_OMP_TARGET_PARALLEL_DO:
6764 case EXEC_OMP_TARGET_PARALLEL_LOOP:
6765 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
6766 innermost = GFC_OMP_SPLIT_DO;
6767 break;
6768 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
6769 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO
6770 | GFC_OMP_MASK_SIMD;
6771 innermost = GFC_OMP_SPLIT_SIMD;
6772 break;
6773 case EXEC_OMP_TARGET_SIMD:
6774 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_SIMD;
6775 innermost = GFC_OMP_SPLIT_SIMD;
6776 break;
6777 case EXEC_OMP_TARGET_TEAMS:
6778 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS;
6779 innermost = GFC_OMP_SPLIT_TEAMS;
6780 break;
6781 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
6782 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS
6783 | GFC_OMP_MASK_DISTRIBUTE;
6784 innermost = GFC_OMP_SPLIT_DISTRIBUTE;
6785 break;
6786 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
6787 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
6788 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
6789 innermost = GFC_OMP_SPLIT_DO;
6790 break;
6791 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
6792 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
6793 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
6794 innermost = GFC_OMP_SPLIT_SIMD;
6795 break;
6796 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
6797 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS
6798 | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
6799 innermost = GFC_OMP_SPLIT_SIMD;
6800 break;
6801 case EXEC_OMP_TARGET_TEAMS_LOOP:
6802 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DO;
6803 innermost = GFC_OMP_SPLIT_DO;
6804 break;
6805 case EXEC_OMP_MASKED_TASKLOOP:
6806 mask = GFC_OMP_MASK_MASKED | GFC_OMP_MASK_TASKLOOP;
6807 innermost = GFC_OMP_SPLIT_TASKLOOP;
6808 break;
6809 case EXEC_OMP_MASTER_TASKLOOP:
6810 case EXEC_OMP_TASKLOOP:
6811 innermost = GFC_OMP_SPLIT_TASKLOOP;
6812 break;
6813 case EXEC_OMP_MASKED_TASKLOOP_SIMD:
6814 mask = GFC_OMP_MASK_MASKED | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
6815 innermost = GFC_OMP_SPLIT_SIMD;
6816 break;
6817 case EXEC_OMP_MASTER_TASKLOOP_SIMD:
6818 case EXEC_OMP_TASKLOOP_SIMD:
6819 mask = GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
6820 innermost = GFC_OMP_SPLIT_SIMD;
6821 break;
6822 case EXEC_OMP_TEAMS:
6823 innermost = GFC_OMP_SPLIT_TEAMS;
6824 break;
6825 case EXEC_OMP_TEAMS_DISTRIBUTE:
6826 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE;
6827 innermost = GFC_OMP_SPLIT_DISTRIBUTE;
6828 break;
6829 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
6830 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
6831 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
6832 innermost = GFC_OMP_SPLIT_DO;
6833 break;
6834 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
6835 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
6836 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
6837 innermost = GFC_OMP_SPLIT_SIMD;
6838 break;
6839 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
6840 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
6841 innermost = GFC_OMP_SPLIT_SIMD;
6842 break;
6843 case EXEC_OMP_TEAMS_LOOP:
6844 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DO;
6845 innermost = GFC_OMP_SPLIT_DO;
6846 break;
6847 default:
6848 gcc_unreachable ();
6850 if (mask == 0)
6852 clausesa[innermost] = *code->ext.omp_clauses;
6853 return;
6855 /* Loops are similar to DO but still a bit different. */
6856 switch (code->op)
6858 case EXEC_OMP_LOOP:
6859 case EXEC_OMP_PARALLEL_LOOP:
6860 case EXEC_OMP_TEAMS_LOOP:
6861 case EXEC_OMP_TARGET_PARALLEL_LOOP:
6862 case EXEC_OMP_TARGET_TEAMS_LOOP:
6863 is_loop = true;
6864 default:
6865 break;
6867 if (code->ext.omp_clauses != NULL)
6869 if (mask & GFC_OMP_MASK_TARGET)
6871 /* First the clauses that are unique to some constructs. */
6872 clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_MAP]
6873 = code->ext.omp_clauses->lists[OMP_LIST_MAP];
6874 clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_IS_DEVICE_PTR]
6875 = code->ext.omp_clauses->lists[OMP_LIST_IS_DEVICE_PTR];
6876 clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_HAS_DEVICE_ADDR]
6877 = code->ext.omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR];
6878 clausesa[GFC_OMP_SPLIT_TARGET].device
6879 = code->ext.omp_clauses->device;
6880 clausesa[GFC_OMP_SPLIT_TARGET].thread_limit
6881 = code->ext.omp_clauses->thread_limit;
6882 clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_USES_ALLOCATORS]
6883 = code->ext.omp_clauses->lists[OMP_LIST_USES_ALLOCATORS];
6884 for (int i = 0; i < OMP_DEFAULTMAP_CAT_NUM; i++)
6885 clausesa[GFC_OMP_SPLIT_TARGET].defaultmap[i]
6886 = code->ext.omp_clauses->defaultmap[i];
6887 clausesa[GFC_OMP_SPLIT_TARGET].if_exprs[OMP_IF_TARGET]
6888 = code->ext.omp_clauses->if_exprs[OMP_IF_TARGET];
6889 /* And this is copied to all. */
6890 clausesa[GFC_OMP_SPLIT_TARGET].if_expr
6891 = code->ext.omp_clauses->if_expr;
6892 clausesa[GFC_OMP_SPLIT_TARGET].nowait
6893 = code->ext.omp_clauses->nowait;
6895 if (mask & GFC_OMP_MASK_TEAMS)
6897 /* First the clauses that are unique to some constructs. */
6898 clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_lower
6899 = code->ext.omp_clauses->num_teams_lower;
6900 clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper
6901 = code->ext.omp_clauses->num_teams_upper;
6902 clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit
6903 = code->ext.omp_clauses->thread_limit;
6904 /* Shared and default clauses are allowed on parallel, teams
6905 and taskloop. */
6906 clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_SHARED]
6907 = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
6908 clausesa[GFC_OMP_SPLIT_TEAMS].default_sharing
6909 = code->ext.omp_clauses->default_sharing;
6911 if (mask & GFC_OMP_MASK_DISTRIBUTE)
6913 /* First the clauses that are unique to some constructs. */
6914 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_sched_kind
6915 = code->ext.omp_clauses->dist_sched_kind;
6916 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_chunk_size
6917 = code->ext.omp_clauses->dist_chunk_size;
6918 /* Duplicate collapse. */
6919 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].collapse
6920 = code->ext.omp_clauses->collapse;
6921 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_concurrent
6922 = code->ext.omp_clauses->order_concurrent;
6923 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_unconstrained
6924 = code->ext.omp_clauses->order_unconstrained;
6925 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_reproducible
6926 = code->ext.omp_clauses->order_reproducible;
6928 if (mask & GFC_OMP_MASK_PARALLEL)
6930 /* First the clauses that are unique to some constructs. */
6931 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_COPYIN]
6932 = code->ext.omp_clauses->lists[OMP_LIST_COPYIN];
6933 clausesa[GFC_OMP_SPLIT_PARALLEL].num_threads
6934 = code->ext.omp_clauses->num_threads;
6935 clausesa[GFC_OMP_SPLIT_PARALLEL].proc_bind
6936 = code->ext.omp_clauses->proc_bind;
6937 /* Shared and default clauses are allowed on parallel, teams
6938 and taskloop. */
6939 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_SHARED]
6940 = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
6941 clausesa[GFC_OMP_SPLIT_PARALLEL].default_sharing
6942 = code->ext.omp_clauses->default_sharing;
6943 clausesa[GFC_OMP_SPLIT_PARALLEL].if_exprs[OMP_IF_PARALLEL]
6944 = code->ext.omp_clauses->if_exprs[OMP_IF_PARALLEL];
6945 /* And this is copied to all. */
6946 clausesa[GFC_OMP_SPLIT_PARALLEL].if_expr
6947 = code->ext.omp_clauses->if_expr;
6949 if (mask & GFC_OMP_MASK_MASKED)
6950 clausesa[GFC_OMP_SPLIT_MASKED].filter = code->ext.omp_clauses->filter;
6951 if ((mask & GFC_OMP_MASK_DO) && !is_loop)
6953 /* First the clauses that are unique to some constructs. */
6954 clausesa[GFC_OMP_SPLIT_DO].ordered
6955 = code->ext.omp_clauses->ordered;
6956 clausesa[GFC_OMP_SPLIT_DO].orderedc
6957 = code->ext.omp_clauses->orderedc;
6958 clausesa[GFC_OMP_SPLIT_DO].sched_kind
6959 = code->ext.omp_clauses->sched_kind;
6960 if (innermost == GFC_OMP_SPLIT_SIMD)
6961 clausesa[GFC_OMP_SPLIT_DO].sched_simd
6962 = code->ext.omp_clauses->sched_simd;
6963 clausesa[GFC_OMP_SPLIT_DO].sched_monotonic
6964 = code->ext.omp_clauses->sched_monotonic;
6965 clausesa[GFC_OMP_SPLIT_DO].sched_nonmonotonic
6966 = code->ext.omp_clauses->sched_nonmonotonic;
6967 clausesa[GFC_OMP_SPLIT_DO].chunk_size
6968 = code->ext.omp_clauses->chunk_size;
6969 clausesa[GFC_OMP_SPLIT_DO].nowait
6970 = code->ext.omp_clauses->nowait;
6972 if (mask & GFC_OMP_MASK_DO)
6974 clausesa[GFC_OMP_SPLIT_DO].bind
6975 = code->ext.omp_clauses->bind;
6976 /* Duplicate collapse. */
6977 clausesa[GFC_OMP_SPLIT_DO].collapse
6978 = code->ext.omp_clauses->collapse;
6979 clausesa[GFC_OMP_SPLIT_DO].order_concurrent
6980 = code->ext.omp_clauses->order_concurrent;
6981 clausesa[GFC_OMP_SPLIT_DO].order_unconstrained
6982 = code->ext.omp_clauses->order_unconstrained;
6983 clausesa[GFC_OMP_SPLIT_DO].order_reproducible
6984 = code->ext.omp_clauses->order_reproducible;
6986 if (mask & GFC_OMP_MASK_SIMD)
6988 clausesa[GFC_OMP_SPLIT_SIMD].safelen_expr
6989 = code->ext.omp_clauses->safelen_expr;
6990 clausesa[GFC_OMP_SPLIT_SIMD].simdlen_expr
6991 = code->ext.omp_clauses->simdlen_expr;
6992 clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_ALIGNED]
6993 = code->ext.omp_clauses->lists[OMP_LIST_ALIGNED];
6994 /* Duplicate collapse. */
6995 clausesa[GFC_OMP_SPLIT_SIMD].collapse
6996 = code->ext.omp_clauses->collapse;
6997 clausesa[GFC_OMP_SPLIT_SIMD].if_exprs[OMP_IF_SIMD]
6998 = code->ext.omp_clauses->if_exprs[OMP_IF_SIMD];
6999 clausesa[GFC_OMP_SPLIT_SIMD].order_concurrent
7000 = code->ext.omp_clauses->order_concurrent;
7001 clausesa[GFC_OMP_SPLIT_SIMD].order_unconstrained
7002 = code->ext.omp_clauses->order_unconstrained;
7003 clausesa[GFC_OMP_SPLIT_SIMD].order_reproducible
7004 = code->ext.omp_clauses->order_reproducible;
7005 /* And this is copied to all. */
7006 clausesa[GFC_OMP_SPLIT_SIMD].if_expr
7007 = code->ext.omp_clauses->if_expr;
7009 if (mask & GFC_OMP_MASK_TASKLOOP)
7011 /* First the clauses that are unique to some constructs. */
7012 clausesa[GFC_OMP_SPLIT_TASKLOOP].nogroup
7013 = code->ext.omp_clauses->nogroup;
7014 clausesa[GFC_OMP_SPLIT_TASKLOOP].grainsize
7015 = code->ext.omp_clauses->grainsize;
7016 clausesa[GFC_OMP_SPLIT_TASKLOOP].grainsize_strict
7017 = code->ext.omp_clauses->grainsize_strict;
7018 clausesa[GFC_OMP_SPLIT_TASKLOOP].num_tasks
7019 = code->ext.omp_clauses->num_tasks;
7020 clausesa[GFC_OMP_SPLIT_TASKLOOP].num_tasks_strict
7021 = code->ext.omp_clauses->num_tasks_strict;
7022 clausesa[GFC_OMP_SPLIT_TASKLOOP].priority
7023 = code->ext.omp_clauses->priority;
7024 clausesa[GFC_OMP_SPLIT_TASKLOOP].final_expr
7025 = code->ext.omp_clauses->final_expr;
7026 clausesa[GFC_OMP_SPLIT_TASKLOOP].untied
7027 = code->ext.omp_clauses->untied;
7028 clausesa[GFC_OMP_SPLIT_TASKLOOP].mergeable
7029 = code->ext.omp_clauses->mergeable;
7030 clausesa[GFC_OMP_SPLIT_TASKLOOP].if_exprs[OMP_IF_TASKLOOP]
7031 = code->ext.omp_clauses->if_exprs[OMP_IF_TASKLOOP];
7032 /* And this is copied to all. */
7033 clausesa[GFC_OMP_SPLIT_TASKLOOP].if_expr
7034 = code->ext.omp_clauses->if_expr;
7035 /* Shared and default clauses are allowed on parallel, teams
7036 and taskloop. */
7037 clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_SHARED]
7038 = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
7039 clausesa[GFC_OMP_SPLIT_TASKLOOP].default_sharing
7040 = code->ext.omp_clauses->default_sharing;
7041 /* Duplicate collapse. */
7042 clausesa[GFC_OMP_SPLIT_TASKLOOP].collapse
7043 = code->ext.omp_clauses->collapse;
7045 /* Private clause is supported on all constructs but master/masked,
7046 it is enough to put it on the innermost one except for master/masked. For
7047 !$ omp parallel do put it on parallel though,
7048 as that's what we did for OpenMP 3.1. */
7049 clausesa[((innermost == GFC_OMP_SPLIT_DO && !is_loop)
7050 || code->op == EXEC_OMP_PARALLEL_MASTER
7051 || code->op == EXEC_OMP_PARALLEL_MASKED)
7052 ? (int) GFC_OMP_SPLIT_PARALLEL
7053 : innermost].lists[OMP_LIST_PRIVATE]
7054 = code->ext.omp_clauses->lists[OMP_LIST_PRIVATE];
7055 /* Firstprivate clause is supported on all constructs but
7056 simd and masked/master. Put it on the outermost of those and duplicate
7057 on parallel and teams. */
7058 if (mask & GFC_OMP_MASK_TARGET)
7059 gfc_add_firstprivate_if_unmapped (&clausesa[GFC_OMP_SPLIT_TARGET],
7060 code->ext.omp_clauses);
7061 if (mask & GFC_OMP_MASK_TEAMS)
7062 clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_FIRSTPRIVATE]
7063 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
7064 else if (mask & GFC_OMP_MASK_DISTRIBUTE)
7065 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_FIRSTPRIVATE]
7066 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
7067 if (mask & GFC_OMP_MASK_TASKLOOP)
7068 clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_FIRSTPRIVATE]
7069 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
7070 if ((mask & GFC_OMP_MASK_PARALLEL)
7071 && !(mask & GFC_OMP_MASK_TASKLOOP))
7072 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_FIRSTPRIVATE]
7073 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
7074 else if ((mask & GFC_OMP_MASK_DO) && !is_loop)
7075 clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_FIRSTPRIVATE]
7076 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
7077 /* Lastprivate is allowed on distribute, do, simd, taskloop and loop.
7078 In parallel do{, simd} we actually want to put it on
7079 parallel rather than do. */
7080 if (mask & GFC_OMP_MASK_DISTRIBUTE)
7081 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_LASTPRIVATE]
7082 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
7083 if (mask & GFC_OMP_MASK_TASKLOOP)
7084 clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_LASTPRIVATE]
7085 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
7086 if ((mask & GFC_OMP_MASK_PARALLEL) && !is_loop
7087 && !(mask & GFC_OMP_MASK_TASKLOOP))
7088 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_LASTPRIVATE]
7089 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
7090 else if (mask & GFC_OMP_MASK_DO)
7091 clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_LASTPRIVATE]
7092 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
7093 if (mask & GFC_OMP_MASK_SIMD)
7094 clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_LASTPRIVATE]
7095 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
7096 /* Reduction is allowed on simd, do, parallel, teams, taskloop, and loop.
7097 Duplicate it on all of them, but
7098 - omit on do if parallel is present;
7099 - omit on task and parallel if loop is present;
7100 additionally, inscan applies to do/simd only. */
7101 for (int i = OMP_LIST_REDUCTION; i <= OMP_LIST_REDUCTION_TASK; i++)
7103 if (mask & GFC_OMP_MASK_TASKLOOP
7104 && i != OMP_LIST_REDUCTION_INSCAN)
7105 clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[i]
7106 = code->ext.omp_clauses->lists[i];
7107 if (mask & GFC_OMP_MASK_TEAMS
7108 && i != OMP_LIST_REDUCTION_INSCAN
7109 && !is_loop)
7110 clausesa[GFC_OMP_SPLIT_TEAMS].lists[i]
7111 = code->ext.omp_clauses->lists[i];
7112 if (mask & GFC_OMP_MASK_PARALLEL
7113 && i != OMP_LIST_REDUCTION_INSCAN
7114 && !(mask & GFC_OMP_MASK_TASKLOOP)
7115 && !is_loop)
7116 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[i]
7117 = code->ext.omp_clauses->lists[i];
7118 else if (mask & GFC_OMP_MASK_DO)
7119 clausesa[GFC_OMP_SPLIT_DO].lists[i]
7120 = code->ext.omp_clauses->lists[i];
7121 if (mask & GFC_OMP_MASK_SIMD)
7122 clausesa[GFC_OMP_SPLIT_SIMD].lists[i]
7123 = code->ext.omp_clauses->lists[i];
7125 if (mask & GFC_OMP_MASK_TARGET)
7126 clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_IN_REDUCTION]
7127 = code->ext.omp_clauses->lists[OMP_LIST_IN_REDUCTION];
7128 if (mask & GFC_OMP_MASK_TASKLOOP)
7129 clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_IN_REDUCTION]
7130 = code->ext.omp_clauses->lists[OMP_LIST_IN_REDUCTION];
7131 /* Linear clause is supported on do and simd,
7132 put it on the innermost one. */
7133 clausesa[innermost].lists[OMP_LIST_LINEAR]
7134 = code->ext.omp_clauses->lists[OMP_LIST_LINEAR];
7136 /* Propagate firstprivate/lastprivate/reduction vars to
7137 shared (parallel, teams) and map-tofrom (target). */
7138 if (mask & GFC_OMP_MASK_TARGET)
7139 gfc_add_clause_implicitly (&clausesa[GFC_OMP_SPLIT_TARGET],
7140 code->ext.omp_clauses, true, false);
7141 if ((mask & GFC_OMP_MASK_PARALLEL) && innermost != GFC_OMP_MASK_PARALLEL)
7142 gfc_add_clause_implicitly (&clausesa[GFC_OMP_SPLIT_PARALLEL],
7143 code->ext.omp_clauses, false,
7144 mask & GFC_OMP_MASK_DO);
7145 if (mask & GFC_OMP_MASK_TEAMS && innermost != GFC_OMP_MASK_TEAMS)
7146 gfc_add_clause_implicitly (&clausesa[GFC_OMP_SPLIT_TEAMS],
7147 code->ext.omp_clauses, false, false);
7148 if (((mask & (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
7149 == (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
7150 && !is_loop)
7151 clausesa[GFC_OMP_SPLIT_DO].nowait = true;
7153 /* Distribute allocate clause to do, parallel, distribute, teams, target
7154 and taskloop. The code below iterates over variables in the
7155 allocate list and checks if that available is also in any
7156 privatization clause on those construct. If yes, then we add it
7157 to the list of 'allocate'ed variables for that construct. If a
7158 variable is found in none of them then we issue an error. */
7160 if (code->ext.omp_clauses->lists[OMP_LIST_ALLOCATE])
7162 gfc_omp_namelist *alloc_nl, *priv_nl;
7163 gfc_omp_namelist *tails[GFC_OMP_SPLIT_NUM];
7164 for (alloc_nl = code->ext.omp_clauses->lists[OMP_LIST_ALLOCATE];
7165 alloc_nl; alloc_nl = alloc_nl->next)
7167 bool found = false;
7168 for (int i = GFC_OMP_SPLIT_DO; i <= GFC_OMP_SPLIT_TASKLOOP; i++)
7170 gfc_omp_namelist *p;
7171 int list;
7172 for (list = 0; list < OMP_LIST_NUM; list++)
7174 switch (list)
7176 case OMP_LIST_PRIVATE:
7177 case OMP_LIST_FIRSTPRIVATE:
7178 case OMP_LIST_LASTPRIVATE:
7179 case OMP_LIST_REDUCTION:
7180 case OMP_LIST_REDUCTION_INSCAN:
7181 case OMP_LIST_REDUCTION_TASK:
7182 case OMP_LIST_IN_REDUCTION:
7183 case OMP_LIST_TASK_REDUCTION:
7184 case OMP_LIST_LINEAR:
7185 for (priv_nl = clausesa[i].lists[list]; priv_nl;
7186 priv_nl = priv_nl->next)
7187 if (alloc_nl->sym == priv_nl->sym)
7189 found = true;
7190 p = gfc_get_omp_namelist ();
7191 p->sym = alloc_nl->sym;
7192 p->expr = alloc_nl->expr;
7193 p->u.align = alloc_nl->u.align;
7194 p->u2.allocator = alloc_nl->u2.allocator;
7195 p->where = alloc_nl->where;
7196 if (clausesa[i].lists[OMP_LIST_ALLOCATE] == NULL)
7198 clausesa[i].lists[OMP_LIST_ALLOCATE] = p;
7199 tails[i] = p;
7201 else
7203 tails[i]->next = p;
7204 tails[i] = tails[i]->next;
7207 break;
7208 default:
7209 break;
7213 if (!found)
7214 gfc_error ("%qs specified in 'allocate' clause at %L but not "
7215 "in an explicit privatization clause",
7216 alloc_nl->sym->name, &alloc_nl->where);
7221 static tree
7222 gfc_trans_omp_do_simd (gfc_code *code, stmtblock_t *pblock,
7223 gfc_omp_clauses *clausesa, tree omp_clauses)
7225 stmtblock_t block;
7226 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
7227 tree stmt, body, omp_do_clauses = NULL_TREE;
7228 bool free_clausesa = false;
7230 if (pblock == NULL)
7231 gfc_start_block (&block);
7232 else
7233 gfc_init_block (&block);
7235 if (clausesa == NULL)
7237 clausesa = clausesa_buf;
7238 gfc_split_omp_clauses (code, clausesa);
7239 free_clausesa = true;
7241 if (flag_openmp)
7242 omp_do_clauses
7243 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DO], code->loc);
7244 body = gfc_trans_omp_do (code, EXEC_OMP_SIMD, pblock ? pblock : &block,
7245 &clausesa[GFC_OMP_SPLIT_SIMD], omp_clauses);
7246 if (pblock == NULL)
7248 if (TREE_CODE (body) != BIND_EXPR)
7249 body = build3_v (BIND_EXPR, NULL, body, poplevel (1, 0));
7250 else
7251 poplevel (0, 0);
7253 else if (TREE_CODE (body) != BIND_EXPR)
7254 body = build3_v (BIND_EXPR, NULL, body, NULL_TREE);
7255 if (flag_openmp)
7257 stmt = make_node (OMP_FOR);
7258 SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
7259 TREE_TYPE (stmt) = void_type_node;
7260 OMP_FOR_BODY (stmt) = body;
7261 OMP_FOR_CLAUSES (stmt) = omp_do_clauses;
7263 else
7264 stmt = body;
7265 gfc_add_expr_to_block (&block, stmt);
7266 if (free_clausesa)
7267 gfc_free_split_omp_clauses (code, clausesa);
7268 return gfc_finish_block (&block);
7271 static tree
7272 gfc_trans_omp_parallel_do (gfc_code *code, bool is_loop, stmtblock_t *pblock,
7273 gfc_omp_clauses *clausesa)
7275 stmtblock_t block, *new_pblock = pblock;
7276 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
7277 tree stmt, omp_clauses = NULL_TREE;
7278 bool free_clausesa = false;
7280 if (pblock == NULL)
7281 gfc_start_block (&block);
7282 else
7283 gfc_init_block (&block);
7285 if (clausesa == NULL)
7287 clausesa = clausesa_buf;
7288 gfc_split_omp_clauses (code, clausesa);
7289 free_clausesa = true;
7291 omp_clauses
7292 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
7293 code->loc);
7294 if (pblock == NULL)
7296 if (!clausesa[GFC_OMP_SPLIT_DO].ordered
7297 && clausesa[GFC_OMP_SPLIT_DO].sched_kind != OMP_SCHED_STATIC)
7298 new_pblock = &block;
7299 else
7300 pushlevel ();
7302 stmt = gfc_trans_omp_do (code, is_loop ? EXEC_OMP_LOOP : EXEC_OMP_DO,
7303 new_pblock, &clausesa[GFC_OMP_SPLIT_DO],
7304 omp_clauses);
7305 if (pblock == NULL)
7307 if (TREE_CODE (stmt) != BIND_EXPR)
7308 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7309 else
7310 poplevel (0, 0);
7312 else if (TREE_CODE (stmt) != BIND_EXPR)
7313 stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
7314 stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
7315 void_type_node, stmt, omp_clauses);
7316 OMP_PARALLEL_COMBINED (stmt) = 1;
7317 gfc_add_expr_to_block (&block, stmt);
7318 if (free_clausesa)
7319 gfc_free_split_omp_clauses (code, clausesa);
7320 return gfc_finish_block (&block);
7323 static tree
7324 gfc_trans_omp_parallel_do_simd (gfc_code *code, stmtblock_t *pblock,
7325 gfc_omp_clauses *clausesa)
7327 stmtblock_t block;
7328 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
7329 tree stmt, omp_clauses = NULL_TREE;
7330 bool free_clausesa = false;
7332 if (pblock == NULL)
7333 gfc_start_block (&block);
7334 else
7335 gfc_init_block (&block);
7337 if (clausesa == NULL)
7339 clausesa = clausesa_buf;
7340 gfc_split_omp_clauses (code, clausesa);
7341 free_clausesa = true;
7343 if (flag_openmp)
7344 omp_clauses
7345 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
7346 code->loc);
7347 if (pblock == NULL)
7348 pushlevel ();
7349 stmt = gfc_trans_omp_do_simd (code, pblock, clausesa, omp_clauses);
7350 if (pblock == NULL)
7352 if (TREE_CODE (stmt) != BIND_EXPR)
7353 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7354 else
7355 poplevel (0, 0);
7357 else if (TREE_CODE (stmt) != BIND_EXPR)
7358 stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
7359 if (flag_openmp)
7361 stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
7362 void_type_node, stmt, omp_clauses);
7363 OMP_PARALLEL_COMBINED (stmt) = 1;
7365 gfc_add_expr_to_block (&block, stmt);
7366 if (free_clausesa)
7367 gfc_free_split_omp_clauses (code, clausesa);
7368 return gfc_finish_block (&block);
7371 static tree
7372 gfc_trans_omp_parallel_sections (gfc_code *code)
7374 stmtblock_t block;
7375 gfc_omp_clauses section_clauses;
7376 tree stmt, omp_clauses;
7378 memset (&section_clauses, 0, sizeof (section_clauses));
7379 section_clauses.nowait = true;
7381 gfc_start_block (&block);
7382 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
7383 code->loc);
7384 pushlevel ();
7385 stmt = gfc_trans_omp_sections (code, &section_clauses);
7386 if (TREE_CODE (stmt) != BIND_EXPR)
7387 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7388 else
7389 poplevel (0, 0);
7390 stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
7391 void_type_node, stmt, omp_clauses);
7392 OMP_PARALLEL_COMBINED (stmt) = 1;
7393 gfc_add_expr_to_block (&block, stmt);
7394 return gfc_finish_block (&block);
7397 static tree
7398 gfc_trans_omp_parallel_workshare (gfc_code *code)
7400 stmtblock_t block;
7401 gfc_omp_clauses workshare_clauses;
7402 tree stmt, omp_clauses;
7404 memset (&workshare_clauses, 0, sizeof (workshare_clauses));
7405 workshare_clauses.nowait = true;
7407 gfc_start_block (&block);
7408 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
7409 code->loc);
7410 pushlevel ();
7411 stmt = gfc_trans_omp_workshare (code, &workshare_clauses);
7412 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7413 stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
7414 void_type_node, stmt, omp_clauses);
7415 OMP_PARALLEL_COMBINED (stmt) = 1;
7416 gfc_add_expr_to_block (&block, stmt);
7417 return gfc_finish_block (&block);
7420 static tree
7421 gfc_trans_omp_scope (gfc_code *code)
7423 stmtblock_t block;
7424 tree body = gfc_trans_code (code->block->next);
7425 if (IS_EMPTY_STMT (body))
7426 return body;
7427 gfc_start_block (&block);
7428 tree omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
7429 code->loc);
7430 tree stmt = make_node (OMP_SCOPE);
7431 SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
7432 TREE_TYPE (stmt) = void_type_node;
7433 OMP_SCOPE_BODY (stmt) = body;
7434 OMP_SCOPE_CLAUSES (stmt) = omp_clauses;
7435 gfc_add_expr_to_block (&block, stmt);
7436 return gfc_finish_block (&block);
7439 static tree
7440 gfc_trans_omp_sections (gfc_code *code, gfc_omp_clauses *clauses)
7442 stmtblock_t block, body;
7443 tree omp_clauses, stmt;
7444 bool has_lastprivate = clauses->lists[OMP_LIST_LASTPRIVATE] != NULL;
7445 location_t loc = gfc_get_location (&code->loc);
7447 gfc_start_block (&block);
7449 omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
7451 gfc_init_block (&body);
7452 for (code = code->block; code; code = code->block)
7454 /* Last section is special because of lastprivate, so even if it
7455 is empty, chain it in. */
7456 stmt = gfc_trans_omp_code (code->next,
7457 has_lastprivate && code->block == NULL);
7458 if (! IS_EMPTY_STMT (stmt))
7460 stmt = build1_v (OMP_SECTION, stmt);
7461 gfc_add_expr_to_block (&body, stmt);
7464 stmt = gfc_finish_block (&body);
7466 stmt = build2_loc (loc, OMP_SECTIONS, void_type_node, stmt, omp_clauses);
7467 gfc_add_expr_to_block (&block, stmt);
7469 return gfc_finish_block (&block);
7472 static tree
7473 gfc_trans_omp_single (gfc_code *code, gfc_omp_clauses *clauses)
7475 stmtblock_t block;
7476 gfc_start_block (&block);
7477 tree omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
7478 tree stmt = gfc_trans_omp_code (code->block->next, true);
7479 stmt = build2_loc (gfc_get_location (&code->loc), OMP_SINGLE, void_type_node,
7480 stmt, omp_clauses);
7481 gfc_add_expr_to_block (&block, stmt);
7482 return gfc_finish_block (&block);
7485 static tree
7486 gfc_trans_omp_task (gfc_code *code)
7488 stmtblock_t block;
7489 tree stmt, omp_clauses;
7491 gfc_start_block (&block);
7492 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
7493 code->loc);
7494 pushlevel ();
7495 stmt = gfc_trans_omp_code (code->block->next, true);
7496 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7497 stmt = build2_loc (gfc_get_location (&code->loc), OMP_TASK, void_type_node,
7498 stmt, omp_clauses);
7499 gfc_add_expr_to_block (&block, stmt);
7500 return gfc_finish_block (&block);
7503 static tree
7504 gfc_trans_omp_taskgroup (gfc_code *code)
7506 stmtblock_t block;
7507 gfc_start_block (&block);
7508 tree body = gfc_trans_code (code->block->next);
7509 tree stmt = make_node (OMP_TASKGROUP);
7510 SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
7511 TREE_TYPE (stmt) = void_type_node;
7512 OMP_TASKGROUP_BODY (stmt) = body;
7513 OMP_TASKGROUP_CLAUSES (stmt) = gfc_trans_omp_clauses (&block,
7514 code->ext.omp_clauses,
7515 code->loc);
7516 gfc_add_expr_to_block (&block, stmt);
7517 return gfc_finish_block (&block);
7520 static tree
7521 gfc_trans_omp_taskwait (gfc_code *code)
7523 if (!code->ext.omp_clauses)
7525 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
7526 return build_call_expr_loc (input_location, decl, 0);
7528 stmtblock_t block;
7529 gfc_start_block (&block);
7530 tree stmt = make_node (OMP_TASK);
7531 SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
7532 TREE_TYPE (stmt) = void_type_node;
7533 OMP_TASK_BODY (stmt) = NULL_TREE;
7534 OMP_TASK_CLAUSES (stmt) = gfc_trans_omp_clauses (&block,
7535 code->ext.omp_clauses,
7536 code->loc);
7537 gfc_add_expr_to_block (&block, stmt);
7538 return gfc_finish_block (&block);
7541 static tree
7542 gfc_trans_omp_taskyield (void)
7544 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
7545 return build_call_expr_loc (input_location, decl, 0);
7548 static tree
7549 gfc_trans_omp_distribute (gfc_code *code, gfc_omp_clauses *clausesa)
7551 stmtblock_t block;
7552 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
7553 tree stmt, omp_clauses = NULL_TREE;
7554 bool free_clausesa = false;
7556 gfc_start_block (&block);
7557 if (clausesa == NULL)
7559 clausesa = clausesa_buf;
7560 gfc_split_omp_clauses (code, clausesa);
7561 free_clausesa = true;
7563 if (flag_openmp)
7564 omp_clauses
7565 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
7566 code->loc);
7567 switch (code->op)
7569 case EXEC_OMP_DISTRIBUTE:
7570 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
7571 case EXEC_OMP_TEAMS_DISTRIBUTE:
7572 /* This is handled in gfc_trans_omp_do. */
7573 gcc_unreachable ();
7574 break;
7575 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
7576 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
7577 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
7578 stmt = gfc_trans_omp_parallel_do (code, false, &block, clausesa);
7579 if (TREE_CODE (stmt) != BIND_EXPR)
7580 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7581 else
7582 poplevel (0, 0);
7583 break;
7584 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
7585 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
7586 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
7587 stmt = gfc_trans_omp_parallel_do_simd (code, &block, clausesa);
7588 if (TREE_CODE (stmt) != BIND_EXPR)
7589 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7590 else
7591 poplevel (0, 0);
7592 break;
7593 case EXEC_OMP_DISTRIBUTE_SIMD:
7594 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
7595 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
7596 stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
7597 &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
7598 if (TREE_CODE (stmt) != BIND_EXPR)
7599 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7600 else
7601 poplevel (0, 0);
7602 break;
7603 default:
7604 gcc_unreachable ();
7606 if (flag_openmp)
7608 tree distribute = make_node (OMP_DISTRIBUTE);
7609 SET_EXPR_LOCATION (distribute, gfc_get_location (&code->loc));
7610 TREE_TYPE (distribute) = void_type_node;
7611 OMP_FOR_BODY (distribute) = stmt;
7612 OMP_FOR_CLAUSES (distribute) = omp_clauses;
7613 stmt = distribute;
7615 gfc_add_expr_to_block (&block, stmt);
7616 if (free_clausesa)
7617 gfc_free_split_omp_clauses (code, clausesa);
7618 return gfc_finish_block (&block);
7621 static tree
7622 gfc_trans_omp_teams (gfc_code *code, gfc_omp_clauses *clausesa,
7623 tree omp_clauses)
7625 stmtblock_t block;
7626 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
7627 tree stmt;
7628 bool combined = true, free_clausesa = false;
7630 gfc_start_block (&block);
7631 if (clausesa == NULL)
7633 clausesa = clausesa_buf;
7634 gfc_split_omp_clauses (code, clausesa);
7635 free_clausesa = true;
7637 if (flag_openmp)
7639 omp_clauses
7640 = chainon (omp_clauses,
7641 gfc_trans_omp_clauses (&block,
7642 &clausesa[GFC_OMP_SPLIT_TEAMS],
7643 code->loc));
7644 pushlevel ();
7646 switch (code->op)
7648 case EXEC_OMP_TARGET_TEAMS:
7649 case EXEC_OMP_TEAMS:
7650 stmt = gfc_trans_omp_code (code->block->next, true);
7651 combined = false;
7652 break;
7653 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
7654 case EXEC_OMP_TEAMS_DISTRIBUTE:
7655 stmt = gfc_trans_omp_do (code, EXEC_OMP_DISTRIBUTE, NULL,
7656 &clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
7657 NULL);
7658 break;
7659 case EXEC_OMP_TARGET_TEAMS_LOOP:
7660 case EXEC_OMP_TEAMS_LOOP:
7661 stmt = gfc_trans_omp_do (code, EXEC_OMP_LOOP, NULL,
7662 &clausesa[GFC_OMP_SPLIT_DO],
7663 NULL);
7664 break;
7665 default:
7666 stmt = gfc_trans_omp_distribute (code, clausesa);
7667 break;
7669 if (flag_openmp)
7671 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7672 stmt = build2_loc (gfc_get_location (&code->loc), OMP_TEAMS,
7673 void_type_node, stmt, omp_clauses);
7674 if (combined)
7675 OMP_TEAMS_COMBINED (stmt) = 1;
7677 gfc_add_expr_to_block (&block, stmt);
7678 if (free_clausesa)
7679 gfc_free_split_omp_clauses (code, clausesa);
7680 return gfc_finish_block (&block);
7683 static tree
7684 gfc_trans_omp_target (gfc_code *code)
7686 stmtblock_t block;
7687 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
7688 tree stmt, omp_clauses = NULL_TREE;
7690 gfc_start_block (&block);
7691 gfc_split_omp_clauses (code, clausesa);
7692 if (flag_openmp)
7693 omp_clauses
7694 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TARGET],
7695 code->loc);
7696 switch (code->op)
7698 case EXEC_OMP_TARGET:
7699 pushlevel ();
7700 stmt = gfc_trans_omp_code (code->block->next, true);
7701 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7702 break;
7703 case EXEC_OMP_TARGET_PARALLEL:
7705 stmtblock_t iblock;
7707 pushlevel ();
7708 gfc_start_block (&iblock);
7709 tree inner_clauses
7710 = gfc_trans_omp_clauses (&iblock, &clausesa[GFC_OMP_SPLIT_PARALLEL],
7711 code->loc);
7712 stmt = gfc_trans_omp_code (code->block->next, true);
7713 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
7714 inner_clauses);
7715 gfc_add_expr_to_block (&iblock, stmt);
7716 stmt = gfc_finish_block (&iblock);
7717 if (TREE_CODE (stmt) != BIND_EXPR)
7718 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7719 else
7720 poplevel (0, 0);
7722 break;
7723 case EXEC_OMP_TARGET_PARALLEL_DO:
7724 case EXEC_OMP_TARGET_PARALLEL_LOOP:
7725 stmt = gfc_trans_omp_parallel_do (code,
7726 (code->op
7727 == EXEC_OMP_TARGET_PARALLEL_LOOP),
7728 &block, clausesa);
7729 if (TREE_CODE (stmt) != BIND_EXPR)
7730 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7731 else
7732 poplevel (0, 0);
7733 break;
7734 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
7735 stmt = gfc_trans_omp_parallel_do_simd (code, &block, clausesa);
7736 if (TREE_CODE (stmt) != BIND_EXPR)
7737 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7738 else
7739 poplevel (0, 0);
7740 break;
7741 case EXEC_OMP_TARGET_SIMD:
7742 stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
7743 &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
7744 if (TREE_CODE (stmt) != BIND_EXPR)
7745 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7746 else
7747 poplevel (0, 0);
7748 break;
7749 default:
7750 if (flag_openmp
7751 && (clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper
7752 || clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit))
7754 gfc_omp_clauses clausesb;
7755 tree teams_clauses;
7756 /* For combined !$omp target teams, the num_teams and
7757 thread_limit clauses are evaluated before entering the
7758 target construct. */
7759 memset (&clausesb, '\0', sizeof (clausesb));
7760 clausesb.num_teams_lower
7761 = clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_lower;
7762 clausesb.num_teams_upper
7763 = clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper;
7764 clausesb.thread_limit = clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit;
7765 clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_lower = NULL;
7766 clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper = NULL;
7767 clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit = NULL;
7768 teams_clauses
7769 = gfc_trans_omp_clauses (&block, &clausesb, code->loc);
7770 pushlevel ();
7771 stmt = gfc_trans_omp_teams (code, clausesa, teams_clauses);
7773 else
7775 pushlevel ();
7776 stmt = gfc_trans_omp_teams (code, clausesa, NULL_TREE);
7778 if (TREE_CODE (stmt) != BIND_EXPR)
7779 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7780 else
7781 poplevel (0, 0);
7782 break;
7784 if (flag_openmp)
7786 stmt = build2_loc (gfc_get_location (&code->loc), OMP_TARGET,
7787 void_type_node, stmt, omp_clauses);
7788 if (code->op != EXEC_OMP_TARGET)
7789 OMP_TARGET_COMBINED (stmt) = 1;
7790 cfun->has_omp_target = true;
7792 gfc_add_expr_to_block (&block, stmt);
7793 gfc_free_split_omp_clauses (code, clausesa);
7794 return gfc_finish_block (&block);
7797 static tree
7798 gfc_trans_omp_taskloop (gfc_code *code, gfc_exec_op op)
7800 stmtblock_t block;
7801 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
7802 tree stmt, omp_clauses = NULL_TREE;
7804 gfc_start_block (&block);
7805 gfc_split_omp_clauses (code, clausesa);
7806 if (flag_openmp)
7807 omp_clauses
7808 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TASKLOOP],
7809 code->loc);
7810 switch (op)
7812 case EXEC_OMP_TASKLOOP:
7813 /* This is handled in gfc_trans_omp_do. */
7814 gcc_unreachable ();
7815 break;
7816 case EXEC_OMP_TASKLOOP_SIMD:
7817 stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
7818 &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
7819 if (TREE_CODE (stmt) != BIND_EXPR)
7820 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7821 else
7822 poplevel (0, 0);
7823 break;
7824 default:
7825 gcc_unreachable ();
7827 if (flag_openmp)
7829 tree taskloop = make_node (OMP_TASKLOOP);
7830 SET_EXPR_LOCATION (taskloop, gfc_get_location (&code->loc));
7831 TREE_TYPE (taskloop) = void_type_node;
7832 OMP_FOR_BODY (taskloop) = stmt;
7833 OMP_FOR_CLAUSES (taskloop) = omp_clauses;
7834 stmt = taskloop;
7836 gfc_add_expr_to_block (&block, stmt);
7837 gfc_free_split_omp_clauses (code, clausesa);
7838 return gfc_finish_block (&block);
7841 static tree
7842 gfc_trans_omp_master_masked_taskloop (gfc_code *code, gfc_exec_op op)
7844 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
7845 stmtblock_t block;
7846 tree stmt;
7848 if (op != EXEC_OMP_MASTER_TASKLOOP_SIMD
7849 && code->op != EXEC_OMP_MASTER_TASKLOOP)
7850 gfc_split_omp_clauses (code, clausesa);
7852 pushlevel ();
7853 if (op == EXEC_OMP_MASKED_TASKLOOP_SIMD
7854 || op == EXEC_OMP_MASTER_TASKLOOP_SIMD)
7855 stmt = gfc_trans_omp_taskloop (code, EXEC_OMP_TASKLOOP_SIMD);
7856 else
7858 gcc_assert (op == EXEC_OMP_MASKED_TASKLOOP
7859 || op == EXEC_OMP_MASTER_TASKLOOP);
7860 stmt = gfc_trans_omp_do (code, EXEC_OMP_TASKLOOP, NULL,
7861 code->op != EXEC_OMP_MASTER_TASKLOOP
7862 ? &clausesa[GFC_OMP_SPLIT_TASKLOOP]
7863 : code->ext.omp_clauses, NULL);
7865 if (TREE_CODE (stmt) != BIND_EXPR)
7866 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7867 else
7868 poplevel (0, 0);
7869 gfc_start_block (&block);
7870 if (op == EXEC_OMP_MASKED_TASKLOOP || op == EXEC_OMP_MASKED_TASKLOOP_SIMD)
7872 tree clauses = gfc_trans_omp_clauses (&block,
7873 &clausesa[GFC_OMP_SPLIT_MASKED],
7874 code->loc);
7875 tree msk = make_node (OMP_MASKED);
7876 SET_EXPR_LOCATION (msk, gfc_get_location (&code->loc));
7877 TREE_TYPE (msk) = void_type_node;
7878 OMP_MASKED_BODY (msk) = stmt;
7879 OMP_MASKED_CLAUSES (msk) = clauses;
7880 OMP_MASKED_COMBINED (msk) = 1;
7881 gfc_add_expr_to_block (&block, msk);
7883 else
7885 gcc_assert (op == EXEC_OMP_MASTER_TASKLOOP
7886 || op == EXEC_OMP_MASTER_TASKLOOP_SIMD);
7887 stmt = build1_v (OMP_MASTER, stmt);
7888 gfc_add_expr_to_block (&block, stmt);
7890 if (op != EXEC_OMP_MASTER_TASKLOOP_SIMD
7891 && code->op != EXEC_OMP_MASTER_TASKLOOP)
7892 gfc_free_split_omp_clauses (code, clausesa);
7893 return gfc_finish_block (&block);
7896 static tree
7897 gfc_trans_omp_parallel_master_masked (gfc_code *code)
7899 stmtblock_t block;
7900 tree stmt, omp_clauses;
7901 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
7902 bool parallel_combined = false;
7904 if (code->op != EXEC_OMP_PARALLEL_MASTER)
7905 gfc_split_omp_clauses (code, clausesa);
7907 gfc_start_block (&block);
7908 omp_clauses = gfc_trans_omp_clauses (&block,
7909 code->op == EXEC_OMP_PARALLEL_MASTER
7910 ? code->ext.omp_clauses
7911 : &clausesa[GFC_OMP_SPLIT_PARALLEL],
7912 code->loc);
7913 pushlevel ();
7914 if (code->op == EXEC_OMP_PARALLEL_MASTER)
7915 stmt = gfc_trans_omp_master (code);
7916 else if (code->op == EXEC_OMP_PARALLEL_MASKED)
7917 stmt = gfc_trans_omp_masked (code, &clausesa[GFC_OMP_SPLIT_MASKED]);
7918 else
7920 gfc_exec_op op;
7921 switch (code->op)
7923 case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
7924 op = EXEC_OMP_MASKED_TASKLOOP;
7925 break;
7926 case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
7927 op = EXEC_OMP_MASKED_TASKLOOP_SIMD;
7928 break;
7929 case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
7930 op = EXEC_OMP_MASTER_TASKLOOP;
7931 break;
7932 case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
7933 op = EXEC_OMP_MASTER_TASKLOOP_SIMD;
7934 break;
7935 default:
7936 gcc_unreachable ();
7938 stmt = gfc_trans_omp_master_masked_taskloop (code, op);
7939 parallel_combined = true;
7941 if (TREE_CODE (stmt) != BIND_EXPR)
7942 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7943 else
7944 poplevel (0, 0);
7945 stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
7946 void_type_node, stmt, omp_clauses);
7947 /* masked does have just filter clause, but during gimplification
7948 isn't represented by a gimplification omp context, so for
7949 !$omp parallel masked don't set OMP_PARALLEL_COMBINED,
7950 so that
7951 !$omp parallel masked
7952 !$omp taskloop simd lastprivate (x)
7953 isn't confused with
7954 !$omp parallel masked taskloop simd lastprivate (x) */
7955 if (parallel_combined)
7956 OMP_PARALLEL_COMBINED (stmt) = 1;
7957 gfc_add_expr_to_block (&block, stmt);
7958 if (code->op != EXEC_OMP_PARALLEL_MASTER)
7959 gfc_free_split_omp_clauses (code, clausesa);
7960 return gfc_finish_block (&block);
7963 static tree
7964 gfc_trans_omp_target_data (gfc_code *code)
7966 stmtblock_t block;
7967 tree stmt, omp_clauses;
7969 gfc_start_block (&block);
7970 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
7971 code->loc);
7972 stmt = gfc_trans_omp_code (code->block->next, true);
7973 stmt = build2_loc (gfc_get_location (&code->loc), OMP_TARGET_DATA,
7974 void_type_node, stmt, omp_clauses);
7975 gfc_add_expr_to_block (&block, stmt);
7976 return gfc_finish_block (&block);
7979 static tree
7980 gfc_trans_omp_target_enter_data (gfc_code *code)
7982 stmtblock_t block;
7983 tree stmt, omp_clauses;
7985 gfc_start_block (&block);
7986 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
7987 code->loc);
7988 stmt = build1_loc (input_location, OMP_TARGET_ENTER_DATA, void_type_node,
7989 omp_clauses);
7990 gfc_add_expr_to_block (&block, stmt);
7991 return gfc_finish_block (&block);
7994 static tree
7995 gfc_trans_omp_target_exit_data (gfc_code *code)
7997 stmtblock_t block;
7998 tree stmt, omp_clauses;
8000 gfc_start_block (&block);
8001 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
8002 code->loc, false, false, code->op);
8003 stmt = build1_loc (input_location, OMP_TARGET_EXIT_DATA, void_type_node,
8004 omp_clauses);
8005 gfc_add_expr_to_block (&block, stmt);
8006 return gfc_finish_block (&block);
8009 static tree
8010 gfc_trans_omp_target_update (gfc_code *code)
8012 stmtblock_t block;
8013 tree stmt, omp_clauses;
8015 gfc_start_block (&block);
8016 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
8017 code->loc);
8018 stmt = build1_loc (input_location, OMP_TARGET_UPDATE, void_type_node,
8019 omp_clauses);
8020 gfc_add_expr_to_block (&block, stmt);
8021 return gfc_finish_block (&block);
8024 static tree
8025 gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses)
8027 tree res, tmp, stmt;
8028 stmtblock_t block, *pblock = NULL;
8029 stmtblock_t singleblock;
8030 int saved_ompws_flags;
8031 bool singleblock_in_progress = false;
8032 /* True if previous gfc_code in workshare construct is not workshared. */
8033 bool prev_singleunit;
8034 location_t loc = gfc_get_location (&code->loc);
8036 code = code->block->next;
8038 pushlevel ();
8040 gfc_start_block (&block);
8041 pblock = &block;
8043 ompws_flags = OMPWS_WORKSHARE_FLAG;
8044 prev_singleunit = false;
8046 /* Translate statements one by one to trees until we reach
8047 the end of the workshare construct. Adjacent gfc_codes that
8048 are a single unit of work are clustered and encapsulated in a
8049 single OMP_SINGLE construct. */
8050 for (; code; code = code->next)
8052 if (code->here != 0)
8054 res = gfc_trans_label_here (code);
8055 gfc_add_expr_to_block (pblock, res);
8058 /* No dependence analysis, use for clauses with wait.
8059 If this is the last gfc_code, use default omp_clauses. */
8060 if (code->next == NULL && clauses->nowait)
8061 ompws_flags |= OMPWS_NOWAIT;
8063 /* By default, every gfc_code is a single unit of work. */
8064 ompws_flags |= OMPWS_CURR_SINGLEUNIT;
8065 ompws_flags &= ~(OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY);
8067 switch (code->op)
8069 case EXEC_NOP:
8070 res = NULL_TREE;
8071 break;
8073 case EXEC_ASSIGN:
8074 res = gfc_trans_assign (code);
8075 break;
8077 case EXEC_POINTER_ASSIGN:
8078 res = gfc_trans_pointer_assign (code);
8079 break;
8081 case EXEC_INIT_ASSIGN:
8082 res = gfc_trans_init_assign (code);
8083 break;
8085 case EXEC_FORALL:
8086 res = gfc_trans_forall (code);
8087 break;
8089 case EXEC_WHERE:
8090 res = gfc_trans_where (code);
8091 break;
8093 case EXEC_OMP_ATOMIC:
8094 res = gfc_trans_omp_directive (code);
8095 break;
8097 case EXEC_OMP_PARALLEL:
8098 case EXEC_OMP_PARALLEL_DO:
8099 case EXEC_OMP_PARALLEL_MASTER:
8100 case EXEC_OMP_PARALLEL_SECTIONS:
8101 case EXEC_OMP_PARALLEL_WORKSHARE:
8102 case EXEC_OMP_CRITICAL:
8103 saved_ompws_flags = ompws_flags;
8104 ompws_flags = 0;
8105 res = gfc_trans_omp_directive (code);
8106 ompws_flags = saved_ompws_flags;
8107 break;
8109 case EXEC_BLOCK:
8110 res = gfc_trans_block_construct (code);
8111 break;
8113 default:
8114 gfc_internal_error ("gfc_trans_omp_workshare(): Bad statement code");
8117 gfc_set_backend_locus (&code->loc);
8119 if (res != NULL_TREE && ! IS_EMPTY_STMT (res))
8121 if (prev_singleunit)
8123 if (ompws_flags & OMPWS_CURR_SINGLEUNIT)
8124 /* Add current gfc_code to single block. */
8125 gfc_add_expr_to_block (&singleblock, res);
8126 else
8128 /* Finish single block and add it to pblock. */
8129 tmp = gfc_finish_block (&singleblock);
8130 tmp = build2_loc (loc, OMP_SINGLE,
8131 void_type_node, tmp, NULL_TREE);
8132 gfc_add_expr_to_block (pblock, tmp);
8133 /* Add current gfc_code to pblock. */
8134 gfc_add_expr_to_block (pblock, res);
8135 singleblock_in_progress = false;
8138 else
8140 if (ompws_flags & OMPWS_CURR_SINGLEUNIT)
8142 /* Start single block. */
8143 gfc_init_block (&singleblock);
8144 gfc_add_expr_to_block (&singleblock, res);
8145 singleblock_in_progress = true;
8146 loc = gfc_get_location (&code->loc);
8148 else
8149 /* Add the new statement to the block. */
8150 gfc_add_expr_to_block (pblock, res);
8152 prev_singleunit = (ompws_flags & OMPWS_CURR_SINGLEUNIT) != 0;
8156 /* Finish remaining SINGLE block, if we were in the middle of one. */
8157 if (singleblock_in_progress)
8159 /* Finish single block and add it to pblock. */
8160 tmp = gfc_finish_block (&singleblock);
8161 tmp = build2_loc (loc, OMP_SINGLE, void_type_node, tmp,
8162 clauses->nowait
8163 ? build_omp_clause (input_location, OMP_CLAUSE_NOWAIT)
8164 : NULL_TREE);
8165 gfc_add_expr_to_block (pblock, tmp);
8168 stmt = gfc_finish_block (pblock);
8169 if (TREE_CODE (stmt) != BIND_EXPR)
8171 if (!IS_EMPTY_STMT (stmt))
8173 tree bindblock = poplevel (1, 0);
8174 stmt = build3_v (BIND_EXPR, NULL, stmt, bindblock);
8176 else
8177 poplevel (0, 0);
8179 else
8180 poplevel (0, 0);
8182 if (IS_EMPTY_STMT (stmt) && !clauses->nowait)
8183 stmt = gfc_trans_omp_barrier ();
8185 ompws_flags = 0;
8186 return stmt;
8189 tree
8190 gfc_trans_oacc_declare (gfc_code *code)
8192 stmtblock_t block;
8193 tree stmt, oacc_clauses;
8194 enum tree_code construct_code;
8196 construct_code = OACC_DATA;
8198 gfc_start_block (&block);
8200 oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.oacc_declare->clauses,
8201 code->loc, false, true);
8202 stmt = gfc_trans_omp_code (code->block->next, true);
8203 stmt = build2_loc (input_location, construct_code, void_type_node, stmt,
8204 oacc_clauses);
8205 gfc_add_expr_to_block (&block, stmt);
8207 return gfc_finish_block (&block);
8210 tree
8211 gfc_trans_oacc_directive (gfc_code *code)
8213 switch (code->op)
8215 case EXEC_OACC_PARALLEL_LOOP:
8216 case EXEC_OACC_KERNELS_LOOP:
8217 case EXEC_OACC_SERIAL_LOOP:
8218 return gfc_trans_oacc_combined_directive (code);
8219 case EXEC_OACC_PARALLEL:
8220 case EXEC_OACC_KERNELS:
8221 case EXEC_OACC_SERIAL:
8222 case EXEC_OACC_DATA:
8223 case EXEC_OACC_HOST_DATA:
8224 return gfc_trans_oacc_construct (code);
8225 case EXEC_OACC_LOOP:
8226 return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses,
8227 NULL);
8228 case EXEC_OACC_UPDATE:
8229 case EXEC_OACC_CACHE:
8230 case EXEC_OACC_ENTER_DATA:
8231 case EXEC_OACC_EXIT_DATA:
8232 return gfc_trans_oacc_executable_directive (code);
8233 case EXEC_OACC_WAIT:
8234 return gfc_trans_oacc_wait_directive (code);
8235 case EXEC_OACC_ATOMIC:
8236 return gfc_trans_omp_atomic (code);
8237 case EXEC_OACC_DECLARE:
8238 return gfc_trans_oacc_declare (code);
8239 default:
8240 gcc_unreachable ();
8244 tree
8245 gfc_trans_omp_directive (gfc_code *code)
8247 switch (code->op)
8249 case EXEC_OMP_ALLOCATE:
8250 case EXEC_OMP_ALLOCATORS:
8251 return gfc_trans_omp_allocators (code);
8252 case EXEC_OMP_ASSUME:
8253 return gfc_trans_omp_assume (code);
8254 case EXEC_OMP_ATOMIC:
8255 return gfc_trans_omp_atomic (code);
8256 case EXEC_OMP_BARRIER:
8257 return gfc_trans_omp_barrier ();
8258 case EXEC_OMP_CANCEL:
8259 return gfc_trans_omp_cancel (code);
8260 case EXEC_OMP_CANCELLATION_POINT:
8261 return gfc_trans_omp_cancellation_point (code);
8262 case EXEC_OMP_CRITICAL:
8263 return gfc_trans_omp_critical (code);
8264 case EXEC_OMP_DEPOBJ:
8265 return gfc_trans_omp_depobj (code);
8266 case EXEC_OMP_DISTRIBUTE:
8267 case EXEC_OMP_DO:
8268 case EXEC_OMP_LOOP:
8269 case EXEC_OMP_SIMD:
8270 case EXEC_OMP_TASKLOOP:
8271 case EXEC_OMP_TILE:
8272 case EXEC_OMP_UNROLL:
8273 return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses,
8274 NULL);
8275 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
8276 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
8277 case EXEC_OMP_DISTRIBUTE_SIMD:
8278 return gfc_trans_omp_distribute (code, NULL);
8279 case EXEC_OMP_DO_SIMD:
8280 return gfc_trans_omp_do_simd (code, NULL, NULL, NULL_TREE);
8281 case EXEC_OMP_ERROR:
8282 return gfc_trans_omp_error (code);
8283 case EXEC_OMP_FLUSH:
8284 return gfc_trans_omp_flush (code);
8285 case EXEC_OMP_MASKED:
8286 return gfc_trans_omp_masked (code, NULL);
8287 case EXEC_OMP_MASTER:
8288 return gfc_trans_omp_master (code);
8289 case EXEC_OMP_MASKED_TASKLOOP:
8290 case EXEC_OMP_MASKED_TASKLOOP_SIMD:
8291 case EXEC_OMP_MASTER_TASKLOOP:
8292 case EXEC_OMP_MASTER_TASKLOOP_SIMD:
8293 return gfc_trans_omp_master_masked_taskloop (code, code->op);
8294 case EXEC_OMP_ORDERED:
8295 return gfc_trans_omp_ordered (code);
8296 case EXEC_OMP_PARALLEL:
8297 return gfc_trans_omp_parallel (code);
8298 case EXEC_OMP_PARALLEL_DO:
8299 return gfc_trans_omp_parallel_do (code, false, NULL, NULL);
8300 case EXEC_OMP_PARALLEL_LOOP:
8301 return gfc_trans_omp_parallel_do (code, true, NULL, NULL);
8302 case EXEC_OMP_PARALLEL_DO_SIMD:
8303 return gfc_trans_omp_parallel_do_simd (code, NULL, NULL);
8304 case EXEC_OMP_PARALLEL_MASKED:
8305 case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
8306 case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
8307 case EXEC_OMP_PARALLEL_MASTER:
8308 case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
8309 case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
8310 return gfc_trans_omp_parallel_master_masked (code);
8311 case EXEC_OMP_PARALLEL_SECTIONS:
8312 return gfc_trans_omp_parallel_sections (code);
8313 case EXEC_OMP_PARALLEL_WORKSHARE:
8314 return gfc_trans_omp_parallel_workshare (code);
8315 case EXEC_OMP_SCOPE:
8316 return gfc_trans_omp_scope (code);
8317 case EXEC_OMP_SECTIONS:
8318 return gfc_trans_omp_sections (code, code->ext.omp_clauses);
8319 case EXEC_OMP_SINGLE:
8320 return gfc_trans_omp_single (code, code->ext.omp_clauses);
8321 case EXEC_OMP_TARGET:
8322 case EXEC_OMP_TARGET_PARALLEL:
8323 case EXEC_OMP_TARGET_PARALLEL_DO:
8324 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
8325 case EXEC_OMP_TARGET_PARALLEL_LOOP:
8326 case EXEC_OMP_TARGET_SIMD:
8327 case EXEC_OMP_TARGET_TEAMS:
8328 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
8329 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
8330 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
8331 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
8332 case EXEC_OMP_TARGET_TEAMS_LOOP:
8333 return gfc_trans_omp_target (code);
8334 case EXEC_OMP_TARGET_DATA:
8335 return gfc_trans_omp_target_data (code);
8336 case EXEC_OMP_TARGET_ENTER_DATA:
8337 return gfc_trans_omp_target_enter_data (code);
8338 case EXEC_OMP_TARGET_EXIT_DATA:
8339 return gfc_trans_omp_target_exit_data (code);
8340 case EXEC_OMP_TARGET_UPDATE:
8341 return gfc_trans_omp_target_update (code);
8342 case EXEC_OMP_TASK:
8343 return gfc_trans_omp_task (code);
8344 case EXEC_OMP_TASKGROUP:
8345 return gfc_trans_omp_taskgroup (code);
8346 case EXEC_OMP_TASKLOOP_SIMD:
8347 return gfc_trans_omp_taskloop (code, code->op);
8348 case EXEC_OMP_TASKWAIT:
8349 return gfc_trans_omp_taskwait (code);
8350 case EXEC_OMP_TASKYIELD:
8351 return gfc_trans_omp_taskyield ();
8352 case EXEC_OMP_TEAMS:
8353 case EXEC_OMP_TEAMS_DISTRIBUTE:
8354 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
8355 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
8356 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
8357 case EXEC_OMP_TEAMS_LOOP:
8358 return gfc_trans_omp_teams (code, NULL, NULL_TREE);
8359 case EXEC_OMP_WORKSHARE:
8360 return gfc_trans_omp_workshare (code, code->ext.omp_clauses);
8361 case EXEC_OMP_INTEROP:
8362 sorry ("%<!$OMP INTEROP%>");
8363 return build_empty_stmt (input_location);
8364 default:
8365 gcc_unreachable ();
8369 void
8370 gfc_trans_omp_declare_simd (gfc_namespace *ns)
8372 if (ns->entries)
8373 return;
8375 gfc_omp_declare_simd *ods;
8376 for (ods = ns->omp_declare_simd; ods; ods = ods->next)
8378 tree c = gfc_trans_omp_clauses (NULL, ods->clauses, ods->where, true);
8379 tree fndecl = ns->proc_name->backend_decl;
8380 if (c != NULL_TREE)
8381 c = tree_cons (NULL_TREE, c, NULL_TREE);
8382 c = build_tree_list (get_identifier ("omp declare simd"), c);
8383 TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
8384 DECL_ATTRIBUTES (fndecl) = c;
8388 void
8389 gfc_trans_omp_declare_variant (gfc_namespace *ns)
8391 tree base_fn_decl = ns->proc_name->backend_decl;
8392 gfc_namespace *search_ns = ns;
8393 gfc_omp_declare_variant *next;
8395 for (gfc_omp_declare_variant *odv = search_ns->omp_declare_variant;
8396 search_ns; odv = next)
8398 /* Look in the parent namespace if there are no more directives in the
8399 current namespace. */
8400 if (!odv)
8402 search_ns = search_ns->parent;
8403 if (search_ns)
8404 next = search_ns->omp_declare_variant;
8405 continue;
8408 next = odv->next;
8410 if (odv->error_p)
8411 continue;
8413 /* Check directive the first time it is encountered. */
8414 bool error_found = true;
8416 if (odv->checked_p)
8417 error_found = false;
8418 if (odv->base_proc_symtree == NULL)
8420 if (!search_ns->proc_name->attr.function
8421 && !search_ns->proc_name->attr.subroutine)
8422 gfc_error ("The base name for 'declare variant' must be "
8423 "specified at %L ", &odv->where);
8424 else
8425 error_found = false;
8427 else
8429 if (!search_ns->contained
8430 && strcmp (odv->base_proc_symtree->name,
8431 ns->proc_name->name))
8432 gfc_error ("The base name at %L does not match the name of the "
8433 "current procedure", &odv->where);
8434 else if (odv->base_proc_symtree->n.sym->attr.entry)
8435 gfc_error ("The base name at %L must not be an entry name",
8436 &odv->where);
8437 else if (odv->base_proc_symtree->n.sym->attr.generic)
8438 gfc_error ("The base name at %L must not be a generic name",
8439 &odv->where);
8440 else if (odv->base_proc_symtree->n.sym->attr.proc_pointer)
8441 gfc_error ("The base name at %L must not be a procedure pointer",
8442 &odv->where);
8443 else if (odv->base_proc_symtree->n.sym->attr.implicit_type)
8444 gfc_error ("The base procedure at %L must have an explicit "
8445 "interface", &odv->where);
8446 else
8447 error_found = false;
8450 odv->checked_p = true;
8451 if (error_found)
8453 odv->error_p = true;
8454 continue;
8457 /* Ignore directives that do not apply to the current procedure. */
8458 if ((odv->base_proc_symtree == NULL && search_ns != ns)
8459 || (odv->base_proc_symtree != NULL
8460 && strcmp (odv->base_proc_symtree->name, ns->proc_name->name)))
8461 continue;
8463 tree set_selectors = NULL_TREE;
8464 gfc_omp_set_selector *oss;
8466 for (oss = odv->set_selectors; oss; oss = oss->next)
8468 tree selectors = NULL_TREE;
8469 gfc_omp_selector *os;
8470 enum omp_tss_code set = oss->code;
8471 gcc_assert (set != OMP_TRAIT_SET_INVALID);
8473 for (os = oss->trait_selectors; os; os = os->next)
8475 tree scoreval = NULL_TREE;
8476 tree properties = NULL_TREE;
8477 gfc_omp_trait_property *otp;
8478 enum omp_ts_code sel = os->code;
8480 /* Per the spec, "Implementations can ignore specified
8481 selectors that are not those described in this section";
8482 however, we must record such selectors because they
8483 cause match failures. */
8484 if (sel == OMP_TRAIT_INVALID)
8486 selectors = make_trait_selector (sel, NULL_TREE, NULL_TREE,
8487 selectors);
8488 continue;
8491 for (otp = os->properties; otp; otp = otp->next)
8493 switch (otp->property_kind)
8495 case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
8496 case OMP_TRAIT_PROPERTY_BOOL_EXPR:
8498 gfc_se se;
8499 gfc_init_se (&se, NULL);
8500 gfc_conv_expr (&se, otp->expr);
8501 properties = make_trait_property (NULL_TREE, se.expr,
8502 properties);
8504 break;
8505 case OMP_TRAIT_PROPERTY_ID:
8506 properties
8507 = make_trait_property (get_identifier (otp->name),
8508 NULL_TREE, properties);
8509 break;
8510 case OMP_TRAIT_PROPERTY_NAME_LIST:
8512 tree prop = OMP_TP_NAMELIST_NODE;
8513 tree value = NULL_TREE;
8514 if (otp->is_name)
8515 value = get_identifier (otp->name);
8516 else
8517 value = gfc_conv_constant_to_tree (otp->expr);
8519 properties = make_trait_property (prop, value,
8520 properties);
8522 break;
8523 case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
8524 properties = gfc_trans_omp_clauses (NULL, otp->clauses,
8525 odv->where, true);
8526 break;
8527 default:
8528 gcc_unreachable ();
8532 if (os->score)
8534 gfc_se se;
8535 gfc_init_se (&se, NULL);
8536 gfc_conv_expr (&se, os->score);
8537 scoreval = se.expr;
8540 selectors = make_trait_selector (sel, scoreval,
8541 properties, selectors);
8543 set_selectors = make_trait_set_selector (set, selectors,
8544 set_selectors);
8547 const char *variant_proc_name = odv->variant_proc_symtree->name;
8548 gfc_symbol *variant_proc_sym = odv->variant_proc_symtree->n.sym;
8549 if (variant_proc_sym == NULL || variant_proc_sym->attr.implicit_type)
8551 gfc_symtree *proc_st;
8552 gfc_find_sym_tree (variant_proc_name, gfc_current_ns, 1, &proc_st);
8553 variant_proc_sym = proc_st->n.sym;
8555 if (variant_proc_sym == NULL)
8557 gfc_error ("Cannot find symbol %qs", variant_proc_name);
8558 continue;
8560 set_selectors = omp_check_context_selector
8561 (gfc_get_location (&odv->where), set_selectors);
8562 if (set_selectors != error_mark_node)
8564 if (!variant_proc_sym->attr.implicit_type
8565 && !variant_proc_sym->attr.subroutine
8566 && !variant_proc_sym->attr.function)
8568 gfc_error ("variant %qs at %L is not a function or subroutine",
8569 variant_proc_name, &odv->where);
8570 variant_proc_sym = NULL;
8572 else if (omp_get_context_selector (set_selectors,
8573 OMP_TRAIT_SET_CONSTRUCT,
8574 OMP_TRAIT_CONSTRUCT_SIMD)
8575 == NULL_TREE)
8577 char err[256];
8578 if (!gfc_compare_interfaces (ns->proc_name, variant_proc_sym,
8579 variant_proc_sym->name, 0, 1,
8580 err, sizeof (err), NULL, NULL))
8582 gfc_error ("variant %qs and base %qs at %L have "
8583 "incompatible types: %s",
8584 variant_proc_name, ns->proc_name->name,
8585 &odv->where, err);
8586 variant_proc_sym = NULL;
8589 if (variant_proc_sym != NULL)
8591 gfc_set_sym_referenced (variant_proc_sym);
8592 tree construct
8593 = omp_get_context_selector_list (set_selectors,
8594 OMP_TRAIT_SET_CONSTRUCT);
8595 omp_mark_declare_variant (gfc_get_location (&odv->where),
8596 gfc_get_symbol_decl (variant_proc_sym),
8597 construct);
8598 if (omp_context_selector_matches (set_selectors))
8600 tree id = get_identifier ("omp declare variant base");
8601 tree variant = gfc_get_symbol_decl (variant_proc_sym);
8602 DECL_ATTRIBUTES (base_fn_decl)
8603 = tree_cons (id, build_tree_list (variant, set_selectors),
8604 DECL_ATTRIBUTES (base_fn_decl));
8611 /* Add ptr for tracking as being allocated by GOMP_alloc. */
8613 tree
8614 gfc_omp_call_add_alloc (tree ptr)
8616 static tree fn = NULL_TREE;
8617 if (fn == NULL_TREE)
8619 fn = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
8620 tree att = build_tree_list (NULL_TREE, build_string (4, ". R "));
8621 att = tree_cons (get_identifier ("fn spec"), att, TYPE_ATTRIBUTES (fn));
8622 fn = build_type_attribute_variant (fn, att);
8623 fn = build_fn_decl ("GOMP_add_alloc", fn);
8625 return build_call_expr_loc (input_location, fn, 1, ptr);
8628 /* Generated function returns true when it was tracked via GOMP_add_alloc and
8629 removes it from the tracking. As called just before GOMP_free or omp_realloc
8630 the pointer is or might become invalid, thus, it is always removed. */
8632 tree
8633 gfc_omp_call_is_alloc (tree ptr)
8635 static tree fn = NULL_TREE;
8636 if (fn == NULL_TREE)
8638 fn = build_function_type_list (boolean_type_node, ptr_type_node,
8639 NULL_TREE);
8640 tree att = build_tree_list (NULL_TREE, build_string (4, ". R "));
8641 att = tree_cons (get_identifier ("fn spec"), att, TYPE_ATTRIBUTES (fn));
8642 fn = build_type_attribute_variant (fn, att);
8643 fn = build_fn_decl ("GOMP_is_alloc", fn);
8645 return build_call_expr_loc (input_location, fn, 1, ptr);