ada/
[official-gcc.git] / gcc / fortran / trans-openmp.c
blobdd19a9cec213ab9b758757c91a54ef51b070d7c4
1 /* OpenMP directive translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2005-2015 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 "hash-set.h"
26 #include "machmode.h"
27 #include "vec.h"
28 #include "double-int.h"
29 #include "input.h"
30 #include "alias.h"
31 #include "symtab.h"
32 #include "options.h"
33 #include "wide-int.h"
34 #include "inchash.h"
35 #include "tree.h"
36 #include "fold-const.h"
37 #include "gimple-expr.h"
38 #include "gimplify.h" /* For create_tmp_var_raw. */
39 #include "stringpool.h"
40 #include "gfortran.h"
41 #include "diagnostic-core.h" /* For internal_error. */
42 #include "trans.h"
43 #include "trans-stmt.h"
44 #include "trans-types.h"
45 #include "trans-array.h"
46 #include "trans-const.h"
47 #include "arith.h"
48 #include "omp-low.h"
49 #include "gomp-constants.h"
51 int ompws_flags;
53 /* True if OpenMP should privatize what this DECL points to rather
54 than the DECL itself. */
56 bool
57 gfc_omp_privatize_by_reference (const_tree decl)
59 tree type = TREE_TYPE (decl);
61 if (TREE_CODE (type) == REFERENCE_TYPE
62 && (!DECL_ARTIFICIAL (decl) || TREE_CODE (decl) == PARM_DECL))
63 return true;
65 if (TREE_CODE (type) == POINTER_TYPE)
67 /* Array POINTER/ALLOCATABLE have aggregate types, all user variables
68 that have POINTER_TYPE type and aren't scalar pointers, scalar
69 allocatables, Cray pointees or C pointers are supposed to be
70 privatized by reference. */
71 if (GFC_DECL_GET_SCALAR_POINTER (decl)
72 || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
73 || GFC_DECL_CRAY_POINTEE (decl)
74 || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
75 return false;
77 if (!DECL_ARTIFICIAL (decl)
78 && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
79 return true;
81 /* Some arrays are expanded as DECL_ARTIFICIAL pointers
82 by the frontend. */
83 if (DECL_LANG_SPECIFIC (decl)
84 && GFC_DECL_SAVED_DESCRIPTOR (decl))
85 return true;
88 return false;
91 /* True if OpenMP sharing attribute of DECL is predetermined. */
93 enum omp_clause_default_kind
94 gfc_omp_predetermined_sharing (tree decl)
96 /* Associate names preserve the association established during ASSOCIATE.
97 As they are implemented either as pointers to the selector or array
98 descriptor and shouldn't really change in the ASSOCIATE region,
99 this decl can be either shared or firstprivate. If it is a pointer,
100 use firstprivate, as it is cheaper that way, otherwise make it shared. */
101 if (GFC_DECL_ASSOCIATE_VAR_P (decl))
103 if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
104 return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
105 else
106 return OMP_CLAUSE_DEFAULT_SHARED;
109 if (DECL_ARTIFICIAL (decl)
110 && ! GFC_DECL_RESULT (decl)
111 && ! (DECL_LANG_SPECIFIC (decl)
112 && GFC_DECL_SAVED_DESCRIPTOR (decl)))
113 return OMP_CLAUSE_DEFAULT_SHARED;
115 /* Cray pointees shouldn't be listed in any clauses and should be
116 gimplified to dereference of the corresponding Cray pointer.
117 Make them all private, so that they are emitted in the debug
118 information. */
119 if (GFC_DECL_CRAY_POINTEE (decl))
120 return OMP_CLAUSE_DEFAULT_PRIVATE;
122 /* Assumed-size arrays are predetermined shared. */
123 if (TREE_CODE (decl) == PARM_DECL
124 && GFC_ARRAY_TYPE_P (TREE_TYPE (decl))
125 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN
126 && GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (decl),
127 GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)) - 1)
128 == NULL)
129 return OMP_CLAUSE_DEFAULT_SHARED;
131 /* Dummy procedures aren't considered variables by OpenMP, thus are
132 disallowed in OpenMP clauses. They are represented as PARM_DECLs
133 in the middle-end, so return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE here
134 to avoid complaining about their uses with default(none). */
135 if (TREE_CODE (decl) == PARM_DECL
136 && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
137 && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == FUNCTION_TYPE)
138 return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
140 /* COMMON and EQUIVALENCE decls are shared. They
141 are only referenced through DECL_VALUE_EXPR of the variables
142 contained in them. If those are privatized, they will not be
143 gimplified to the COMMON or EQUIVALENCE decls. */
144 if (GFC_DECL_COMMON_OR_EQUIV (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
145 return OMP_CLAUSE_DEFAULT_SHARED;
147 if (GFC_DECL_RESULT (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
148 return OMP_CLAUSE_DEFAULT_SHARED;
150 /* These are either array or derived parameters, or vtables.
151 In the former cases, the OpenMP standard doesn't consider them to be
152 variables at all (they can't be redefined), but they can nevertheless appear
153 in parallel/task regions and for default(none) purposes treat them as shared.
154 For vtables likely the same handling is desirable. */
155 if (TREE_CODE (decl) == VAR_DECL
156 && TREE_READONLY (decl)
157 && TREE_STATIC (decl))
158 return OMP_CLAUSE_DEFAULT_SHARED;
160 return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
163 /* Return decl that should be used when reporting DEFAULT(NONE)
164 diagnostics. */
166 tree
167 gfc_omp_report_decl (tree decl)
169 if (DECL_ARTIFICIAL (decl)
170 && DECL_LANG_SPECIFIC (decl)
171 && GFC_DECL_SAVED_DESCRIPTOR (decl))
172 return GFC_DECL_SAVED_DESCRIPTOR (decl);
174 return decl;
177 /* Return true if TYPE has any allocatable components. */
179 static bool
180 gfc_has_alloc_comps (tree type, tree decl)
182 tree field, ftype;
184 if (POINTER_TYPE_P (type))
186 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
187 type = TREE_TYPE (type);
188 else if (GFC_DECL_GET_SCALAR_POINTER (decl))
189 return false;
192 if (GFC_DESCRIPTOR_TYPE_P (type) || GFC_ARRAY_TYPE_P (type))
193 type = gfc_get_element_type (type);
195 if (TREE_CODE (type) != RECORD_TYPE)
196 return false;
198 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
200 ftype = TREE_TYPE (field);
201 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
202 return true;
203 if (GFC_DESCRIPTOR_TYPE_P (ftype)
204 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
205 return true;
206 if (gfc_has_alloc_comps (ftype, field))
207 return true;
209 return false;
212 /* Return true if DECL in private clause needs
213 OMP_CLAUSE_PRIVATE_OUTER_REF on the private clause. */
214 bool
215 gfc_omp_private_outer_ref (tree decl)
217 tree type = TREE_TYPE (decl);
219 if (GFC_DESCRIPTOR_TYPE_P (type)
220 && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
221 return true;
223 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
224 return true;
226 if (gfc_omp_privatize_by_reference (decl))
227 type = TREE_TYPE (type);
229 if (gfc_has_alloc_comps (type, decl))
230 return true;
232 return false;
235 /* Callback for gfc_omp_unshare_expr. */
237 static tree
238 gfc_omp_unshare_expr_r (tree *tp, int *walk_subtrees, void *)
240 tree t = *tp;
241 enum tree_code code = TREE_CODE (t);
243 /* Stop at types, decls, constants like copy_tree_r. */
244 if (TREE_CODE_CLASS (code) == tcc_type
245 || TREE_CODE_CLASS (code) == tcc_declaration
246 || TREE_CODE_CLASS (code) == tcc_constant
247 || code == BLOCK)
248 *walk_subtrees = 0;
249 else if (handled_component_p (t)
250 || TREE_CODE (t) == MEM_REF)
252 *tp = unshare_expr (t);
253 *walk_subtrees = 0;
256 return NULL_TREE;
259 /* Unshare in expr anything that the FE which normally doesn't
260 care much about tree sharing (because during gimplification
261 everything is unshared) could cause problems with tree sharing
262 at omp-low.c time. */
264 static tree
265 gfc_omp_unshare_expr (tree expr)
267 walk_tree (&expr, gfc_omp_unshare_expr_r, NULL, NULL);
268 return expr;
271 enum walk_alloc_comps
273 WALK_ALLOC_COMPS_DTOR,
274 WALK_ALLOC_COMPS_DEFAULT_CTOR,
275 WALK_ALLOC_COMPS_COPY_CTOR
278 /* Handle allocatable components in OpenMP clauses. */
280 static tree
281 gfc_walk_alloc_comps (tree decl, tree dest, tree var,
282 enum walk_alloc_comps kind)
284 stmtblock_t block, tmpblock;
285 tree type = TREE_TYPE (decl), then_b, tem, field;
286 gfc_init_block (&block);
288 if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
290 if (GFC_DESCRIPTOR_TYPE_P (type))
292 gfc_init_block (&tmpblock);
293 tem = gfc_full_array_size (&tmpblock, decl,
294 GFC_TYPE_ARRAY_RANK (type));
295 then_b = gfc_finish_block (&tmpblock);
296 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (then_b));
297 tem = gfc_omp_unshare_expr (tem);
298 tem = fold_build2_loc (input_location, MINUS_EXPR,
299 gfc_array_index_type, tem,
300 gfc_index_one_node);
302 else
304 if (!TYPE_DOMAIN (type)
305 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE
306 || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node
307 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node)
309 tem = fold_build2 (EXACT_DIV_EXPR, sizetype,
310 TYPE_SIZE_UNIT (type),
311 TYPE_SIZE_UNIT (TREE_TYPE (type)));
312 tem = size_binop (MINUS_EXPR, tem, size_one_node);
314 else
315 tem = array_type_nelts (type);
316 tem = fold_convert (gfc_array_index_type, tem);
319 tree nelems = gfc_evaluate_now (tem, &block);
320 tree index = gfc_create_var (gfc_array_index_type, "S");
322 gfc_init_block (&tmpblock);
323 tem = gfc_conv_array_data (decl);
324 tree declvar = build_fold_indirect_ref_loc (input_location, tem);
325 tree declvref = gfc_build_array_ref (declvar, index, NULL);
326 tree destvar, destvref = NULL_TREE;
327 if (dest)
329 tem = gfc_conv_array_data (dest);
330 destvar = build_fold_indirect_ref_loc (input_location, tem);
331 destvref = gfc_build_array_ref (destvar, index, NULL);
333 gfc_add_expr_to_block (&tmpblock,
334 gfc_walk_alloc_comps (declvref, destvref,
335 var, kind));
337 gfc_loopinfo loop;
338 gfc_init_loopinfo (&loop);
339 loop.dimen = 1;
340 loop.from[0] = gfc_index_zero_node;
341 loop.loopvar[0] = index;
342 loop.to[0] = nelems;
343 gfc_trans_scalarizing_loops (&loop, &tmpblock);
344 gfc_add_block_to_block (&block, &loop.pre);
345 return gfc_finish_block (&block);
347 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (var))
349 decl = build_fold_indirect_ref_loc (input_location, decl);
350 if (dest)
351 dest = build_fold_indirect_ref_loc (input_location, dest);
352 type = TREE_TYPE (decl);
355 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
356 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
358 tree ftype = TREE_TYPE (field);
359 tree declf, destf = NULL_TREE;
360 bool has_alloc_comps = gfc_has_alloc_comps (ftype, field);
361 if ((!GFC_DESCRIPTOR_TYPE_P (ftype)
362 || GFC_TYPE_ARRAY_AKIND (ftype) != GFC_ARRAY_ALLOCATABLE)
363 && !GFC_DECL_GET_SCALAR_ALLOCATABLE (field)
364 && !has_alloc_comps)
365 continue;
366 declf = fold_build3_loc (input_location, COMPONENT_REF, ftype,
367 decl, field, NULL_TREE);
368 if (dest)
369 destf = fold_build3_loc (input_location, COMPONENT_REF, ftype,
370 dest, field, NULL_TREE);
372 tem = NULL_TREE;
373 switch (kind)
375 case WALK_ALLOC_COMPS_DTOR:
376 break;
377 case WALK_ALLOC_COMPS_DEFAULT_CTOR:
378 if (GFC_DESCRIPTOR_TYPE_P (ftype)
379 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
381 gfc_add_modify (&block, unshare_expr (destf),
382 unshare_expr (declf));
383 tem = gfc_duplicate_allocatable_nocopy
384 (destf, declf, ftype,
385 GFC_TYPE_ARRAY_RANK (ftype));
387 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
388 tem = gfc_duplicate_allocatable_nocopy (destf, declf, ftype, 0);
389 break;
390 case WALK_ALLOC_COMPS_COPY_CTOR:
391 if (GFC_DESCRIPTOR_TYPE_P (ftype)
392 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
393 tem = gfc_duplicate_allocatable (destf, declf, ftype,
394 GFC_TYPE_ARRAY_RANK (ftype),
395 NULL_TREE);
396 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
397 tem = gfc_duplicate_allocatable (destf, declf, ftype, 0,
398 NULL_TREE);
399 break;
401 if (tem)
402 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
403 if (has_alloc_comps)
405 gfc_init_block (&tmpblock);
406 gfc_add_expr_to_block (&tmpblock,
407 gfc_walk_alloc_comps (declf, destf,
408 field, kind));
409 then_b = gfc_finish_block (&tmpblock);
410 if (GFC_DESCRIPTOR_TYPE_P (ftype)
411 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
412 tem = gfc_conv_descriptor_data_get (unshare_expr (declf));
413 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
414 tem = unshare_expr (declf);
415 else
416 tem = NULL_TREE;
417 if (tem)
419 tem = fold_convert (pvoid_type_node, tem);
420 tem = fold_build2_loc (input_location, NE_EXPR,
421 boolean_type_node, tem,
422 null_pointer_node);
423 then_b = build3_loc (input_location, COND_EXPR, void_type_node,
424 tem, then_b,
425 build_empty_stmt (input_location));
427 gfc_add_expr_to_block (&block, then_b);
429 if (kind == WALK_ALLOC_COMPS_DTOR)
431 if (GFC_DESCRIPTOR_TYPE_P (ftype)
432 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
434 tem = gfc_trans_dealloc_allocated (unshare_expr (declf),
435 false, NULL);
436 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
438 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
440 tem = gfc_call_free (unshare_expr (declf));
441 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
446 return gfc_finish_block (&block);
449 /* Return code to initialize DECL with its default constructor, or
450 NULL if there's nothing to do. */
452 tree
453 gfc_omp_clause_default_ctor (tree clause, tree decl, tree outer)
455 tree type = TREE_TYPE (decl), size, ptr, cond, then_b, else_b;
456 stmtblock_t block, cond_block;
458 gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_PRIVATE
459 || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LASTPRIVATE
460 || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR
461 || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_REDUCTION);
463 if ((! GFC_DESCRIPTOR_TYPE_P (type)
464 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
465 && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)))
467 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
469 gcc_assert (outer);
470 gfc_start_block (&block);
471 tree tem = gfc_walk_alloc_comps (outer, decl,
472 OMP_CLAUSE_DECL (clause),
473 WALK_ALLOC_COMPS_DEFAULT_CTOR);
474 gfc_add_expr_to_block (&block, tem);
475 return gfc_finish_block (&block);
477 return NULL_TREE;
480 gcc_assert (outer != NULL_TREE);
482 /* Allocatable arrays and scalars in PRIVATE clauses need to be set to
483 "not currently allocated" allocation status if outer
484 array is "not currently allocated", otherwise should be allocated. */
485 gfc_start_block (&block);
487 gfc_init_block (&cond_block);
489 if (GFC_DESCRIPTOR_TYPE_P (type))
491 gfc_add_modify (&cond_block, decl, outer);
492 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
493 size = gfc_conv_descriptor_ubound_get (decl, rank);
494 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
495 size,
496 gfc_conv_descriptor_lbound_get (decl, rank));
497 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
498 size, gfc_index_one_node);
499 if (GFC_TYPE_ARRAY_RANK (type) > 1)
500 size = fold_build2_loc (input_location, MULT_EXPR,
501 gfc_array_index_type, size,
502 gfc_conv_descriptor_stride_get (decl, rank));
503 tree esize = fold_convert (gfc_array_index_type,
504 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
505 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
506 size, esize);
507 size = unshare_expr (size);
508 size = gfc_evaluate_now (fold_convert (size_type_node, size),
509 &cond_block);
511 else
512 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
513 ptr = gfc_create_var (pvoid_type_node, NULL);
514 gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
515 if (GFC_DESCRIPTOR_TYPE_P (type))
516 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl), ptr);
517 else
518 gfc_add_modify (&cond_block, unshare_expr (decl),
519 fold_convert (TREE_TYPE (decl), ptr));
520 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
522 tree tem = gfc_walk_alloc_comps (outer, decl,
523 OMP_CLAUSE_DECL (clause),
524 WALK_ALLOC_COMPS_DEFAULT_CTOR);
525 gfc_add_expr_to_block (&cond_block, tem);
527 then_b = gfc_finish_block (&cond_block);
529 /* Reduction clause requires allocated ALLOCATABLE. */
530 if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_REDUCTION)
532 gfc_init_block (&cond_block);
533 if (GFC_DESCRIPTOR_TYPE_P (type))
534 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl),
535 null_pointer_node);
536 else
537 gfc_add_modify (&cond_block, unshare_expr (decl),
538 build_zero_cst (TREE_TYPE (decl)));
539 else_b = gfc_finish_block (&cond_block);
541 tree tem = fold_convert (pvoid_type_node,
542 GFC_DESCRIPTOR_TYPE_P (type)
543 ? gfc_conv_descriptor_data_get (outer) : outer);
544 tem = unshare_expr (tem);
545 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
546 tem, null_pointer_node);
547 gfc_add_expr_to_block (&block,
548 build3_loc (input_location, COND_EXPR,
549 void_type_node, cond, then_b,
550 else_b));
552 else
553 gfc_add_expr_to_block (&block, then_b);
555 return gfc_finish_block (&block);
558 /* Build and return code for a copy constructor from SRC to DEST. */
560 tree
561 gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
563 tree type = TREE_TYPE (dest), ptr, size, call;
564 tree cond, then_b, else_b;
565 stmtblock_t block, cond_block;
567 gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE
568 || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
570 if ((! GFC_DESCRIPTOR_TYPE_P (type)
571 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
572 && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)))
574 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
576 gfc_start_block (&block);
577 gfc_add_modify (&block, dest, src);
578 tree tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause),
579 WALK_ALLOC_COMPS_COPY_CTOR);
580 gfc_add_expr_to_block (&block, tem);
581 return gfc_finish_block (&block);
583 else
584 return build2_v (MODIFY_EXPR, dest, src);
587 /* Allocatable arrays in FIRSTPRIVATE clauses need to be allocated
588 and copied from SRC. */
589 gfc_start_block (&block);
591 gfc_init_block (&cond_block);
593 gfc_add_modify (&cond_block, dest, src);
594 if (GFC_DESCRIPTOR_TYPE_P (type))
596 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
597 size = gfc_conv_descriptor_ubound_get (dest, rank);
598 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
599 size,
600 gfc_conv_descriptor_lbound_get (dest, rank));
601 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
602 size, gfc_index_one_node);
603 if (GFC_TYPE_ARRAY_RANK (type) > 1)
604 size = fold_build2_loc (input_location, MULT_EXPR,
605 gfc_array_index_type, size,
606 gfc_conv_descriptor_stride_get (dest, rank));
607 tree esize = fold_convert (gfc_array_index_type,
608 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
609 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
610 size, esize);
611 size = unshare_expr (size);
612 size = gfc_evaluate_now (fold_convert (size_type_node, size),
613 &cond_block);
615 else
616 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
617 ptr = gfc_create_var (pvoid_type_node, NULL);
618 gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
619 if (GFC_DESCRIPTOR_TYPE_P (type))
620 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest), ptr);
621 else
622 gfc_add_modify (&cond_block, unshare_expr (dest),
623 fold_convert (TREE_TYPE (dest), ptr));
625 tree srcptr = GFC_DESCRIPTOR_TYPE_P (type)
626 ? gfc_conv_descriptor_data_get (src) : src;
627 srcptr = unshare_expr (srcptr);
628 srcptr = fold_convert (pvoid_type_node, srcptr);
629 call = build_call_expr_loc (input_location,
630 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr,
631 srcptr, size);
632 gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
633 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
635 tree tem = gfc_walk_alloc_comps (src, dest,
636 OMP_CLAUSE_DECL (clause),
637 WALK_ALLOC_COMPS_COPY_CTOR);
638 gfc_add_expr_to_block (&cond_block, tem);
640 then_b = gfc_finish_block (&cond_block);
642 gfc_init_block (&cond_block);
643 if (GFC_DESCRIPTOR_TYPE_P (type))
644 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest),
645 null_pointer_node);
646 else
647 gfc_add_modify (&cond_block, unshare_expr (dest),
648 build_zero_cst (TREE_TYPE (dest)));
649 else_b = gfc_finish_block (&cond_block);
651 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
652 unshare_expr (srcptr), null_pointer_node);
653 gfc_add_expr_to_block (&block,
654 build3_loc (input_location, COND_EXPR,
655 void_type_node, cond, then_b, else_b));
657 return gfc_finish_block (&block);
660 /* Similarly, except use an intrinsic or pointer assignment operator
661 instead. */
663 tree
664 gfc_omp_clause_assign_op (tree clause, tree dest, tree src)
666 tree type = TREE_TYPE (dest), ptr, size, call, nonalloc;
667 tree cond, then_b, else_b;
668 stmtblock_t block, cond_block, cond_block2, inner_block;
670 if ((! GFC_DESCRIPTOR_TYPE_P (type)
671 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
672 && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)))
674 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
676 gfc_start_block (&block);
677 /* First dealloc any allocatable components in DEST. */
678 tree tem = gfc_walk_alloc_comps (dest, NULL_TREE,
679 OMP_CLAUSE_DECL (clause),
680 WALK_ALLOC_COMPS_DTOR);
681 gfc_add_expr_to_block (&block, tem);
682 /* Then copy over toplevel data. */
683 gfc_add_modify (&block, dest, src);
684 /* Finally allocate any allocatable components and copy. */
685 tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause),
686 WALK_ALLOC_COMPS_COPY_CTOR);
687 gfc_add_expr_to_block (&block, tem);
688 return gfc_finish_block (&block);
690 else
691 return build2_v (MODIFY_EXPR, dest, src);
694 gfc_start_block (&block);
696 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
698 then_b = gfc_walk_alloc_comps (dest, NULL_TREE, OMP_CLAUSE_DECL (clause),
699 WALK_ALLOC_COMPS_DTOR);
700 tree tem = fold_convert (pvoid_type_node,
701 GFC_DESCRIPTOR_TYPE_P (type)
702 ? gfc_conv_descriptor_data_get (dest) : dest);
703 tem = unshare_expr (tem);
704 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
705 tem, null_pointer_node);
706 tem = build3_loc (input_location, COND_EXPR, void_type_node, cond,
707 then_b, build_empty_stmt (input_location));
708 gfc_add_expr_to_block (&block, tem);
711 gfc_init_block (&cond_block);
713 if (GFC_DESCRIPTOR_TYPE_P (type))
715 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
716 size = gfc_conv_descriptor_ubound_get (src, rank);
717 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
718 size,
719 gfc_conv_descriptor_lbound_get (src, rank));
720 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
721 size, gfc_index_one_node);
722 if (GFC_TYPE_ARRAY_RANK (type) > 1)
723 size = fold_build2_loc (input_location, MULT_EXPR,
724 gfc_array_index_type, size,
725 gfc_conv_descriptor_stride_get (src, rank));
726 tree esize = fold_convert (gfc_array_index_type,
727 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
728 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
729 size, esize);
730 size = unshare_expr (size);
731 size = gfc_evaluate_now (fold_convert (size_type_node, size),
732 &cond_block);
734 else
735 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
736 ptr = gfc_create_var (pvoid_type_node, NULL);
738 tree destptr = GFC_DESCRIPTOR_TYPE_P (type)
739 ? gfc_conv_descriptor_data_get (dest) : dest;
740 destptr = unshare_expr (destptr);
741 destptr = fold_convert (pvoid_type_node, destptr);
742 gfc_add_modify (&cond_block, ptr, destptr);
744 nonalloc = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
745 destptr, null_pointer_node);
746 cond = nonalloc;
747 if (GFC_DESCRIPTOR_TYPE_P (type))
749 int i;
750 for (i = 0; i < GFC_TYPE_ARRAY_RANK (type); i++)
752 tree rank = gfc_rank_cst[i];
753 tree tem = gfc_conv_descriptor_ubound_get (src, rank);
754 tem = fold_build2_loc (input_location, MINUS_EXPR,
755 gfc_array_index_type, tem,
756 gfc_conv_descriptor_lbound_get (src, rank));
757 tem = fold_build2_loc (input_location, PLUS_EXPR,
758 gfc_array_index_type, tem,
759 gfc_conv_descriptor_lbound_get (dest, rank));
760 tem = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
761 tem, gfc_conv_descriptor_ubound_get (dest,
762 rank));
763 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
764 boolean_type_node, cond, tem);
768 gfc_init_block (&cond_block2);
770 if (GFC_DESCRIPTOR_TYPE_P (type))
772 gfc_init_block (&inner_block);
773 gfc_allocate_using_malloc (&inner_block, ptr, size, NULL_TREE);
774 then_b = gfc_finish_block (&inner_block);
776 gfc_init_block (&inner_block);
777 gfc_add_modify (&inner_block, ptr,
778 gfc_call_realloc (&inner_block, ptr, size));
779 else_b = gfc_finish_block (&inner_block);
781 gfc_add_expr_to_block (&cond_block2,
782 build3_loc (input_location, COND_EXPR,
783 void_type_node,
784 unshare_expr (nonalloc),
785 then_b, else_b));
786 gfc_add_modify (&cond_block2, dest, src);
787 gfc_conv_descriptor_data_set (&cond_block2, unshare_expr (dest), ptr);
789 else
791 gfc_allocate_using_malloc (&cond_block2, ptr, size, NULL_TREE);
792 gfc_add_modify (&cond_block2, unshare_expr (dest),
793 fold_convert (type, ptr));
795 then_b = gfc_finish_block (&cond_block2);
796 else_b = build_empty_stmt (input_location);
798 gfc_add_expr_to_block (&cond_block,
799 build3_loc (input_location, COND_EXPR,
800 void_type_node, unshare_expr (cond),
801 then_b, else_b));
803 tree srcptr = GFC_DESCRIPTOR_TYPE_P (type)
804 ? gfc_conv_descriptor_data_get (src) : src;
805 srcptr = unshare_expr (srcptr);
806 srcptr = fold_convert (pvoid_type_node, srcptr);
807 call = build_call_expr_loc (input_location,
808 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr,
809 srcptr, size);
810 gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
811 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
813 tree tem = gfc_walk_alloc_comps (src, dest,
814 OMP_CLAUSE_DECL (clause),
815 WALK_ALLOC_COMPS_COPY_CTOR);
816 gfc_add_expr_to_block (&cond_block, tem);
818 then_b = gfc_finish_block (&cond_block);
820 if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_COPYIN)
822 gfc_init_block (&cond_block);
823 if (GFC_DESCRIPTOR_TYPE_P (type))
824 gfc_add_expr_to_block (&cond_block,
825 gfc_trans_dealloc_allocated (unshare_expr (dest),
826 false, NULL));
827 else
829 destptr = gfc_evaluate_now (destptr, &cond_block);
830 gfc_add_expr_to_block (&cond_block, gfc_call_free (destptr));
831 gfc_add_modify (&cond_block, unshare_expr (dest),
832 build_zero_cst (TREE_TYPE (dest)));
834 else_b = gfc_finish_block (&cond_block);
836 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
837 unshare_expr (srcptr), null_pointer_node);
838 gfc_add_expr_to_block (&block,
839 build3_loc (input_location, COND_EXPR,
840 void_type_node, cond,
841 then_b, else_b));
843 else
844 gfc_add_expr_to_block (&block, then_b);
846 return gfc_finish_block (&block);
849 static void
850 gfc_omp_linear_clause_add_loop (stmtblock_t *block, tree dest, tree src,
851 tree add, tree nelems)
853 stmtblock_t tmpblock;
854 tree desta, srca, index = gfc_create_var (gfc_array_index_type, "S");
855 nelems = gfc_evaluate_now (nelems, block);
857 gfc_init_block (&tmpblock);
858 if (TREE_CODE (TREE_TYPE (dest)) == ARRAY_TYPE)
860 desta = gfc_build_array_ref (dest, index, NULL);
861 srca = gfc_build_array_ref (src, index, NULL);
863 else
865 gcc_assert (POINTER_TYPE_P (TREE_TYPE (dest)));
866 tree idx = fold_build2 (MULT_EXPR, sizetype,
867 fold_convert (sizetype, index),
868 TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (dest))));
869 desta = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR,
870 TREE_TYPE (dest), dest,
871 idx));
872 srca = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR,
873 TREE_TYPE (src), src,
874 idx));
876 gfc_add_modify (&tmpblock, desta,
877 fold_build2 (PLUS_EXPR, TREE_TYPE (desta),
878 srca, add));
880 gfc_loopinfo loop;
881 gfc_init_loopinfo (&loop);
882 loop.dimen = 1;
883 loop.from[0] = gfc_index_zero_node;
884 loop.loopvar[0] = index;
885 loop.to[0] = nelems;
886 gfc_trans_scalarizing_loops (&loop, &tmpblock);
887 gfc_add_block_to_block (block, &loop.pre);
890 /* Build and return code for a constructor of DEST that initializes
891 it to SRC plus ADD (ADD is scalar integer). */
893 tree
894 gfc_omp_clause_linear_ctor (tree clause, tree dest, tree src, tree add)
896 tree type = TREE_TYPE (dest), ptr, size, nelems = NULL_TREE;
897 stmtblock_t block;
899 gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
901 gfc_start_block (&block);
902 add = gfc_evaluate_now (add, &block);
904 if ((! GFC_DESCRIPTOR_TYPE_P (type)
905 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
906 && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)))
908 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
909 if (!TYPE_DOMAIN (type)
910 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE
911 || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node
912 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node)
914 nelems = fold_build2 (EXACT_DIV_EXPR, sizetype,
915 TYPE_SIZE_UNIT (type),
916 TYPE_SIZE_UNIT (TREE_TYPE (type)));
917 nelems = size_binop (MINUS_EXPR, nelems, size_one_node);
919 else
920 nelems = array_type_nelts (type);
921 nelems = fold_convert (gfc_array_index_type, nelems);
923 gfc_omp_linear_clause_add_loop (&block, dest, src, add, nelems);
924 return gfc_finish_block (&block);
927 /* Allocatable arrays in LINEAR clauses need to be allocated
928 and copied from SRC. */
929 gfc_add_modify (&block, dest, src);
930 if (GFC_DESCRIPTOR_TYPE_P (type))
932 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
933 size = gfc_conv_descriptor_ubound_get (dest, rank);
934 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
935 size,
936 gfc_conv_descriptor_lbound_get (dest, rank));
937 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
938 size, gfc_index_one_node);
939 if (GFC_TYPE_ARRAY_RANK (type) > 1)
940 size = fold_build2_loc (input_location, MULT_EXPR,
941 gfc_array_index_type, size,
942 gfc_conv_descriptor_stride_get (dest, rank));
943 tree esize = fold_convert (gfc_array_index_type,
944 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
945 nelems = gfc_evaluate_now (unshare_expr (size), &block);
946 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
947 nelems, unshare_expr (esize));
948 size = gfc_evaluate_now (fold_convert (size_type_node, size),
949 &block);
950 nelems = fold_build2_loc (input_location, MINUS_EXPR,
951 gfc_array_index_type, nelems,
952 gfc_index_one_node);
954 else
955 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
956 ptr = gfc_create_var (pvoid_type_node, NULL);
957 gfc_allocate_using_malloc (&block, ptr, size, NULL_TREE);
958 if (GFC_DESCRIPTOR_TYPE_P (type))
960 gfc_conv_descriptor_data_set (&block, unshare_expr (dest), ptr);
961 tree etype = gfc_get_element_type (type);
962 ptr = fold_convert (build_pointer_type (etype), ptr);
963 tree srcptr = gfc_conv_descriptor_data_get (unshare_expr (src));
964 srcptr = fold_convert (build_pointer_type (etype), srcptr);
965 gfc_omp_linear_clause_add_loop (&block, ptr, srcptr, add, nelems);
967 else
969 gfc_add_modify (&block, unshare_expr (dest),
970 fold_convert (TREE_TYPE (dest), ptr));
971 ptr = fold_convert (TREE_TYPE (dest), ptr);
972 tree dstm = build_fold_indirect_ref (ptr);
973 tree srcm = build_fold_indirect_ref (unshare_expr (src));
974 gfc_add_modify (&block, dstm,
975 fold_build2 (PLUS_EXPR, TREE_TYPE (add), srcm, add));
977 return gfc_finish_block (&block);
980 /* Build and return code destructing DECL. Return NULL if nothing
981 to be done. */
983 tree
984 gfc_omp_clause_dtor (tree clause, tree decl)
986 tree type = TREE_TYPE (decl), tem;
988 if ((! GFC_DESCRIPTOR_TYPE_P (type)
989 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
990 && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)))
992 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
993 return gfc_walk_alloc_comps (decl, NULL_TREE,
994 OMP_CLAUSE_DECL (clause),
995 WALK_ALLOC_COMPS_DTOR);
996 return NULL_TREE;
999 if (GFC_DESCRIPTOR_TYPE_P (type))
1000 /* Allocatable arrays in FIRSTPRIVATE/LASTPRIVATE etc. clauses need
1001 to be deallocated if they were allocated. */
1002 tem = gfc_trans_dealloc_allocated (decl, false, NULL);
1003 else
1004 tem = gfc_call_free (decl);
1005 tem = gfc_omp_unshare_expr (tem);
1007 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
1009 stmtblock_t block;
1010 tree then_b;
1012 gfc_init_block (&block);
1013 gfc_add_expr_to_block (&block,
1014 gfc_walk_alloc_comps (decl, NULL_TREE,
1015 OMP_CLAUSE_DECL (clause),
1016 WALK_ALLOC_COMPS_DTOR));
1017 gfc_add_expr_to_block (&block, tem);
1018 then_b = gfc_finish_block (&block);
1020 tem = fold_convert (pvoid_type_node,
1021 GFC_DESCRIPTOR_TYPE_P (type)
1022 ? gfc_conv_descriptor_data_get (decl) : decl);
1023 tem = unshare_expr (tem);
1024 tree cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1025 tem, null_pointer_node);
1026 tem = build3_loc (input_location, COND_EXPR, void_type_node, cond,
1027 then_b, build_empty_stmt (input_location));
1029 return tem;
1033 void
1034 gfc_omp_finish_clause (tree c, gimple_seq *pre_p)
1036 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
1037 return;
1039 tree decl = OMP_CLAUSE_DECL (c);
1040 tree c2 = NULL_TREE, c3 = NULL_TREE, c4 = NULL_TREE;
1041 if (POINTER_TYPE_P (TREE_TYPE (decl)))
1043 if (!gfc_omp_privatize_by_reference (decl)
1044 && !GFC_DECL_GET_SCALAR_POINTER (decl)
1045 && !GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
1046 && !GFC_DECL_CRAY_POINTEE (decl)
1047 && !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
1048 return;
1049 tree orig_decl = decl;
1050 c4 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
1051 OMP_CLAUSE_SET_MAP_KIND (c4, GOMP_MAP_POINTER);
1052 OMP_CLAUSE_DECL (c4) = decl;
1053 OMP_CLAUSE_SIZE (c4) = size_int (0);
1054 decl = build_fold_indirect_ref (decl);
1055 OMP_CLAUSE_DECL (c) = decl;
1056 OMP_CLAUSE_SIZE (c) = NULL_TREE;
1057 if (TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE
1058 && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
1059 || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
1061 c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
1062 OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_POINTER);
1063 OMP_CLAUSE_DECL (c3) = unshare_expr (decl);
1064 OMP_CLAUSE_SIZE (c3) = size_int (0);
1065 decl = build_fold_indirect_ref (decl);
1066 OMP_CLAUSE_DECL (c) = decl;
1069 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
1071 stmtblock_t block;
1072 gfc_start_block (&block);
1073 tree type = TREE_TYPE (decl);
1074 tree ptr = gfc_conv_descriptor_data_get (decl);
1075 ptr = fold_convert (build_pointer_type (char_type_node), ptr);
1076 ptr = build_fold_indirect_ref (ptr);
1077 OMP_CLAUSE_DECL (c) = ptr;
1078 c2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
1079 OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_TO_PSET);
1080 OMP_CLAUSE_DECL (c2) = decl;
1081 OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (type);
1082 c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
1083 OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_POINTER);
1084 OMP_CLAUSE_DECL (c3) = gfc_conv_descriptor_data_get (decl);
1085 OMP_CLAUSE_SIZE (c3) = size_int (0);
1086 tree size = create_tmp_var (gfc_array_index_type);
1087 tree elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
1088 elemsz = fold_convert (gfc_array_index_type, elemsz);
1089 if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER
1090 || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT)
1092 stmtblock_t cond_block;
1093 tree tem, then_b, else_b, zero, cond;
1095 gfc_init_block (&cond_block);
1096 tem = gfc_full_array_size (&cond_block, decl,
1097 GFC_TYPE_ARRAY_RANK (type));
1098 gfc_add_modify (&cond_block, size, tem);
1099 gfc_add_modify (&cond_block, size,
1100 fold_build2 (MULT_EXPR, gfc_array_index_type,
1101 size, elemsz));
1102 then_b = gfc_finish_block (&cond_block);
1103 gfc_init_block (&cond_block);
1104 zero = build_int_cst (gfc_array_index_type, 0);
1105 gfc_add_modify (&cond_block, size, zero);
1106 else_b = gfc_finish_block (&cond_block);
1107 tem = gfc_conv_descriptor_data_get (decl);
1108 tem = fold_convert (pvoid_type_node, tem);
1109 cond = fold_build2_loc (input_location, NE_EXPR,
1110 boolean_type_node, tem, null_pointer_node);
1111 gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR,
1112 void_type_node, cond,
1113 then_b, else_b));
1115 else
1117 gfc_add_modify (&block, size,
1118 gfc_full_array_size (&block, decl,
1119 GFC_TYPE_ARRAY_RANK (type)));
1120 gfc_add_modify (&block, size,
1121 fold_build2 (MULT_EXPR, gfc_array_index_type,
1122 size, elemsz));
1124 OMP_CLAUSE_SIZE (c) = size;
1125 tree stmt = gfc_finish_block (&block);
1126 gimplify_and_add (stmt, pre_p);
1128 tree last = c;
1129 if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
1130 OMP_CLAUSE_SIZE (c)
1131 = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
1132 : TYPE_SIZE_UNIT (TREE_TYPE (decl));
1133 if (c2)
1135 OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (last);
1136 OMP_CLAUSE_CHAIN (last) = c2;
1137 last = c2;
1139 if (c3)
1141 OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (last);
1142 OMP_CLAUSE_CHAIN (last) = c3;
1143 last = c3;
1145 if (c4)
1147 OMP_CLAUSE_CHAIN (c4) = OMP_CLAUSE_CHAIN (last);
1148 OMP_CLAUSE_CHAIN (last) = c4;
1149 last = c4;
1154 /* Return true if DECL's DECL_VALUE_EXPR (if any) should be
1155 disregarded in OpenMP construct, because it is going to be
1156 remapped during OpenMP lowering. SHARED is true if DECL
1157 is going to be shared, false if it is going to be privatized. */
1159 bool
1160 gfc_omp_disregard_value_expr (tree decl, bool shared)
1162 if (GFC_DECL_COMMON_OR_EQUIV (decl)
1163 && DECL_HAS_VALUE_EXPR_P (decl))
1165 tree value = DECL_VALUE_EXPR (decl);
1167 if (TREE_CODE (value) == COMPONENT_REF
1168 && TREE_CODE (TREE_OPERAND (value, 0)) == VAR_DECL
1169 && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
1171 /* If variable in COMMON or EQUIVALENCE is privatized, return
1172 true, as just that variable is supposed to be privatized,
1173 not the whole COMMON or whole EQUIVALENCE.
1174 For shared variables in COMMON or EQUIVALENCE, let them be
1175 gimplified to DECL_VALUE_EXPR, so that for multiple shared vars
1176 from the same COMMON or EQUIVALENCE just one sharing of the
1177 whole COMMON or EQUIVALENCE is enough. */
1178 return ! shared;
1182 if (GFC_DECL_RESULT (decl) && DECL_HAS_VALUE_EXPR_P (decl))
1183 return ! shared;
1185 return false;
1188 /* Return true if DECL that is shared iff SHARED is true should
1189 be put into OMP_CLAUSE_PRIVATE with OMP_CLAUSE_PRIVATE_DEBUG
1190 flag set. */
1192 bool
1193 gfc_omp_private_debug_clause (tree decl, bool shared)
1195 if (GFC_DECL_CRAY_POINTEE (decl))
1196 return true;
1198 if (GFC_DECL_COMMON_OR_EQUIV (decl)
1199 && DECL_HAS_VALUE_EXPR_P (decl))
1201 tree value = DECL_VALUE_EXPR (decl);
1203 if (TREE_CODE (value) == COMPONENT_REF
1204 && TREE_CODE (TREE_OPERAND (value, 0)) == VAR_DECL
1205 && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
1206 return shared;
1209 return false;
1212 /* Register language specific type size variables as potentially OpenMP
1213 firstprivate variables. */
1215 void
1216 gfc_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
1218 if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
1220 int r;
1222 gcc_assert (TYPE_LANG_SPECIFIC (type) != NULL);
1223 for (r = 0; r < GFC_TYPE_ARRAY_RANK (type); r++)
1225 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_LBOUND (type, r));
1226 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_UBOUND (type, r));
1227 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_STRIDE (type, r));
1229 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_SIZE (type));
1230 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_OFFSET (type));
1235 static inline tree
1236 gfc_trans_add_clause (tree node, tree tail)
1238 OMP_CLAUSE_CHAIN (node) = tail;
1239 return node;
1242 static tree
1243 gfc_trans_omp_variable (gfc_symbol *sym, bool declare_simd)
1245 if (declare_simd)
1247 int cnt = 0;
1248 gfc_symbol *proc_sym;
1249 gfc_formal_arglist *f;
1251 gcc_assert (sym->attr.dummy);
1252 proc_sym = sym->ns->proc_name;
1253 if (proc_sym->attr.entry_master)
1254 ++cnt;
1255 if (gfc_return_by_reference (proc_sym))
1257 ++cnt;
1258 if (proc_sym->ts.type == BT_CHARACTER)
1259 ++cnt;
1261 for (f = gfc_sym_get_dummy_args (proc_sym); f; f = f->next)
1262 if (f->sym == sym)
1263 break;
1264 else if (f->sym)
1265 ++cnt;
1266 gcc_assert (f);
1267 return build_int_cst (integer_type_node, cnt);
1270 tree t = gfc_get_symbol_decl (sym);
1271 tree parent_decl;
1272 int parent_flag;
1273 bool return_value;
1274 bool alternate_entry;
1275 bool entry_master;
1277 return_value = sym->attr.function && sym->result == sym;
1278 alternate_entry = sym->attr.function && sym->attr.entry
1279 && sym->result == sym;
1280 entry_master = sym->attr.result
1281 && sym->ns->proc_name->attr.entry_master
1282 && !gfc_return_by_reference (sym->ns->proc_name);
1283 parent_decl = current_function_decl
1284 ? DECL_CONTEXT (current_function_decl) : NULL_TREE;
1286 if ((t == parent_decl && return_value)
1287 || (sym->ns && sym->ns->proc_name
1288 && sym->ns->proc_name->backend_decl == parent_decl
1289 && (alternate_entry || entry_master)))
1290 parent_flag = 1;
1291 else
1292 parent_flag = 0;
1294 /* Special case for assigning the return value of a function.
1295 Self recursive functions must have an explicit return value. */
1296 if (return_value && (t == current_function_decl || parent_flag))
1297 t = gfc_get_fake_result_decl (sym, parent_flag);
1299 /* Similarly for alternate entry points. */
1300 else if (alternate_entry
1301 && (sym->ns->proc_name->backend_decl == current_function_decl
1302 || parent_flag))
1304 gfc_entry_list *el = NULL;
1306 for (el = sym->ns->entries; el; el = el->next)
1307 if (sym == el->sym)
1309 t = gfc_get_fake_result_decl (sym, parent_flag);
1310 break;
1314 else if (entry_master
1315 && (sym->ns->proc_name->backend_decl == current_function_decl
1316 || parent_flag))
1317 t = gfc_get_fake_result_decl (sym, parent_flag);
1319 return t;
1322 static tree
1323 gfc_trans_omp_variable_list (enum omp_clause_code code,
1324 gfc_omp_namelist *namelist, tree list,
1325 bool declare_simd)
1327 for (; namelist != NULL; namelist = namelist->next)
1328 if (namelist->sym->attr.referenced || declare_simd)
1330 tree t = gfc_trans_omp_variable (namelist->sym, declare_simd);
1331 if (t != error_mark_node)
1333 tree node = build_omp_clause (input_location, code);
1334 OMP_CLAUSE_DECL (node) = t;
1335 list = gfc_trans_add_clause (node, list);
1338 return list;
1341 struct omp_udr_find_orig_data
1343 gfc_omp_udr *omp_udr;
1344 bool omp_orig_seen;
1347 static int
1348 omp_udr_find_orig (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
1349 void *data)
1351 struct omp_udr_find_orig_data *cd = (struct omp_udr_find_orig_data *) data;
1352 if ((*e)->expr_type == EXPR_VARIABLE
1353 && (*e)->symtree->n.sym == cd->omp_udr->omp_orig)
1354 cd->omp_orig_seen = true;
1356 return 0;
1359 static void
1360 gfc_trans_omp_array_reduction_or_udr (tree c, gfc_omp_namelist *n, locus where)
1362 gfc_symbol *sym = n->sym;
1363 gfc_symtree *root1 = NULL, *root2 = NULL, *root3 = NULL, *root4 = NULL;
1364 gfc_symtree *symtree1, *symtree2, *symtree3, *symtree4 = NULL;
1365 gfc_symbol init_val_sym, outer_sym, intrinsic_sym;
1366 gfc_symbol omp_var_copy[4];
1367 gfc_expr *e1, *e2, *e3, *e4;
1368 gfc_ref *ref;
1369 tree decl, backend_decl, stmt, type, outer_decl;
1370 locus old_loc = gfc_current_locus;
1371 const char *iname;
1372 bool t;
1373 gfc_omp_udr *udr = n->udr ? n->udr->udr : NULL;
1375 decl = OMP_CLAUSE_DECL (c);
1376 gfc_current_locus = where;
1377 type = TREE_TYPE (decl);
1378 outer_decl = create_tmp_var_raw (type);
1379 if (TREE_CODE (decl) == PARM_DECL
1380 && TREE_CODE (type) == REFERENCE_TYPE
1381 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type))
1382 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (type)) == GFC_ARRAY_ALLOCATABLE)
1384 decl = build_fold_indirect_ref (decl);
1385 type = TREE_TYPE (type);
1388 /* Create a fake symbol for init value. */
1389 memset (&init_val_sym, 0, sizeof (init_val_sym));
1390 init_val_sym.ns = sym->ns;
1391 init_val_sym.name = sym->name;
1392 init_val_sym.ts = sym->ts;
1393 init_val_sym.attr.referenced = 1;
1394 init_val_sym.declared_at = where;
1395 init_val_sym.attr.flavor = FL_VARIABLE;
1396 if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK)
1397 backend_decl = omp_reduction_init (c, gfc_sym_type (&init_val_sym));
1398 else if (udr->initializer_ns)
1399 backend_decl = NULL;
1400 else
1401 switch (sym->ts.type)
1403 case BT_LOGICAL:
1404 case BT_INTEGER:
1405 case BT_REAL:
1406 case BT_COMPLEX:
1407 backend_decl = build_zero_cst (gfc_sym_type (&init_val_sym));
1408 break;
1409 default:
1410 backend_decl = NULL_TREE;
1411 break;
1413 init_val_sym.backend_decl = backend_decl;
1415 /* Create a fake symbol for the outer array reference. */
1416 outer_sym = *sym;
1417 if (sym->as)
1418 outer_sym.as = gfc_copy_array_spec (sym->as);
1419 outer_sym.attr.dummy = 0;
1420 outer_sym.attr.result = 0;
1421 outer_sym.attr.flavor = FL_VARIABLE;
1422 outer_sym.backend_decl = outer_decl;
1423 if (decl != OMP_CLAUSE_DECL (c))
1424 outer_sym.backend_decl = build_fold_indirect_ref (outer_decl);
1426 /* Create fake symtrees for it. */
1427 symtree1 = gfc_new_symtree (&root1, sym->name);
1428 symtree1->n.sym = sym;
1429 gcc_assert (symtree1 == root1);
1431 symtree2 = gfc_new_symtree (&root2, sym->name);
1432 symtree2->n.sym = &init_val_sym;
1433 gcc_assert (symtree2 == root2);
1435 symtree3 = gfc_new_symtree (&root3, sym->name);
1436 symtree3->n.sym = &outer_sym;
1437 gcc_assert (symtree3 == root3);
1439 memset (omp_var_copy, 0, sizeof omp_var_copy);
1440 if (udr)
1442 omp_var_copy[0] = *udr->omp_out;
1443 omp_var_copy[1] = *udr->omp_in;
1444 *udr->omp_out = outer_sym;
1445 *udr->omp_in = *sym;
1446 if (udr->initializer_ns)
1448 omp_var_copy[2] = *udr->omp_priv;
1449 omp_var_copy[3] = *udr->omp_orig;
1450 *udr->omp_priv = *sym;
1451 *udr->omp_orig = outer_sym;
1455 /* Create expressions. */
1456 e1 = gfc_get_expr ();
1457 e1->expr_type = EXPR_VARIABLE;
1458 e1->where = where;
1459 e1->symtree = symtree1;
1460 e1->ts = sym->ts;
1461 if (sym->attr.dimension)
1463 e1->ref = ref = gfc_get_ref ();
1464 ref->type = REF_ARRAY;
1465 ref->u.ar.where = where;
1466 ref->u.ar.as = sym->as;
1467 ref->u.ar.type = AR_FULL;
1468 ref->u.ar.dimen = 0;
1470 t = gfc_resolve_expr (e1);
1471 gcc_assert (t);
1473 e2 = NULL;
1474 if (backend_decl != NULL_TREE)
1476 e2 = gfc_get_expr ();
1477 e2->expr_type = EXPR_VARIABLE;
1478 e2->where = where;
1479 e2->symtree = symtree2;
1480 e2->ts = sym->ts;
1481 t = gfc_resolve_expr (e2);
1482 gcc_assert (t);
1484 else if (udr->initializer_ns == NULL)
1486 gcc_assert (sym->ts.type == BT_DERIVED);
1487 e2 = gfc_default_initializer (&sym->ts);
1488 gcc_assert (e2);
1489 t = gfc_resolve_expr (e2);
1490 gcc_assert (t);
1492 else if (n->udr->initializer->op == EXEC_ASSIGN)
1494 e2 = gfc_copy_expr (n->udr->initializer->expr2);
1495 t = gfc_resolve_expr (e2);
1496 gcc_assert (t);
1498 if (udr && udr->initializer_ns)
1500 struct omp_udr_find_orig_data cd;
1501 cd.omp_udr = udr;
1502 cd.omp_orig_seen = false;
1503 gfc_code_walker (&n->udr->initializer,
1504 gfc_dummy_code_callback, omp_udr_find_orig, &cd);
1505 if (cd.omp_orig_seen)
1506 OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c) = 1;
1509 e3 = gfc_copy_expr (e1);
1510 e3->symtree = symtree3;
1511 t = gfc_resolve_expr (e3);
1512 gcc_assert (t);
1514 iname = NULL;
1515 e4 = NULL;
1516 switch (OMP_CLAUSE_REDUCTION_CODE (c))
1518 case PLUS_EXPR:
1519 case MINUS_EXPR:
1520 e4 = gfc_add (e3, e1);
1521 break;
1522 case MULT_EXPR:
1523 e4 = gfc_multiply (e3, e1);
1524 break;
1525 case TRUTH_ANDIF_EXPR:
1526 e4 = gfc_and (e3, e1);
1527 break;
1528 case TRUTH_ORIF_EXPR:
1529 e4 = gfc_or (e3, e1);
1530 break;
1531 case EQ_EXPR:
1532 e4 = gfc_eqv (e3, e1);
1533 break;
1534 case NE_EXPR:
1535 e4 = gfc_neqv (e3, e1);
1536 break;
1537 case MIN_EXPR:
1538 iname = "min";
1539 break;
1540 case MAX_EXPR:
1541 iname = "max";
1542 break;
1543 case BIT_AND_EXPR:
1544 iname = "iand";
1545 break;
1546 case BIT_IOR_EXPR:
1547 iname = "ior";
1548 break;
1549 case BIT_XOR_EXPR:
1550 iname = "ieor";
1551 break;
1552 case ERROR_MARK:
1553 if (n->udr->combiner->op == EXEC_ASSIGN)
1555 gfc_free_expr (e3);
1556 e3 = gfc_copy_expr (n->udr->combiner->expr1);
1557 e4 = gfc_copy_expr (n->udr->combiner->expr2);
1558 t = gfc_resolve_expr (e3);
1559 gcc_assert (t);
1560 t = gfc_resolve_expr (e4);
1561 gcc_assert (t);
1563 break;
1564 default:
1565 gcc_unreachable ();
1567 if (iname != NULL)
1569 memset (&intrinsic_sym, 0, sizeof (intrinsic_sym));
1570 intrinsic_sym.ns = sym->ns;
1571 intrinsic_sym.name = iname;
1572 intrinsic_sym.ts = sym->ts;
1573 intrinsic_sym.attr.referenced = 1;
1574 intrinsic_sym.attr.intrinsic = 1;
1575 intrinsic_sym.attr.function = 1;
1576 intrinsic_sym.result = &intrinsic_sym;
1577 intrinsic_sym.declared_at = where;
1579 symtree4 = gfc_new_symtree (&root4, iname);
1580 symtree4->n.sym = &intrinsic_sym;
1581 gcc_assert (symtree4 == root4);
1583 e4 = gfc_get_expr ();
1584 e4->expr_type = EXPR_FUNCTION;
1585 e4->where = where;
1586 e4->symtree = symtree4;
1587 e4->value.function.actual = gfc_get_actual_arglist ();
1588 e4->value.function.actual->expr = e3;
1589 e4->value.function.actual->next = gfc_get_actual_arglist ();
1590 e4->value.function.actual->next->expr = e1;
1592 if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK)
1594 /* e1 and e3 have been stored as arguments of e4, avoid sharing. */
1595 e1 = gfc_copy_expr (e1);
1596 e3 = gfc_copy_expr (e3);
1597 t = gfc_resolve_expr (e4);
1598 gcc_assert (t);
1601 /* Create the init statement list. */
1602 pushlevel ();
1603 if (e2)
1604 stmt = gfc_trans_assignment (e1, e2, false, false);
1605 else
1606 stmt = gfc_trans_call (n->udr->initializer, false,
1607 NULL_TREE, NULL_TREE, false);
1608 if (TREE_CODE (stmt) != BIND_EXPR)
1609 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
1610 else
1611 poplevel (0, 0);
1612 OMP_CLAUSE_REDUCTION_INIT (c) = stmt;
1614 /* Create the merge statement list. */
1615 pushlevel ();
1616 if (e4)
1617 stmt = gfc_trans_assignment (e3, e4, false, true);
1618 else
1619 stmt = gfc_trans_call (n->udr->combiner, false,
1620 NULL_TREE, NULL_TREE, false);
1621 if (TREE_CODE (stmt) != BIND_EXPR)
1622 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
1623 else
1624 poplevel (0, 0);
1625 OMP_CLAUSE_REDUCTION_MERGE (c) = stmt;
1627 /* And stick the placeholder VAR_DECL into the clause as well. */
1628 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = outer_decl;
1630 gfc_current_locus = old_loc;
1632 gfc_free_expr (e1);
1633 if (e2)
1634 gfc_free_expr (e2);
1635 gfc_free_expr (e3);
1636 if (e4)
1637 gfc_free_expr (e4);
1638 free (symtree1);
1639 free (symtree2);
1640 free (symtree3);
1641 free (symtree4);
1642 if (outer_sym.as)
1643 gfc_free_array_spec (outer_sym.as);
1645 if (udr)
1647 *udr->omp_out = omp_var_copy[0];
1648 *udr->omp_in = omp_var_copy[1];
1649 if (udr->initializer_ns)
1651 *udr->omp_priv = omp_var_copy[2];
1652 *udr->omp_orig = omp_var_copy[3];
1657 static tree
1658 gfc_trans_omp_reduction_list (gfc_omp_namelist *namelist, tree list,
1659 locus where)
1661 for (; namelist != NULL; namelist = namelist->next)
1662 if (namelist->sym->attr.referenced)
1664 tree t = gfc_trans_omp_variable (namelist->sym, false);
1665 if (t != error_mark_node)
1667 tree node = build_omp_clause (where.lb->location,
1668 OMP_CLAUSE_REDUCTION);
1669 OMP_CLAUSE_DECL (node) = t;
1670 switch (namelist->u.reduction_op)
1672 case OMP_REDUCTION_PLUS:
1673 OMP_CLAUSE_REDUCTION_CODE (node) = PLUS_EXPR;
1674 break;
1675 case OMP_REDUCTION_MINUS:
1676 OMP_CLAUSE_REDUCTION_CODE (node) = MINUS_EXPR;
1677 break;
1678 case OMP_REDUCTION_TIMES:
1679 OMP_CLAUSE_REDUCTION_CODE (node) = MULT_EXPR;
1680 break;
1681 case OMP_REDUCTION_AND:
1682 OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ANDIF_EXPR;
1683 break;
1684 case OMP_REDUCTION_OR:
1685 OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ORIF_EXPR;
1686 break;
1687 case OMP_REDUCTION_EQV:
1688 OMP_CLAUSE_REDUCTION_CODE (node) = EQ_EXPR;
1689 break;
1690 case OMP_REDUCTION_NEQV:
1691 OMP_CLAUSE_REDUCTION_CODE (node) = NE_EXPR;
1692 break;
1693 case OMP_REDUCTION_MAX:
1694 OMP_CLAUSE_REDUCTION_CODE (node) = MAX_EXPR;
1695 break;
1696 case OMP_REDUCTION_MIN:
1697 OMP_CLAUSE_REDUCTION_CODE (node) = MIN_EXPR;
1698 break;
1699 case OMP_REDUCTION_IAND:
1700 OMP_CLAUSE_REDUCTION_CODE (node) = BIT_AND_EXPR;
1701 break;
1702 case OMP_REDUCTION_IOR:
1703 OMP_CLAUSE_REDUCTION_CODE (node) = BIT_IOR_EXPR;
1704 break;
1705 case OMP_REDUCTION_IEOR:
1706 OMP_CLAUSE_REDUCTION_CODE (node) = BIT_XOR_EXPR;
1707 break;
1708 case OMP_REDUCTION_USER:
1709 OMP_CLAUSE_REDUCTION_CODE (node) = ERROR_MARK;
1710 break;
1711 default:
1712 gcc_unreachable ();
1714 if (namelist->sym->attr.dimension
1715 || namelist->u.reduction_op == OMP_REDUCTION_USER
1716 || namelist->sym->attr.allocatable)
1717 gfc_trans_omp_array_reduction_or_udr (node, namelist, where);
1718 list = gfc_trans_add_clause (node, list);
1721 return list;
1724 static inline tree
1725 gfc_convert_expr_to_tree (stmtblock_t *block, gfc_expr *expr)
1727 gfc_se se;
1728 tree result;
1730 gfc_init_se (&se, NULL );
1731 gfc_conv_expr (&se, expr);
1732 gfc_add_block_to_block (block, &se.pre);
1733 result = gfc_evaluate_now (se.expr, block);
1734 gfc_add_block_to_block (block, &se.post);
1736 return result;
1739 static tree
1740 gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
1741 locus where, bool declare_simd = false)
1743 tree omp_clauses = NULL_TREE, chunk_size, c;
1744 int list;
1745 enum omp_clause_code clause_code;
1746 gfc_se se;
1748 if (clauses == NULL)
1749 return NULL_TREE;
1751 for (list = 0; list < OMP_LIST_NUM; list++)
1753 gfc_omp_namelist *n = clauses->lists[list];
1755 if (n == NULL)
1756 continue;
1757 switch (list)
1759 case OMP_LIST_REDUCTION:
1760 omp_clauses = gfc_trans_omp_reduction_list (n, omp_clauses, where);
1761 break;
1762 case OMP_LIST_PRIVATE:
1763 clause_code = OMP_CLAUSE_PRIVATE;
1764 goto add_clause;
1765 case OMP_LIST_SHARED:
1766 clause_code = OMP_CLAUSE_SHARED;
1767 goto add_clause;
1768 case OMP_LIST_FIRSTPRIVATE:
1769 clause_code = OMP_CLAUSE_FIRSTPRIVATE;
1770 goto add_clause;
1771 case OMP_LIST_LASTPRIVATE:
1772 clause_code = OMP_CLAUSE_LASTPRIVATE;
1773 goto add_clause;
1774 case OMP_LIST_COPYIN:
1775 clause_code = OMP_CLAUSE_COPYIN;
1776 goto add_clause;
1777 case OMP_LIST_COPYPRIVATE:
1778 clause_code = OMP_CLAUSE_COPYPRIVATE;
1779 goto add_clause;
1780 case OMP_LIST_UNIFORM:
1781 clause_code = OMP_CLAUSE_UNIFORM;
1782 goto add_clause;
1783 case OMP_LIST_USE_DEVICE:
1784 clause_code = OMP_CLAUSE_USE_DEVICE;
1785 goto add_clause;
1786 case OMP_LIST_DEVICE_RESIDENT:
1787 clause_code = OMP_CLAUSE_DEVICE_RESIDENT;
1788 goto add_clause;
1789 case OMP_LIST_CACHE:
1790 clause_code = OMP_CLAUSE__CACHE_;
1791 goto add_clause;
1793 add_clause:
1794 omp_clauses
1795 = gfc_trans_omp_variable_list (clause_code, n, omp_clauses,
1796 declare_simd);
1797 break;
1798 case OMP_LIST_ALIGNED:
1799 for (; n != NULL; n = n->next)
1800 if (n->sym->attr.referenced || declare_simd)
1802 tree t = gfc_trans_omp_variable (n->sym, declare_simd);
1803 if (t != error_mark_node)
1805 tree node = build_omp_clause (input_location,
1806 OMP_CLAUSE_ALIGNED);
1807 OMP_CLAUSE_DECL (node) = t;
1808 if (n->expr)
1810 tree alignment_var;
1812 if (block == NULL)
1813 alignment_var = gfc_conv_constant_to_tree (n->expr);
1814 else
1816 gfc_init_se (&se, NULL);
1817 gfc_conv_expr (&se, n->expr);
1818 gfc_add_block_to_block (block, &se.pre);
1819 alignment_var = gfc_evaluate_now (se.expr, block);
1820 gfc_add_block_to_block (block, &se.post);
1822 OMP_CLAUSE_ALIGNED_ALIGNMENT (node) = alignment_var;
1824 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
1827 break;
1828 case OMP_LIST_LINEAR:
1830 gfc_expr *last_step_expr = NULL;
1831 tree last_step = NULL_TREE;
1833 for (; n != NULL; n = n->next)
1835 if (n->expr)
1837 last_step_expr = n->expr;
1838 last_step = NULL_TREE;
1840 if (n->sym->attr.referenced || declare_simd)
1842 tree t = gfc_trans_omp_variable (n->sym, declare_simd);
1843 if (t != error_mark_node)
1845 tree node = build_omp_clause (input_location,
1846 OMP_CLAUSE_LINEAR);
1847 OMP_CLAUSE_DECL (node) = t;
1848 if (last_step_expr && last_step == NULL_TREE)
1850 if (block == NULL)
1851 last_step
1852 = gfc_conv_constant_to_tree (last_step_expr);
1853 else
1855 gfc_init_se (&se, NULL);
1856 gfc_conv_expr (&se, last_step_expr);
1857 gfc_add_block_to_block (block, &se.pre);
1858 last_step = gfc_evaluate_now (se.expr, block);
1859 gfc_add_block_to_block (block, &se.post);
1862 OMP_CLAUSE_LINEAR_STEP (node)
1863 = fold_convert (gfc_typenode_for_spec (&n->sym->ts),
1864 last_step);
1865 if (n->sym->attr.dimension || n->sym->attr.allocatable)
1866 OMP_CLAUSE_LINEAR_ARRAY (node) = 1;
1867 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
1872 break;
1873 case OMP_LIST_DEPEND:
1874 for (; n != NULL; n = n->next)
1876 if (!n->sym->attr.referenced)
1877 continue;
1879 tree node = build_omp_clause (input_location, OMP_CLAUSE_DEPEND);
1880 if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
1882 tree decl = gfc_get_symbol_decl (n->sym);
1883 if (gfc_omp_privatize_by_reference (decl))
1884 decl = build_fold_indirect_ref (decl);
1885 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
1887 decl = gfc_conv_descriptor_data_get (decl);
1888 decl = fold_convert (build_pointer_type (char_type_node),
1889 decl);
1890 decl = build_fold_indirect_ref (decl);
1892 else if (DECL_P (decl))
1893 TREE_ADDRESSABLE (decl) = 1;
1894 OMP_CLAUSE_DECL (node) = decl;
1896 else
1898 tree ptr;
1899 gfc_init_se (&se, NULL);
1900 if (n->expr->ref->u.ar.type == AR_ELEMENT)
1902 gfc_conv_expr_reference (&se, n->expr);
1903 ptr = se.expr;
1905 else
1907 gfc_conv_expr_descriptor (&se, n->expr);
1908 ptr = gfc_conv_array_data (se.expr);
1910 gfc_add_block_to_block (block, &se.pre);
1911 gfc_add_block_to_block (block, &se.post);
1912 ptr = fold_convert (build_pointer_type (char_type_node),
1913 ptr);
1914 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
1916 switch (n->u.depend_op)
1918 case OMP_DEPEND_IN:
1919 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_IN;
1920 break;
1921 case OMP_DEPEND_OUT:
1922 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_OUT;
1923 break;
1924 case OMP_DEPEND_INOUT:
1925 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_INOUT;
1926 break;
1927 default:
1928 gcc_unreachable ();
1930 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
1932 break;
1933 case OMP_LIST_MAP:
1934 for (; n != NULL; n = n->next)
1936 if (!n->sym->attr.referenced)
1937 continue;
1939 tree node = build_omp_clause (input_location, OMP_CLAUSE_MAP);
1940 tree node2 = NULL_TREE;
1941 tree node3 = NULL_TREE;
1942 tree node4 = NULL_TREE;
1943 tree decl = gfc_get_symbol_decl (n->sym);
1944 if (DECL_P (decl))
1945 TREE_ADDRESSABLE (decl) = 1;
1946 if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
1948 if (POINTER_TYPE_P (TREE_TYPE (decl))
1949 && (gfc_omp_privatize_by_reference (decl)
1950 || GFC_DECL_GET_SCALAR_POINTER (decl)
1951 || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
1952 || GFC_DECL_CRAY_POINTEE (decl)
1953 || GFC_DESCRIPTOR_TYPE_P
1954 (TREE_TYPE (TREE_TYPE (decl)))))
1956 tree orig_decl = decl;
1957 node4 = build_omp_clause (input_location,
1958 OMP_CLAUSE_MAP);
1959 OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER);
1960 OMP_CLAUSE_DECL (node4) = decl;
1961 OMP_CLAUSE_SIZE (node4) = size_int (0);
1962 decl = build_fold_indirect_ref (decl);
1963 if (TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE
1964 && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
1965 || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
1967 node3 = build_omp_clause (input_location,
1968 OMP_CLAUSE_MAP);
1969 OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_POINTER);
1970 OMP_CLAUSE_DECL (node3) = decl;
1971 OMP_CLAUSE_SIZE (node3) = size_int (0);
1972 decl = build_fold_indirect_ref (decl);
1975 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
1977 tree type = TREE_TYPE (decl);
1978 tree ptr = gfc_conv_descriptor_data_get (decl);
1979 ptr = fold_convert (build_pointer_type (char_type_node),
1980 ptr);
1981 ptr = build_fold_indirect_ref (ptr);
1982 OMP_CLAUSE_DECL (node) = ptr;
1983 node2 = build_omp_clause (input_location,
1984 OMP_CLAUSE_MAP);
1985 OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
1986 OMP_CLAUSE_DECL (node2) = decl;
1987 OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
1988 node3 = build_omp_clause (input_location,
1989 OMP_CLAUSE_MAP);
1990 OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_POINTER);
1991 OMP_CLAUSE_DECL (node3)
1992 = gfc_conv_descriptor_data_get (decl);
1993 OMP_CLAUSE_SIZE (node3) = size_int (0);
1995 /* We have to check for n->sym->attr.dimension because
1996 of scalar coarrays. */
1997 if (n->sym->attr.pointer && n->sym->attr.dimension)
1999 stmtblock_t cond_block;
2000 tree size
2001 = gfc_create_var (gfc_array_index_type, NULL);
2002 tree tem, then_b, else_b, zero, cond;
2004 gfc_init_block (&cond_block);
2006 = gfc_full_array_size (&cond_block, decl,
2007 GFC_TYPE_ARRAY_RANK (type));
2008 gfc_add_modify (&cond_block, size, tem);
2009 then_b = gfc_finish_block (&cond_block);
2010 gfc_init_block (&cond_block);
2011 zero = build_int_cst (gfc_array_index_type, 0);
2012 gfc_add_modify (&cond_block, size, zero);
2013 else_b = gfc_finish_block (&cond_block);
2014 tem = gfc_conv_descriptor_data_get (decl);
2015 tem = fold_convert (pvoid_type_node, tem);
2016 cond = fold_build2_loc (input_location, NE_EXPR,
2017 boolean_type_node,
2018 tem, null_pointer_node);
2019 gfc_add_expr_to_block (block,
2020 build3_loc (input_location,
2021 COND_EXPR,
2022 void_type_node,
2023 cond, then_b,
2024 else_b));
2025 OMP_CLAUSE_SIZE (node) = size;
2027 else if (n->sym->attr.dimension)
2028 OMP_CLAUSE_SIZE (node)
2029 = gfc_full_array_size (block, decl,
2030 GFC_TYPE_ARRAY_RANK (type));
2031 if (n->sym->attr.dimension)
2033 tree elemsz
2034 = TYPE_SIZE_UNIT (gfc_get_element_type (type));
2035 elemsz = fold_convert (gfc_array_index_type, elemsz);
2036 OMP_CLAUSE_SIZE (node)
2037 = fold_build2 (MULT_EXPR, gfc_array_index_type,
2038 OMP_CLAUSE_SIZE (node), elemsz);
2041 else
2042 OMP_CLAUSE_DECL (node) = decl;
2044 else
2046 tree ptr, ptr2;
2047 gfc_init_se (&se, NULL);
2048 if (n->expr->ref->u.ar.type == AR_ELEMENT)
2050 gfc_conv_expr_reference (&se, n->expr);
2051 gfc_add_block_to_block (block, &se.pre);
2052 ptr = se.expr;
2053 OMP_CLAUSE_SIZE (node)
2054 = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
2056 else
2058 gfc_conv_expr_descriptor (&se, n->expr);
2059 ptr = gfc_conv_array_data (se.expr);
2060 tree type = TREE_TYPE (se.expr);
2061 gfc_add_block_to_block (block, &se.pre);
2062 OMP_CLAUSE_SIZE (node)
2063 = gfc_full_array_size (block, se.expr,
2064 GFC_TYPE_ARRAY_RANK (type));
2065 tree elemsz
2066 = TYPE_SIZE_UNIT (gfc_get_element_type (type));
2067 elemsz = fold_convert (gfc_array_index_type, elemsz);
2068 OMP_CLAUSE_SIZE (node)
2069 = fold_build2 (MULT_EXPR, gfc_array_index_type,
2070 OMP_CLAUSE_SIZE (node), elemsz);
2072 gfc_add_block_to_block (block, &se.post);
2073 ptr = fold_convert (build_pointer_type (char_type_node),
2074 ptr);
2075 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
2077 if (POINTER_TYPE_P (TREE_TYPE (decl))
2078 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
2080 node4 = build_omp_clause (input_location,
2081 OMP_CLAUSE_MAP);
2082 OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER);
2083 OMP_CLAUSE_DECL (node4) = decl;
2084 OMP_CLAUSE_SIZE (node4) = size_int (0);
2085 decl = build_fold_indirect_ref (decl);
2087 ptr = fold_convert (sizetype, ptr);
2088 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
2090 tree type = TREE_TYPE (decl);
2091 ptr2 = gfc_conv_descriptor_data_get (decl);
2092 node2 = build_omp_clause (input_location,
2093 OMP_CLAUSE_MAP);
2094 OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
2095 OMP_CLAUSE_DECL (node2) = decl;
2096 OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
2097 node3 = build_omp_clause (input_location,
2098 OMP_CLAUSE_MAP);
2099 OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_POINTER);
2100 OMP_CLAUSE_DECL (node3)
2101 = gfc_conv_descriptor_data_get (decl);
2103 else
2105 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2106 ptr2 = build_fold_addr_expr (decl);
2107 else
2109 gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl)));
2110 ptr2 = decl;
2112 node3 = build_omp_clause (input_location,
2113 OMP_CLAUSE_MAP);
2114 OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_POINTER);
2115 OMP_CLAUSE_DECL (node3) = decl;
2117 ptr2 = fold_convert (sizetype, ptr2);
2118 OMP_CLAUSE_SIZE (node3)
2119 = fold_build2 (MINUS_EXPR, sizetype, ptr, ptr2);
2121 switch (n->u.map_op)
2123 case OMP_MAP_ALLOC:
2124 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALLOC);
2125 break;
2126 case OMP_MAP_TO:
2127 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TO);
2128 break;
2129 case OMP_MAP_FROM:
2130 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FROM);
2131 break;
2132 case OMP_MAP_TOFROM:
2133 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TOFROM);
2134 break;
2135 case OMP_MAP_FORCE_ALLOC:
2136 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_ALLOC);
2137 break;
2138 case OMP_MAP_FORCE_DEALLOC:
2139 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_DEALLOC);
2140 break;
2141 case OMP_MAP_FORCE_TO:
2142 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TO);
2143 break;
2144 case OMP_MAP_FORCE_FROM:
2145 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_FROM);
2146 break;
2147 case OMP_MAP_FORCE_TOFROM:
2148 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TOFROM);
2149 break;
2150 case OMP_MAP_FORCE_PRESENT:
2151 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_PRESENT);
2152 break;
2153 case OMP_MAP_FORCE_DEVICEPTR:
2154 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_DEVICEPTR);
2155 break;
2156 default:
2157 gcc_unreachable ();
2159 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2160 if (node2)
2161 omp_clauses = gfc_trans_add_clause (node2, omp_clauses);
2162 if (node3)
2163 omp_clauses = gfc_trans_add_clause (node3, omp_clauses);
2164 if (node4)
2165 omp_clauses = gfc_trans_add_clause (node4, omp_clauses);
2167 break;
2168 case OMP_LIST_TO:
2169 case OMP_LIST_FROM:
2170 for (; n != NULL; n = n->next)
2172 if (!n->sym->attr.referenced)
2173 continue;
2175 tree node = build_omp_clause (input_location,
2176 list == OMP_LIST_TO
2177 ? OMP_CLAUSE_TO : OMP_CLAUSE_FROM);
2178 if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
2180 tree decl = gfc_get_symbol_decl (n->sym);
2181 if (gfc_omp_privatize_by_reference (decl))
2182 decl = build_fold_indirect_ref (decl);
2183 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
2185 tree type = TREE_TYPE (decl);
2186 tree ptr = gfc_conv_descriptor_data_get (decl);
2187 ptr = fold_convert (build_pointer_type (char_type_node),
2188 ptr);
2189 ptr = build_fold_indirect_ref (ptr);
2190 OMP_CLAUSE_DECL (node) = ptr;
2191 OMP_CLAUSE_SIZE (node)
2192 = gfc_full_array_size (block, decl,
2193 GFC_TYPE_ARRAY_RANK (type));
2194 tree elemsz
2195 = TYPE_SIZE_UNIT (gfc_get_element_type (type));
2196 elemsz = fold_convert (gfc_array_index_type, elemsz);
2197 OMP_CLAUSE_SIZE (node)
2198 = fold_build2 (MULT_EXPR, gfc_array_index_type,
2199 OMP_CLAUSE_SIZE (node), elemsz);
2201 else
2202 OMP_CLAUSE_DECL (node) = decl;
2204 else
2206 tree ptr;
2207 gfc_init_se (&se, NULL);
2208 if (n->expr->ref->u.ar.type == AR_ELEMENT)
2210 gfc_conv_expr_reference (&se, n->expr);
2211 ptr = se.expr;
2212 gfc_add_block_to_block (block, &se.pre);
2213 OMP_CLAUSE_SIZE (node)
2214 = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
2216 else
2218 gfc_conv_expr_descriptor (&se, n->expr);
2219 ptr = gfc_conv_array_data (se.expr);
2220 tree type = TREE_TYPE (se.expr);
2221 gfc_add_block_to_block (block, &se.pre);
2222 OMP_CLAUSE_SIZE (node)
2223 = gfc_full_array_size (block, se.expr,
2224 GFC_TYPE_ARRAY_RANK (type));
2225 tree elemsz
2226 = TYPE_SIZE_UNIT (gfc_get_element_type (type));
2227 elemsz = fold_convert (gfc_array_index_type, elemsz);
2228 OMP_CLAUSE_SIZE (node)
2229 = fold_build2 (MULT_EXPR, gfc_array_index_type,
2230 OMP_CLAUSE_SIZE (node), elemsz);
2232 gfc_add_block_to_block (block, &se.post);
2233 ptr = fold_convert (build_pointer_type (char_type_node),
2234 ptr);
2235 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
2237 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2239 break;
2240 default:
2241 break;
2245 if (clauses->if_expr)
2247 tree if_var;
2249 gfc_init_se (&se, NULL);
2250 gfc_conv_expr (&se, clauses->if_expr);
2251 gfc_add_block_to_block (block, &se.pre);
2252 if_var = gfc_evaluate_now (se.expr, block);
2253 gfc_add_block_to_block (block, &se.post);
2255 c = build_omp_clause (where.lb->location, OMP_CLAUSE_IF);
2256 OMP_CLAUSE_IF_EXPR (c) = if_var;
2257 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2260 if (clauses->final_expr)
2262 tree final_var;
2264 gfc_init_se (&se, NULL);
2265 gfc_conv_expr (&se, clauses->final_expr);
2266 gfc_add_block_to_block (block, &se.pre);
2267 final_var = gfc_evaluate_now (se.expr, block);
2268 gfc_add_block_to_block (block, &se.post);
2270 c = build_omp_clause (where.lb->location, OMP_CLAUSE_FINAL);
2271 OMP_CLAUSE_FINAL_EXPR (c) = final_var;
2272 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2275 if (clauses->num_threads)
2277 tree num_threads;
2279 gfc_init_se (&se, NULL);
2280 gfc_conv_expr (&se, clauses->num_threads);
2281 gfc_add_block_to_block (block, &se.pre);
2282 num_threads = gfc_evaluate_now (se.expr, block);
2283 gfc_add_block_to_block (block, &se.post);
2285 c = build_omp_clause (where.lb->location, OMP_CLAUSE_NUM_THREADS);
2286 OMP_CLAUSE_NUM_THREADS_EXPR (c) = num_threads;
2287 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2290 chunk_size = NULL_TREE;
2291 if (clauses->chunk_size)
2293 gfc_init_se (&se, NULL);
2294 gfc_conv_expr (&se, clauses->chunk_size);
2295 gfc_add_block_to_block (block, &se.pre);
2296 chunk_size = gfc_evaluate_now (se.expr, block);
2297 gfc_add_block_to_block (block, &se.post);
2300 if (clauses->sched_kind != OMP_SCHED_NONE)
2302 c = build_omp_clause (where.lb->location, OMP_CLAUSE_SCHEDULE);
2303 OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
2304 switch (clauses->sched_kind)
2306 case OMP_SCHED_STATIC:
2307 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
2308 break;
2309 case OMP_SCHED_DYNAMIC:
2310 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
2311 break;
2312 case OMP_SCHED_GUIDED:
2313 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
2314 break;
2315 case OMP_SCHED_RUNTIME:
2316 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
2317 break;
2318 case OMP_SCHED_AUTO:
2319 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
2320 break;
2321 default:
2322 gcc_unreachable ();
2324 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2327 if (clauses->default_sharing != OMP_DEFAULT_UNKNOWN)
2329 c = build_omp_clause (where.lb->location, OMP_CLAUSE_DEFAULT);
2330 switch (clauses->default_sharing)
2332 case OMP_DEFAULT_NONE:
2333 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_NONE;
2334 break;
2335 case OMP_DEFAULT_SHARED:
2336 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_SHARED;
2337 break;
2338 case OMP_DEFAULT_PRIVATE:
2339 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRIVATE;
2340 break;
2341 case OMP_DEFAULT_FIRSTPRIVATE:
2342 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
2343 break;
2344 default:
2345 gcc_unreachable ();
2347 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2350 if (clauses->nowait)
2352 c = build_omp_clause (where.lb->location, OMP_CLAUSE_NOWAIT);
2353 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2356 if (clauses->ordered)
2358 c = build_omp_clause (where.lb->location, OMP_CLAUSE_ORDERED);
2359 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2362 if (clauses->untied)
2364 c = build_omp_clause (where.lb->location, OMP_CLAUSE_UNTIED);
2365 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2368 if (clauses->mergeable)
2370 c = build_omp_clause (where.lb->location, OMP_CLAUSE_MERGEABLE);
2371 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2374 if (clauses->collapse)
2376 c = build_omp_clause (where.lb->location, OMP_CLAUSE_COLLAPSE);
2377 OMP_CLAUSE_COLLAPSE_EXPR (c)
2378 = build_int_cst (integer_type_node, clauses->collapse);
2379 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2382 if (clauses->inbranch)
2384 c = build_omp_clause (where.lb->location, OMP_CLAUSE_INBRANCH);
2385 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2388 if (clauses->notinbranch)
2390 c = build_omp_clause (where.lb->location, OMP_CLAUSE_NOTINBRANCH);
2391 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2394 switch (clauses->cancel)
2396 case OMP_CANCEL_UNKNOWN:
2397 break;
2398 case OMP_CANCEL_PARALLEL:
2399 c = build_omp_clause (where.lb->location, OMP_CLAUSE_PARALLEL);
2400 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2401 break;
2402 case OMP_CANCEL_SECTIONS:
2403 c = build_omp_clause (where.lb->location, OMP_CLAUSE_SECTIONS);
2404 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2405 break;
2406 case OMP_CANCEL_DO:
2407 c = build_omp_clause (where.lb->location, OMP_CLAUSE_FOR);
2408 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2409 break;
2410 case OMP_CANCEL_TASKGROUP:
2411 c = build_omp_clause (where.lb->location, OMP_CLAUSE_TASKGROUP);
2412 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2413 break;
2416 if (clauses->proc_bind != OMP_PROC_BIND_UNKNOWN)
2418 c = build_omp_clause (where.lb->location, OMP_CLAUSE_PROC_BIND);
2419 switch (clauses->proc_bind)
2421 case OMP_PROC_BIND_MASTER:
2422 OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_MASTER;
2423 break;
2424 case OMP_PROC_BIND_SPREAD:
2425 OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_SPREAD;
2426 break;
2427 case OMP_PROC_BIND_CLOSE:
2428 OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_CLOSE;
2429 break;
2430 default:
2431 gcc_unreachable ();
2433 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2436 if (clauses->safelen_expr)
2438 tree safelen_var;
2440 gfc_init_se (&se, NULL);
2441 gfc_conv_expr (&se, clauses->safelen_expr);
2442 gfc_add_block_to_block (block, &se.pre);
2443 safelen_var = gfc_evaluate_now (se.expr, block);
2444 gfc_add_block_to_block (block, &se.post);
2446 c = build_omp_clause (where.lb->location, OMP_CLAUSE_SAFELEN);
2447 OMP_CLAUSE_SAFELEN_EXPR (c) = safelen_var;
2448 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2451 if (clauses->simdlen_expr)
2453 c = build_omp_clause (where.lb->location, OMP_CLAUSE_SIMDLEN);
2454 OMP_CLAUSE_SIMDLEN_EXPR (c)
2455 = gfc_conv_constant_to_tree (clauses->simdlen_expr);
2456 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2459 if (clauses->num_teams)
2461 tree num_teams;
2463 gfc_init_se (&se, NULL);
2464 gfc_conv_expr (&se, clauses->num_teams);
2465 gfc_add_block_to_block (block, &se.pre);
2466 num_teams = gfc_evaluate_now (se.expr, block);
2467 gfc_add_block_to_block (block, &se.post);
2469 c = build_omp_clause (where.lb->location, OMP_CLAUSE_NUM_TEAMS);
2470 OMP_CLAUSE_NUM_TEAMS_EXPR (c) = num_teams;
2471 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2474 if (clauses->device)
2476 tree device;
2478 gfc_init_se (&se, NULL);
2479 gfc_conv_expr (&se, clauses->device);
2480 gfc_add_block_to_block (block, &se.pre);
2481 device = gfc_evaluate_now (se.expr, block);
2482 gfc_add_block_to_block (block, &se.post);
2484 c = build_omp_clause (where.lb->location, OMP_CLAUSE_DEVICE);
2485 OMP_CLAUSE_DEVICE_ID (c) = device;
2486 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2489 if (clauses->thread_limit)
2491 tree thread_limit;
2493 gfc_init_se (&se, NULL);
2494 gfc_conv_expr (&se, clauses->thread_limit);
2495 gfc_add_block_to_block (block, &se.pre);
2496 thread_limit = gfc_evaluate_now (se.expr, block);
2497 gfc_add_block_to_block (block, &se.post);
2499 c = build_omp_clause (where.lb->location, OMP_CLAUSE_THREAD_LIMIT);
2500 OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = thread_limit;
2501 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2504 chunk_size = NULL_TREE;
2505 if (clauses->dist_chunk_size)
2507 gfc_init_se (&se, NULL);
2508 gfc_conv_expr (&se, clauses->dist_chunk_size);
2509 gfc_add_block_to_block (block, &se.pre);
2510 chunk_size = gfc_evaluate_now (se.expr, block);
2511 gfc_add_block_to_block (block, &se.post);
2514 if (clauses->dist_sched_kind != OMP_SCHED_NONE)
2516 c = build_omp_clause (where.lb->location, OMP_CLAUSE_DIST_SCHEDULE);
2517 OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
2518 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2521 if (clauses->async)
2523 c = build_omp_clause (where.lb->location, OMP_CLAUSE_ASYNC);
2524 if (clauses->async_expr)
2525 OMP_CLAUSE_ASYNC_EXPR (c)
2526 = gfc_convert_expr_to_tree (block, clauses->async_expr);
2527 else
2528 OMP_CLAUSE_ASYNC_EXPR (c) = NULL;
2529 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2531 if (clauses->seq)
2533 c = build_omp_clause (where.lb->location, OMP_CLAUSE_ORDERED);
2534 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2536 if (clauses->independent)
2538 c = build_omp_clause (where.lb->location, OMP_CLAUSE_INDEPENDENT);
2539 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2541 if (clauses->wait_list)
2543 gfc_expr_list *el;
2545 for (el = clauses->wait_list; el; el = el->next)
2547 c = build_omp_clause (where.lb->location, OMP_CLAUSE_WAIT);
2548 OMP_CLAUSE_DECL (c) = gfc_convert_expr_to_tree (block, el->expr);
2549 OMP_CLAUSE_CHAIN (c) = omp_clauses;
2550 omp_clauses = c;
2553 if (clauses->num_gangs_expr)
2555 tree num_gangs_var
2556 = gfc_convert_expr_to_tree (block, clauses->num_gangs_expr);
2557 c = build_omp_clause (where.lb->location, OMP_CLAUSE_NUM_GANGS);
2558 OMP_CLAUSE_NUM_GANGS_EXPR (c) = num_gangs_var;
2559 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2561 if (clauses->num_workers_expr)
2563 tree num_workers_var
2564 = gfc_convert_expr_to_tree (block, clauses->num_workers_expr);
2565 c = build_omp_clause (where.lb->location, OMP_CLAUSE_NUM_WORKERS);
2566 OMP_CLAUSE_NUM_WORKERS_EXPR (c) = num_workers_var;
2567 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2569 if (clauses->vector_length_expr)
2571 tree vector_length_var
2572 = gfc_convert_expr_to_tree (block, clauses->vector_length_expr);
2573 c = build_omp_clause (where.lb->location, OMP_CLAUSE_VECTOR_LENGTH);
2574 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c) = vector_length_var;
2575 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2577 if (clauses->vector)
2579 if (clauses->vector_expr)
2581 tree vector_var
2582 = gfc_convert_expr_to_tree (block, clauses->vector_expr);
2583 c = build_omp_clause (where.lb->location, OMP_CLAUSE_VECTOR);
2584 OMP_CLAUSE_VECTOR_EXPR (c) = vector_var;
2585 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2587 else
2589 c = build_omp_clause (where.lb->location, OMP_CLAUSE_VECTOR);
2590 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2593 if (clauses->worker)
2595 if (clauses->worker_expr)
2597 tree worker_var
2598 = gfc_convert_expr_to_tree (block, clauses->worker_expr);
2599 c = build_omp_clause (where.lb->location, OMP_CLAUSE_WORKER);
2600 OMP_CLAUSE_WORKER_EXPR (c) = worker_var;
2601 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2603 else
2605 c = build_omp_clause (where.lb->location, OMP_CLAUSE_WORKER);
2606 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2609 if (clauses->gang)
2611 if (clauses->gang_expr)
2613 tree gang_var
2614 = gfc_convert_expr_to_tree (block, clauses->gang_expr);
2615 c = build_omp_clause (where.lb->location, OMP_CLAUSE_GANG);
2616 OMP_CLAUSE_GANG_EXPR (c) = gang_var;
2617 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2619 else
2621 c = build_omp_clause (where.lb->location, OMP_CLAUSE_GANG);
2622 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2626 return nreverse (omp_clauses);
2629 /* Like gfc_trans_code, but force creation of a BIND_EXPR around it. */
2631 static tree
2632 gfc_trans_omp_code (gfc_code *code, bool force_empty)
2634 tree stmt;
2636 pushlevel ();
2637 stmt = gfc_trans_code (code);
2638 if (TREE_CODE (stmt) != BIND_EXPR)
2640 if (!IS_EMPTY_STMT (stmt) || force_empty)
2642 tree block = poplevel (1, 0);
2643 stmt = build3_v (BIND_EXPR, NULL, stmt, block);
2645 else
2646 poplevel (0, 0);
2648 else
2649 poplevel (0, 0);
2650 return stmt;
2653 /* Trans OpenACC directives. */
2654 /* parallel, kernels, data and host_data. */
2655 static tree
2656 gfc_trans_oacc_construct (gfc_code *code)
2658 stmtblock_t block;
2659 tree stmt, oacc_clauses;
2660 enum tree_code construct_code;
2662 switch (code->op)
2664 case EXEC_OACC_PARALLEL:
2665 construct_code = OACC_PARALLEL;
2666 break;
2667 case EXEC_OACC_KERNELS:
2668 construct_code = OACC_KERNELS;
2669 break;
2670 case EXEC_OACC_DATA:
2671 construct_code = OACC_DATA;
2672 break;
2673 case EXEC_OACC_HOST_DATA:
2674 construct_code = OACC_HOST_DATA;
2675 break;
2676 default:
2677 gcc_unreachable ();
2680 gfc_start_block (&block);
2681 oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
2682 code->loc);
2683 stmt = gfc_trans_omp_code (code->block->next, true);
2684 stmt = build2_loc (input_location, construct_code, void_type_node, stmt,
2685 oacc_clauses);
2686 gfc_add_expr_to_block (&block, stmt);
2687 return gfc_finish_block (&block);
2690 /* update, enter_data, exit_data, cache. */
2691 static tree
2692 gfc_trans_oacc_executable_directive (gfc_code *code)
2694 stmtblock_t block;
2695 tree stmt, oacc_clauses;
2696 enum tree_code construct_code;
2698 switch (code->op)
2700 case EXEC_OACC_UPDATE:
2701 construct_code = OACC_UPDATE;
2702 break;
2703 case EXEC_OACC_ENTER_DATA:
2704 construct_code = OACC_ENTER_DATA;
2705 break;
2706 case EXEC_OACC_EXIT_DATA:
2707 construct_code = OACC_EXIT_DATA;
2708 break;
2709 case EXEC_OACC_CACHE:
2710 construct_code = OACC_CACHE;
2711 break;
2712 default:
2713 gcc_unreachable ();
2716 gfc_start_block (&block);
2717 oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
2718 code->loc);
2719 stmt = build1_loc (input_location, construct_code, void_type_node,
2720 oacc_clauses);
2721 gfc_add_expr_to_block (&block, stmt);
2722 return gfc_finish_block (&block);
2725 static tree
2726 gfc_trans_oacc_wait_directive (gfc_code *code)
2728 stmtblock_t block;
2729 tree stmt, t;
2730 vec<tree, va_gc> *args;
2731 int nparms = 0;
2732 gfc_expr_list *el;
2733 gfc_omp_clauses *clauses = code->ext.omp_clauses;
2734 location_t loc = input_location;
2736 for (el = clauses->wait_list; el; el = el->next)
2737 nparms++;
2739 vec_alloc (args, nparms + 2);
2740 stmt = builtin_decl_explicit (BUILT_IN_GOACC_WAIT);
2742 gfc_start_block (&block);
2744 if (clauses->async_expr)
2745 t = gfc_convert_expr_to_tree (&block, clauses->async_expr);
2746 else
2747 t = build_int_cst (integer_type_node, -2);
2749 args->quick_push (t);
2750 args->quick_push (build_int_cst (integer_type_node, nparms));
2752 for (el = clauses->wait_list; el; el = el->next)
2753 args->quick_push (gfc_convert_expr_to_tree (&block, el->expr));
2755 stmt = build_call_expr_loc_vec (loc, stmt, args);
2756 gfc_add_expr_to_block (&block, stmt);
2758 vec_free (args);
2760 return gfc_finish_block (&block);
2763 static tree gfc_trans_omp_sections (gfc_code *, gfc_omp_clauses *);
2764 static tree gfc_trans_omp_workshare (gfc_code *, gfc_omp_clauses *);
2766 static tree
2767 gfc_trans_omp_atomic (gfc_code *code)
2769 gfc_code *atomic_code = code;
2770 gfc_se lse;
2771 gfc_se rse;
2772 gfc_se vse;
2773 gfc_expr *expr2, *e;
2774 gfc_symbol *var;
2775 stmtblock_t block;
2776 tree lhsaddr, type, rhs, x;
2777 enum tree_code op = ERROR_MARK;
2778 enum tree_code aop = OMP_ATOMIC;
2779 bool var_on_left = false;
2780 bool seq_cst = (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SEQ_CST) != 0;
2782 code = code->block->next;
2783 gcc_assert (code->op == EXEC_ASSIGN);
2784 var = code->expr1->symtree->n.sym;
2786 gfc_init_se (&lse, NULL);
2787 gfc_init_se (&rse, NULL);
2788 gfc_init_se (&vse, NULL);
2789 gfc_start_block (&block);
2791 expr2 = code->expr2;
2792 if (expr2->expr_type == EXPR_FUNCTION
2793 && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
2794 expr2 = expr2->value.function.actual->expr;
2796 switch (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
2798 case GFC_OMP_ATOMIC_READ:
2799 gfc_conv_expr (&vse, code->expr1);
2800 gfc_add_block_to_block (&block, &vse.pre);
2802 gfc_conv_expr (&lse, expr2);
2803 gfc_add_block_to_block (&block, &lse.pre);
2804 type = TREE_TYPE (lse.expr);
2805 lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
2807 x = build1 (OMP_ATOMIC_READ, type, lhsaddr);
2808 OMP_ATOMIC_SEQ_CST (x) = seq_cst;
2809 x = convert (TREE_TYPE (vse.expr), x);
2810 gfc_add_modify (&block, vse.expr, x);
2812 gfc_add_block_to_block (&block, &lse.pre);
2813 gfc_add_block_to_block (&block, &rse.pre);
2815 return gfc_finish_block (&block);
2816 case GFC_OMP_ATOMIC_CAPTURE:
2817 aop = OMP_ATOMIC_CAPTURE_NEW;
2818 if (expr2->expr_type == EXPR_VARIABLE)
2820 aop = OMP_ATOMIC_CAPTURE_OLD;
2821 gfc_conv_expr (&vse, code->expr1);
2822 gfc_add_block_to_block (&block, &vse.pre);
2824 gfc_conv_expr (&lse, expr2);
2825 gfc_add_block_to_block (&block, &lse.pre);
2826 gfc_init_se (&lse, NULL);
2827 code = code->next;
2828 var = code->expr1->symtree->n.sym;
2829 expr2 = code->expr2;
2830 if (expr2->expr_type == EXPR_FUNCTION
2831 && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
2832 expr2 = expr2->value.function.actual->expr;
2834 break;
2835 default:
2836 break;
2839 gfc_conv_expr (&lse, code->expr1);
2840 gfc_add_block_to_block (&block, &lse.pre);
2841 type = TREE_TYPE (lse.expr);
2842 lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
2844 if (((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
2845 == GFC_OMP_ATOMIC_WRITE)
2846 || (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SWAP))
2848 gfc_conv_expr (&rse, expr2);
2849 gfc_add_block_to_block (&block, &rse.pre);
2851 else if (expr2->expr_type == EXPR_OP)
2853 gfc_expr *e;
2854 switch (expr2->value.op.op)
2856 case INTRINSIC_PLUS:
2857 op = PLUS_EXPR;
2858 break;
2859 case INTRINSIC_TIMES:
2860 op = MULT_EXPR;
2861 break;
2862 case INTRINSIC_MINUS:
2863 op = MINUS_EXPR;
2864 break;
2865 case INTRINSIC_DIVIDE:
2866 if (expr2->ts.type == BT_INTEGER)
2867 op = TRUNC_DIV_EXPR;
2868 else
2869 op = RDIV_EXPR;
2870 break;
2871 case INTRINSIC_AND:
2872 op = TRUTH_ANDIF_EXPR;
2873 break;
2874 case INTRINSIC_OR:
2875 op = TRUTH_ORIF_EXPR;
2876 break;
2877 case INTRINSIC_EQV:
2878 op = EQ_EXPR;
2879 break;
2880 case INTRINSIC_NEQV:
2881 op = NE_EXPR;
2882 break;
2883 default:
2884 gcc_unreachable ();
2886 e = expr2->value.op.op1;
2887 if (e->expr_type == EXPR_FUNCTION
2888 && e->value.function.isym->id == GFC_ISYM_CONVERSION)
2889 e = e->value.function.actual->expr;
2890 if (e->expr_type == EXPR_VARIABLE
2891 && e->symtree != NULL
2892 && e->symtree->n.sym == var)
2894 expr2 = expr2->value.op.op2;
2895 var_on_left = true;
2897 else
2899 e = expr2->value.op.op2;
2900 if (e->expr_type == EXPR_FUNCTION
2901 && e->value.function.isym->id == GFC_ISYM_CONVERSION)
2902 e = e->value.function.actual->expr;
2903 gcc_assert (e->expr_type == EXPR_VARIABLE
2904 && e->symtree != NULL
2905 && e->symtree->n.sym == var);
2906 expr2 = expr2->value.op.op1;
2907 var_on_left = false;
2909 gfc_conv_expr (&rse, expr2);
2910 gfc_add_block_to_block (&block, &rse.pre);
2912 else
2914 gcc_assert (expr2->expr_type == EXPR_FUNCTION);
2915 switch (expr2->value.function.isym->id)
2917 case GFC_ISYM_MIN:
2918 op = MIN_EXPR;
2919 break;
2920 case GFC_ISYM_MAX:
2921 op = MAX_EXPR;
2922 break;
2923 case GFC_ISYM_IAND:
2924 op = BIT_AND_EXPR;
2925 break;
2926 case GFC_ISYM_IOR:
2927 op = BIT_IOR_EXPR;
2928 break;
2929 case GFC_ISYM_IEOR:
2930 op = BIT_XOR_EXPR;
2931 break;
2932 default:
2933 gcc_unreachable ();
2935 e = expr2->value.function.actual->expr;
2936 gcc_assert (e->expr_type == EXPR_VARIABLE
2937 && e->symtree != NULL
2938 && e->symtree->n.sym == var);
2940 gfc_conv_expr (&rse, expr2->value.function.actual->next->expr);
2941 gfc_add_block_to_block (&block, &rse.pre);
2942 if (expr2->value.function.actual->next->next != NULL)
2944 tree accum = gfc_create_var (TREE_TYPE (rse.expr), NULL);
2945 gfc_actual_arglist *arg;
2947 gfc_add_modify (&block, accum, rse.expr);
2948 for (arg = expr2->value.function.actual->next->next; arg;
2949 arg = arg->next)
2951 gfc_init_block (&rse.pre);
2952 gfc_conv_expr (&rse, arg->expr);
2953 gfc_add_block_to_block (&block, &rse.pre);
2954 x = fold_build2_loc (input_location, op, TREE_TYPE (accum),
2955 accum, rse.expr);
2956 gfc_add_modify (&block, accum, x);
2959 rse.expr = accum;
2962 expr2 = expr2->value.function.actual->next->expr;
2965 lhsaddr = save_expr (lhsaddr);
2966 if (TREE_CODE (lhsaddr) != SAVE_EXPR
2967 && (TREE_CODE (lhsaddr) != ADDR_EXPR
2968 || TREE_CODE (TREE_OPERAND (lhsaddr, 0)) != VAR_DECL))
2970 /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
2971 it even after unsharing function body. */
2972 tree var = create_tmp_var_raw (TREE_TYPE (lhsaddr));
2973 DECL_CONTEXT (var) = current_function_decl;
2974 lhsaddr = build4 (TARGET_EXPR, TREE_TYPE (lhsaddr), var, lhsaddr,
2975 NULL_TREE, NULL_TREE);
2978 rhs = gfc_evaluate_now (rse.expr, &block);
2980 if (((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
2981 == GFC_OMP_ATOMIC_WRITE)
2982 || (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SWAP))
2983 x = rhs;
2984 else
2986 x = convert (TREE_TYPE (rhs),
2987 build_fold_indirect_ref_loc (input_location, lhsaddr));
2988 if (var_on_left)
2989 x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), x, rhs);
2990 else
2991 x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), rhs, x);
2994 if (TREE_CODE (TREE_TYPE (rhs)) == COMPLEX_TYPE
2995 && TREE_CODE (type) != COMPLEX_TYPE)
2996 x = fold_build1_loc (input_location, REALPART_EXPR,
2997 TREE_TYPE (TREE_TYPE (rhs)), x);
2999 gfc_add_block_to_block (&block, &lse.pre);
3000 gfc_add_block_to_block (&block, &rse.pre);
3002 if (aop == OMP_ATOMIC)
3004 x = build2_v (OMP_ATOMIC, lhsaddr, convert (type, x));
3005 OMP_ATOMIC_SEQ_CST (x) = seq_cst;
3006 gfc_add_expr_to_block (&block, x);
3008 else
3010 if (aop == OMP_ATOMIC_CAPTURE_NEW)
3012 code = code->next;
3013 expr2 = code->expr2;
3014 if (expr2->expr_type == EXPR_FUNCTION
3015 && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
3016 expr2 = expr2->value.function.actual->expr;
3018 gcc_assert (expr2->expr_type == EXPR_VARIABLE);
3019 gfc_conv_expr (&vse, code->expr1);
3020 gfc_add_block_to_block (&block, &vse.pre);
3022 gfc_init_se (&lse, NULL);
3023 gfc_conv_expr (&lse, expr2);
3024 gfc_add_block_to_block (&block, &lse.pre);
3026 x = build2 (aop, type, lhsaddr, convert (type, x));
3027 OMP_ATOMIC_SEQ_CST (x) = seq_cst;
3028 x = convert (TREE_TYPE (vse.expr), x);
3029 gfc_add_modify (&block, vse.expr, x);
3032 return gfc_finish_block (&block);
3035 static tree
3036 gfc_trans_omp_barrier (void)
3038 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
3039 return build_call_expr_loc (input_location, decl, 0);
3042 static tree
3043 gfc_trans_omp_cancel (gfc_code *code)
3045 int mask = 0;
3046 tree ifc = boolean_true_node;
3047 stmtblock_t block;
3048 switch (code->ext.omp_clauses->cancel)
3050 case OMP_CANCEL_PARALLEL: mask = 1; break;
3051 case OMP_CANCEL_DO: mask = 2; break;
3052 case OMP_CANCEL_SECTIONS: mask = 4; break;
3053 case OMP_CANCEL_TASKGROUP: mask = 8; break;
3054 default: gcc_unreachable ();
3056 gfc_start_block (&block);
3057 if (code->ext.omp_clauses->if_expr)
3059 gfc_se se;
3060 tree if_var;
3062 gfc_init_se (&se, NULL);
3063 gfc_conv_expr (&se, code->ext.omp_clauses->if_expr);
3064 gfc_add_block_to_block (&block, &se.pre);
3065 if_var = gfc_evaluate_now (se.expr, &block);
3066 gfc_add_block_to_block (&block, &se.post);
3067 tree type = TREE_TYPE (if_var);
3068 ifc = fold_build2_loc (input_location, NE_EXPR,
3069 boolean_type_node, if_var,
3070 build_zero_cst (type));
3072 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
3073 tree c_bool_type = TREE_TYPE (TREE_TYPE (decl));
3074 ifc = fold_convert (c_bool_type, ifc);
3075 gfc_add_expr_to_block (&block,
3076 build_call_expr_loc (input_location, decl, 2,
3077 build_int_cst (integer_type_node,
3078 mask), ifc));
3079 return gfc_finish_block (&block);
3082 static tree
3083 gfc_trans_omp_cancellation_point (gfc_code *code)
3085 int mask = 0;
3086 switch (code->ext.omp_clauses->cancel)
3088 case OMP_CANCEL_PARALLEL: mask = 1; break;
3089 case OMP_CANCEL_DO: mask = 2; break;
3090 case OMP_CANCEL_SECTIONS: mask = 4; break;
3091 case OMP_CANCEL_TASKGROUP: mask = 8; break;
3092 default: gcc_unreachable ();
3094 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCELLATION_POINT);
3095 return build_call_expr_loc (input_location, decl, 1,
3096 build_int_cst (integer_type_node, mask));
3099 static tree
3100 gfc_trans_omp_critical (gfc_code *code)
3102 tree name = NULL_TREE, stmt;
3103 if (code->ext.omp_name != NULL)
3104 name = get_identifier (code->ext.omp_name);
3105 stmt = gfc_trans_code (code->block->next);
3106 return build2_loc (input_location, OMP_CRITICAL, void_type_node, stmt, name);
3109 typedef struct dovar_init_d {
3110 tree var;
3111 tree init;
3112 } dovar_init;
3115 static tree
3116 gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
3117 gfc_omp_clauses *do_clauses, tree par_clauses)
3119 gfc_se se;
3120 tree dovar, stmt, from, to, step, type, init, cond, incr;
3121 tree count = NULL_TREE, cycle_label, tmp, omp_clauses;
3122 stmtblock_t block;
3123 stmtblock_t body;
3124 gfc_omp_clauses *clauses = code->ext.omp_clauses;
3125 int i, collapse = clauses->collapse;
3126 vec<dovar_init> inits = vNULL;
3127 dovar_init *di;
3128 unsigned ix;
3130 if (collapse <= 0)
3131 collapse = 1;
3133 code = code->block->next;
3134 gcc_assert (code->op == EXEC_DO);
3136 init = make_tree_vec (collapse);
3137 cond = make_tree_vec (collapse);
3138 incr = make_tree_vec (collapse);
3140 if (pblock == NULL)
3142 gfc_start_block (&block);
3143 pblock = &block;
3146 omp_clauses = gfc_trans_omp_clauses (pblock, do_clauses, code->loc);
3148 for (i = 0; i < collapse; i++)
3150 int simple = 0;
3151 int dovar_found = 0;
3152 tree dovar_decl;
3154 if (clauses)
3156 gfc_omp_namelist *n = NULL;
3157 if (op != EXEC_OMP_DISTRIBUTE)
3158 for (n = clauses->lists[(op == EXEC_OMP_SIMD && collapse == 1)
3159 ? OMP_LIST_LINEAR : OMP_LIST_LASTPRIVATE];
3160 n != NULL; n = n->next)
3161 if (code->ext.iterator->var->symtree->n.sym == n->sym)
3162 break;
3163 if (n != NULL)
3164 dovar_found = 1;
3165 else if (n == NULL && op != EXEC_OMP_SIMD)
3166 for (n = clauses->lists[OMP_LIST_PRIVATE]; n != NULL; n = n->next)
3167 if (code->ext.iterator->var->symtree->n.sym == n->sym)
3168 break;
3169 if (n != NULL)
3170 dovar_found++;
3173 /* Evaluate all the expressions in the iterator. */
3174 gfc_init_se (&se, NULL);
3175 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
3176 gfc_add_block_to_block (pblock, &se.pre);
3177 dovar = se.expr;
3178 type = TREE_TYPE (dovar);
3179 gcc_assert (TREE_CODE (type) == INTEGER_TYPE);
3181 gfc_init_se (&se, NULL);
3182 gfc_conv_expr_val (&se, code->ext.iterator->start);
3183 gfc_add_block_to_block (pblock, &se.pre);
3184 from = gfc_evaluate_now (se.expr, pblock);
3186 gfc_init_se (&se, NULL);
3187 gfc_conv_expr_val (&se, code->ext.iterator->end);
3188 gfc_add_block_to_block (pblock, &se.pre);
3189 to = gfc_evaluate_now (se.expr, pblock);
3191 gfc_init_se (&se, NULL);
3192 gfc_conv_expr_val (&se, code->ext.iterator->step);
3193 gfc_add_block_to_block (pblock, &se.pre);
3194 step = gfc_evaluate_now (se.expr, pblock);
3195 dovar_decl = dovar;
3197 /* Special case simple loops. */
3198 if (TREE_CODE (dovar) == VAR_DECL)
3200 if (integer_onep (step))
3201 simple = 1;
3202 else if (tree_int_cst_equal (step, integer_minus_one_node))
3203 simple = -1;
3205 else
3206 dovar_decl
3207 = gfc_trans_omp_variable (code->ext.iterator->var->symtree->n.sym,
3208 false);
3210 /* Loop body. */
3211 if (simple)
3213 TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, dovar, from);
3214 /* The condition should not be folded. */
3215 TREE_VEC_ELT (cond, i) = build2_loc (input_location, simple > 0
3216 ? LE_EXPR : GE_EXPR,
3217 boolean_type_node, dovar, to);
3218 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR,
3219 type, dovar, step);
3220 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location,
3221 MODIFY_EXPR,
3222 type, dovar,
3223 TREE_VEC_ELT (incr, i));
3225 else
3227 /* STEP is not 1 or -1. Use:
3228 for (count = 0; count < (to + step - from) / step; count++)
3230 dovar = from + count * step;
3231 body;
3232 cycle_label:;
3233 } */
3234 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, step, from);
3235 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, to, tmp);
3236 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, type, tmp,
3237 step);
3238 tmp = gfc_evaluate_now (tmp, pblock);
3239 count = gfc_create_var (type, "count");
3240 TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, count,
3241 build_int_cst (type, 0));
3242 /* The condition should not be folded. */
3243 TREE_VEC_ELT (cond, i) = build2_loc (input_location, LT_EXPR,
3244 boolean_type_node,
3245 count, tmp);
3246 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR,
3247 type, count,
3248 build_int_cst (type, 1));
3249 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location,
3250 MODIFY_EXPR, type, count,
3251 TREE_VEC_ELT (incr, i));
3253 /* Initialize DOVAR. */
3254 tmp = fold_build2_loc (input_location, MULT_EXPR, type, count, step);
3255 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, from, tmp);
3256 dovar_init e = {dovar, tmp};
3257 inits.safe_push (e);
3260 if (dovar_found == 2
3261 && op == EXEC_OMP_SIMD
3262 && collapse == 1
3263 && !simple)
3265 for (tmp = omp_clauses; tmp; tmp = OMP_CLAUSE_CHAIN (tmp))
3266 if (OMP_CLAUSE_CODE (tmp) == OMP_CLAUSE_LINEAR
3267 && OMP_CLAUSE_DECL (tmp) == dovar)
3269 OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
3270 break;
3273 if (!dovar_found)
3275 if (op == EXEC_OMP_SIMD)
3277 if (collapse == 1)
3279 tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
3280 OMP_CLAUSE_LINEAR_STEP (tmp) = step;
3281 OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
3283 else
3284 tmp = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
3285 if (!simple)
3286 dovar_found = 2;
3288 else
3289 tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
3290 OMP_CLAUSE_DECL (tmp) = dovar_decl;
3291 omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
3293 if (dovar_found == 2)
3295 tree c = NULL;
3297 tmp = NULL;
3298 if (!simple)
3300 /* If dovar is lastprivate, but different counter is used,
3301 dovar += step needs to be added to
3302 OMP_CLAUSE_LASTPRIVATE_STMT, otherwise the copied dovar
3303 will have the value on entry of the last loop, rather
3304 than value after iterator increment. */
3305 tmp = gfc_evaluate_now (step, pblock);
3306 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, dovar,
3307 tmp);
3308 tmp = fold_build2_loc (input_location, MODIFY_EXPR, type,
3309 dovar, tmp);
3310 for (c = omp_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3311 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3312 && OMP_CLAUSE_DECL (c) == dovar_decl)
3314 OMP_CLAUSE_LASTPRIVATE_STMT (c) = tmp;
3315 break;
3317 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3318 && OMP_CLAUSE_DECL (c) == dovar_decl)
3320 OMP_CLAUSE_LINEAR_STMT (c) = tmp;
3321 break;
3324 if (c == NULL && op == EXEC_OMP_DO && par_clauses != NULL)
3326 for (c = par_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3327 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3328 && OMP_CLAUSE_DECL (c) == dovar_decl)
3330 tree l = build_omp_clause (input_location,
3331 OMP_CLAUSE_LASTPRIVATE);
3332 OMP_CLAUSE_DECL (l) = dovar_decl;
3333 OMP_CLAUSE_CHAIN (l) = omp_clauses;
3334 OMP_CLAUSE_LASTPRIVATE_STMT (l) = tmp;
3335 omp_clauses = l;
3336 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_SHARED);
3337 break;
3340 gcc_assert (simple || c != NULL);
3342 if (!simple)
3344 if (op != EXEC_OMP_SIMD)
3345 tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
3346 else if (collapse == 1)
3348 tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
3349 OMP_CLAUSE_LINEAR_STEP (tmp) = build_int_cst (type, 1);
3350 OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
3351 OMP_CLAUSE_LINEAR_NO_COPYOUT (tmp) = 1;
3353 else
3354 tmp = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
3355 OMP_CLAUSE_DECL (tmp) = count;
3356 omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
3359 if (i + 1 < collapse)
3360 code = code->block->next;
3363 if (pblock != &block)
3365 pushlevel ();
3366 gfc_start_block (&block);
3369 gfc_start_block (&body);
3371 FOR_EACH_VEC_ELT (inits, ix, di)
3372 gfc_add_modify (&body, di->var, di->init);
3373 inits.release ();
3375 /* Cycle statement is implemented with a goto. Exit statement must not be
3376 present for this loop. */
3377 cycle_label = gfc_build_label_decl (NULL_TREE);
3379 /* Put these labels where they can be found later. */
3381 code->cycle_label = cycle_label;
3382 code->exit_label = NULL_TREE;
3384 /* Main loop body. */
3385 tmp = gfc_trans_omp_code (code->block->next, true);
3386 gfc_add_expr_to_block (&body, tmp);
3388 /* Label for cycle statements (if needed). */
3389 if (TREE_USED (cycle_label))
3391 tmp = build1_v (LABEL_EXPR, cycle_label);
3392 gfc_add_expr_to_block (&body, tmp);
3395 /* End of loop body. */
3396 switch (op)
3398 case EXEC_OMP_SIMD: stmt = make_node (OMP_SIMD); break;
3399 case EXEC_OMP_DO: stmt = make_node (OMP_FOR); break;
3400 case EXEC_OMP_DISTRIBUTE: stmt = make_node (OMP_DISTRIBUTE); break;
3401 case EXEC_OACC_LOOP: stmt = make_node (OACC_LOOP); break;
3402 default: gcc_unreachable ();
3405 TREE_TYPE (stmt) = void_type_node;
3406 OMP_FOR_BODY (stmt) = gfc_finish_block (&body);
3407 OMP_FOR_CLAUSES (stmt) = omp_clauses;
3408 OMP_FOR_INIT (stmt) = init;
3409 OMP_FOR_COND (stmt) = cond;
3410 OMP_FOR_INCR (stmt) = incr;
3411 gfc_add_expr_to_block (&block, stmt);
3413 return gfc_finish_block (&block);
3416 /* parallel loop and kernels loop. */
3417 static tree
3418 gfc_trans_oacc_combined_directive (gfc_code *code)
3420 stmtblock_t block, *pblock = NULL;
3421 gfc_omp_clauses construct_clauses, loop_clauses;
3422 tree stmt, oacc_clauses = NULL_TREE;
3423 enum tree_code construct_code;
3425 switch (code->op)
3427 case EXEC_OACC_PARALLEL_LOOP:
3428 construct_code = OACC_PARALLEL;
3429 break;
3430 case EXEC_OACC_KERNELS_LOOP:
3431 construct_code = OACC_KERNELS;
3432 break;
3433 default:
3434 gcc_unreachable ();
3437 gfc_start_block (&block);
3439 memset (&loop_clauses, 0, sizeof (loop_clauses));
3440 if (code->ext.omp_clauses != NULL)
3442 memcpy (&construct_clauses, code->ext.omp_clauses,
3443 sizeof (construct_clauses));
3444 loop_clauses.collapse = construct_clauses.collapse;
3445 loop_clauses.gang = construct_clauses.gang;
3446 loop_clauses.vector = construct_clauses.vector;
3447 loop_clauses.worker = construct_clauses.worker;
3448 loop_clauses.seq = construct_clauses.seq;
3449 loop_clauses.independent = construct_clauses.independent;
3450 construct_clauses.collapse = 0;
3451 construct_clauses.gang = false;
3452 construct_clauses.vector = false;
3453 construct_clauses.worker = false;
3454 construct_clauses.seq = false;
3455 construct_clauses.independent = false;
3456 oacc_clauses = gfc_trans_omp_clauses (&block, &construct_clauses,
3457 code->loc);
3459 if (!loop_clauses.seq)
3460 pblock = &block;
3461 else
3462 pushlevel ();
3463 stmt = gfc_trans_omp_do (code, EXEC_OACC_LOOP, pblock, &loop_clauses, NULL);
3464 if (TREE_CODE (stmt) != BIND_EXPR)
3465 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
3466 else
3467 poplevel (0, 0);
3468 stmt = build2_loc (input_location, construct_code, void_type_node, stmt,
3469 oacc_clauses);
3470 if (code->op == EXEC_OACC_KERNELS_LOOP)
3471 OACC_KERNELS_COMBINED (stmt) = 1;
3472 else
3473 OACC_PARALLEL_COMBINED (stmt) = 1;
3474 gfc_add_expr_to_block (&block, stmt);
3475 return gfc_finish_block (&block);
3478 static tree
3479 gfc_trans_omp_flush (void)
3481 tree decl = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
3482 return build_call_expr_loc (input_location, decl, 0);
3485 static tree
3486 gfc_trans_omp_master (gfc_code *code)
3488 tree stmt = gfc_trans_code (code->block->next);
3489 if (IS_EMPTY_STMT (stmt))
3490 return stmt;
3491 return build1_v (OMP_MASTER, stmt);
3494 static tree
3495 gfc_trans_omp_ordered (gfc_code *code)
3497 return build1_v (OMP_ORDERED, gfc_trans_code (code->block->next));
3500 static tree
3501 gfc_trans_omp_parallel (gfc_code *code)
3503 stmtblock_t block;
3504 tree stmt, omp_clauses;
3506 gfc_start_block (&block);
3507 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
3508 code->loc);
3509 stmt = gfc_trans_omp_code (code->block->next, true);
3510 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
3511 omp_clauses);
3512 gfc_add_expr_to_block (&block, stmt);
3513 return gfc_finish_block (&block);
3516 enum
3518 GFC_OMP_SPLIT_SIMD,
3519 GFC_OMP_SPLIT_DO,
3520 GFC_OMP_SPLIT_PARALLEL,
3521 GFC_OMP_SPLIT_DISTRIBUTE,
3522 GFC_OMP_SPLIT_TEAMS,
3523 GFC_OMP_SPLIT_TARGET,
3524 GFC_OMP_SPLIT_NUM
3527 enum
3529 GFC_OMP_MASK_SIMD = (1 << GFC_OMP_SPLIT_SIMD),
3530 GFC_OMP_MASK_DO = (1 << GFC_OMP_SPLIT_DO),
3531 GFC_OMP_MASK_PARALLEL = (1 << GFC_OMP_SPLIT_PARALLEL),
3532 GFC_OMP_MASK_DISTRIBUTE = (1 << GFC_OMP_SPLIT_DISTRIBUTE),
3533 GFC_OMP_MASK_TEAMS = (1 << GFC_OMP_SPLIT_TEAMS),
3534 GFC_OMP_MASK_TARGET = (1 << GFC_OMP_SPLIT_TARGET)
3537 static void
3538 gfc_split_omp_clauses (gfc_code *code,
3539 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM])
3541 int mask = 0, innermost = 0;
3542 memset (clausesa, 0, GFC_OMP_SPLIT_NUM * sizeof (gfc_omp_clauses));
3543 switch (code->op)
3545 case EXEC_OMP_DISTRIBUTE:
3546 innermost = GFC_OMP_SPLIT_DISTRIBUTE;
3547 break;
3548 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
3549 mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
3550 innermost = GFC_OMP_SPLIT_DO;
3551 break;
3552 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
3553 mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL
3554 | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
3555 innermost = GFC_OMP_SPLIT_SIMD;
3556 break;
3557 case EXEC_OMP_DISTRIBUTE_SIMD:
3558 mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
3559 innermost = GFC_OMP_SPLIT_SIMD;
3560 break;
3561 case EXEC_OMP_DO:
3562 innermost = GFC_OMP_SPLIT_DO;
3563 break;
3564 case EXEC_OMP_DO_SIMD:
3565 mask = GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
3566 innermost = GFC_OMP_SPLIT_SIMD;
3567 break;
3568 case EXEC_OMP_PARALLEL:
3569 innermost = GFC_OMP_SPLIT_PARALLEL;
3570 break;
3571 case EXEC_OMP_PARALLEL_DO:
3572 mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
3573 innermost = GFC_OMP_SPLIT_DO;
3574 break;
3575 case EXEC_OMP_PARALLEL_DO_SIMD:
3576 mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
3577 innermost = GFC_OMP_SPLIT_SIMD;
3578 break;
3579 case EXEC_OMP_SIMD:
3580 innermost = GFC_OMP_SPLIT_SIMD;
3581 break;
3582 case EXEC_OMP_TARGET:
3583 innermost = GFC_OMP_SPLIT_TARGET;
3584 break;
3585 case EXEC_OMP_TARGET_TEAMS:
3586 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS;
3587 innermost = GFC_OMP_SPLIT_TEAMS;
3588 break;
3589 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
3590 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS
3591 | GFC_OMP_MASK_DISTRIBUTE;
3592 innermost = GFC_OMP_SPLIT_DISTRIBUTE;
3593 break;
3594 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
3595 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
3596 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
3597 innermost = GFC_OMP_SPLIT_DO;
3598 break;
3599 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
3600 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
3601 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
3602 innermost = GFC_OMP_SPLIT_SIMD;
3603 break;
3604 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
3605 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS
3606 | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
3607 innermost = GFC_OMP_SPLIT_SIMD;
3608 break;
3609 case EXEC_OMP_TEAMS:
3610 innermost = GFC_OMP_SPLIT_TEAMS;
3611 break;
3612 case EXEC_OMP_TEAMS_DISTRIBUTE:
3613 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE;
3614 innermost = GFC_OMP_SPLIT_DISTRIBUTE;
3615 break;
3616 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
3617 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
3618 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
3619 innermost = GFC_OMP_SPLIT_DO;
3620 break;
3621 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
3622 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
3623 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
3624 innermost = GFC_OMP_SPLIT_SIMD;
3625 break;
3626 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
3627 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
3628 innermost = GFC_OMP_SPLIT_SIMD;
3629 break;
3630 default:
3631 gcc_unreachable ();
3633 if (mask == 0)
3635 clausesa[innermost] = *code->ext.omp_clauses;
3636 return;
3638 if (code->ext.omp_clauses != NULL)
3640 if (mask & GFC_OMP_MASK_TARGET)
3642 /* First the clauses that are unique to some constructs. */
3643 clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_MAP]
3644 = code->ext.omp_clauses->lists[OMP_LIST_MAP];
3645 clausesa[GFC_OMP_SPLIT_TARGET].device
3646 = code->ext.omp_clauses->device;
3648 if (mask & GFC_OMP_MASK_TEAMS)
3650 /* First the clauses that are unique to some constructs. */
3651 clausesa[GFC_OMP_SPLIT_TEAMS].num_teams
3652 = code->ext.omp_clauses->num_teams;
3653 clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit
3654 = code->ext.omp_clauses->thread_limit;
3655 /* Shared and default clauses are allowed on parallel and teams. */
3656 clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_SHARED]
3657 = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
3658 clausesa[GFC_OMP_SPLIT_TEAMS].default_sharing
3659 = code->ext.omp_clauses->default_sharing;
3661 if (mask & GFC_OMP_MASK_DISTRIBUTE)
3663 /* First the clauses that are unique to some constructs. */
3664 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_sched_kind
3665 = code->ext.omp_clauses->dist_sched_kind;
3666 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_chunk_size
3667 = code->ext.omp_clauses->dist_chunk_size;
3668 /* Duplicate collapse. */
3669 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].collapse
3670 = code->ext.omp_clauses->collapse;
3672 if (mask & GFC_OMP_MASK_PARALLEL)
3674 /* First the clauses that are unique to some constructs. */
3675 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_COPYIN]
3676 = code->ext.omp_clauses->lists[OMP_LIST_COPYIN];
3677 clausesa[GFC_OMP_SPLIT_PARALLEL].num_threads
3678 = code->ext.omp_clauses->num_threads;
3679 clausesa[GFC_OMP_SPLIT_PARALLEL].proc_bind
3680 = code->ext.omp_clauses->proc_bind;
3681 /* Shared and default clauses are allowed on parallel and teams. */
3682 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_SHARED]
3683 = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
3684 clausesa[GFC_OMP_SPLIT_PARALLEL].default_sharing
3685 = code->ext.omp_clauses->default_sharing;
3687 if (mask & GFC_OMP_MASK_DO)
3689 /* First the clauses that are unique to some constructs. */
3690 clausesa[GFC_OMP_SPLIT_DO].ordered
3691 = code->ext.omp_clauses->ordered;
3692 clausesa[GFC_OMP_SPLIT_DO].sched_kind
3693 = code->ext.omp_clauses->sched_kind;
3694 clausesa[GFC_OMP_SPLIT_DO].chunk_size
3695 = code->ext.omp_clauses->chunk_size;
3696 clausesa[GFC_OMP_SPLIT_DO].nowait
3697 = code->ext.omp_clauses->nowait;
3698 /* Duplicate collapse. */
3699 clausesa[GFC_OMP_SPLIT_DO].collapse
3700 = code->ext.omp_clauses->collapse;
3702 if (mask & GFC_OMP_MASK_SIMD)
3704 clausesa[GFC_OMP_SPLIT_SIMD].safelen_expr
3705 = code->ext.omp_clauses->safelen_expr;
3706 clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_LINEAR]
3707 = code->ext.omp_clauses->lists[OMP_LIST_LINEAR];
3708 clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_ALIGNED]
3709 = code->ext.omp_clauses->lists[OMP_LIST_ALIGNED];
3710 /* Duplicate collapse. */
3711 clausesa[GFC_OMP_SPLIT_SIMD].collapse
3712 = code->ext.omp_clauses->collapse;
3714 /* Private clause is supported on all constructs but target,
3715 it is enough to put it on the innermost one. For
3716 !$ omp do put it on parallel though,
3717 as that's what we did for OpenMP 3.1. */
3718 clausesa[innermost == GFC_OMP_SPLIT_DO
3719 ? (int) GFC_OMP_SPLIT_PARALLEL
3720 : innermost].lists[OMP_LIST_PRIVATE]
3721 = code->ext.omp_clauses->lists[OMP_LIST_PRIVATE];
3722 /* Firstprivate clause is supported on all constructs but
3723 target and simd. Put it on the outermost of those and
3724 duplicate on parallel. */
3725 if (mask & GFC_OMP_MASK_TEAMS)
3726 clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_FIRSTPRIVATE]
3727 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
3728 else if (mask & GFC_OMP_MASK_DISTRIBUTE)
3729 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_FIRSTPRIVATE]
3730 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
3731 if (mask & GFC_OMP_MASK_PARALLEL)
3732 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_FIRSTPRIVATE]
3733 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
3734 else if (mask & GFC_OMP_MASK_DO)
3735 clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_FIRSTPRIVATE]
3736 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
3737 /* Lastprivate is allowed on do and simd. In
3738 parallel do{, simd} we actually want to put it on
3739 parallel rather than do. */
3740 if (mask & GFC_OMP_MASK_PARALLEL)
3741 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_LASTPRIVATE]
3742 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
3743 else if (mask & GFC_OMP_MASK_DO)
3744 clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_LASTPRIVATE]
3745 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
3746 if (mask & GFC_OMP_MASK_SIMD)
3747 clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_LASTPRIVATE]
3748 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
3749 /* Reduction is allowed on simd, do, parallel and teams.
3750 Duplicate it on all of them, but omit on do if
3751 parallel is present. */
3752 if (mask & GFC_OMP_MASK_TEAMS)
3753 clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_REDUCTION]
3754 = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
3755 if (mask & GFC_OMP_MASK_PARALLEL)
3756 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_REDUCTION]
3757 = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
3758 else if (mask & GFC_OMP_MASK_DO)
3759 clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_REDUCTION]
3760 = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
3761 if (mask & GFC_OMP_MASK_SIMD)
3762 clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_REDUCTION]
3763 = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
3764 /* FIXME: This is currently being discussed. */
3765 if (mask & GFC_OMP_MASK_PARALLEL)
3766 clausesa[GFC_OMP_SPLIT_PARALLEL].if_expr
3767 = code->ext.omp_clauses->if_expr;
3768 else
3769 clausesa[GFC_OMP_SPLIT_TARGET].if_expr
3770 = code->ext.omp_clauses->if_expr;
3772 if ((mask & (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
3773 == (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
3774 clausesa[GFC_OMP_SPLIT_DO].nowait = true;
3777 static tree
3778 gfc_trans_omp_do_simd (gfc_code *code, stmtblock_t *pblock,
3779 gfc_omp_clauses *clausesa, tree omp_clauses)
3781 stmtblock_t block;
3782 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
3783 tree stmt, body, omp_do_clauses = NULL_TREE;
3785 if (pblock == NULL)
3786 gfc_start_block (&block);
3787 else
3788 gfc_init_block (&block);
3790 if (clausesa == NULL)
3792 clausesa = clausesa_buf;
3793 gfc_split_omp_clauses (code, clausesa);
3795 if (flag_openmp)
3796 omp_do_clauses
3797 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DO], code->loc);
3798 body = gfc_trans_omp_do (code, EXEC_OMP_SIMD, pblock ? pblock : &block,
3799 &clausesa[GFC_OMP_SPLIT_SIMD], omp_clauses);
3800 if (pblock == NULL)
3802 if (TREE_CODE (body) != BIND_EXPR)
3803 body = build3_v (BIND_EXPR, NULL, body, poplevel (1, 0));
3804 else
3805 poplevel (0, 0);
3807 else if (TREE_CODE (body) != BIND_EXPR)
3808 body = build3_v (BIND_EXPR, NULL, body, NULL_TREE);
3809 if (flag_openmp)
3811 stmt = make_node (OMP_FOR);
3812 TREE_TYPE (stmt) = void_type_node;
3813 OMP_FOR_BODY (stmt) = body;
3814 OMP_FOR_CLAUSES (stmt) = omp_do_clauses;
3816 else
3817 stmt = body;
3818 gfc_add_expr_to_block (&block, stmt);
3819 return gfc_finish_block (&block);
3822 static tree
3823 gfc_trans_omp_parallel_do (gfc_code *code, stmtblock_t *pblock,
3824 gfc_omp_clauses *clausesa)
3826 stmtblock_t block, *new_pblock = pblock;
3827 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
3828 tree stmt, omp_clauses = NULL_TREE;
3830 if (pblock == NULL)
3831 gfc_start_block (&block);
3832 else
3833 gfc_init_block (&block);
3835 if (clausesa == NULL)
3837 clausesa = clausesa_buf;
3838 gfc_split_omp_clauses (code, clausesa);
3840 omp_clauses
3841 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
3842 code->loc);
3843 if (pblock == NULL)
3845 if (!clausesa[GFC_OMP_SPLIT_DO].ordered
3846 && clausesa[GFC_OMP_SPLIT_DO].sched_kind != OMP_SCHED_STATIC)
3847 new_pblock = &block;
3848 else
3849 pushlevel ();
3851 stmt = gfc_trans_omp_do (code, EXEC_OMP_DO, new_pblock,
3852 &clausesa[GFC_OMP_SPLIT_DO], omp_clauses);
3853 if (pblock == NULL)
3855 if (TREE_CODE (stmt) != BIND_EXPR)
3856 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
3857 else
3858 poplevel (0, 0);
3860 else if (TREE_CODE (stmt) != BIND_EXPR)
3861 stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
3862 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
3863 omp_clauses);
3864 OMP_PARALLEL_COMBINED (stmt) = 1;
3865 gfc_add_expr_to_block (&block, stmt);
3866 return gfc_finish_block (&block);
3869 static tree
3870 gfc_trans_omp_parallel_do_simd (gfc_code *code, stmtblock_t *pblock,
3871 gfc_omp_clauses *clausesa)
3873 stmtblock_t block;
3874 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
3875 tree stmt, omp_clauses = NULL_TREE;
3877 if (pblock == NULL)
3878 gfc_start_block (&block);
3879 else
3880 gfc_init_block (&block);
3882 if (clausesa == NULL)
3884 clausesa = clausesa_buf;
3885 gfc_split_omp_clauses (code, clausesa);
3887 if (flag_openmp)
3888 omp_clauses
3889 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
3890 code->loc);
3891 if (pblock == NULL)
3892 pushlevel ();
3893 stmt = gfc_trans_omp_do_simd (code, pblock, clausesa, omp_clauses);
3894 if (pblock == NULL)
3896 if (TREE_CODE (stmt) != BIND_EXPR)
3897 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
3898 else
3899 poplevel (0, 0);
3901 else if (TREE_CODE (stmt) != BIND_EXPR)
3902 stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
3903 if (flag_openmp)
3905 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
3906 omp_clauses);
3907 OMP_PARALLEL_COMBINED (stmt) = 1;
3909 gfc_add_expr_to_block (&block, stmt);
3910 return gfc_finish_block (&block);
3913 static tree
3914 gfc_trans_omp_parallel_sections (gfc_code *code)
3916 stmtblock_t block;
3917 gfc_omp_clauses section_clauses;
3918 tree stmt, omp_clauses;
3920 memset (&section_clauses, 0, sizeof (section_clauses));
3921 section_clauses.nowait = true;
3923 gfc_start_block (&block);
3924 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
3925 code->loc);
3926 pushlevel ();
3927 stmt = gfc_trans_omp_sections (code, &section_clauses);
3928 if (TREE_CODE (stmt) != BIND_EXPR)
3929 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
3930 else
3931 poplevel (0, 0);
3932 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
3933 omp_clauses);
3934 OMP_PARALLEL_COMBINED (stmt) = 1;
3935 gfc_add_expr_to_block (&block, stmt);
3936 return gfc_finish_block (&block);
3939 static tree
3940 gfc_trans_omp_parallel_workshare (gfc_code *code)
3942 stmtblock_t block;
3943 gfc_omp_clauses workshare_clauses;
3944 tree stmt, omp_clauses;
3946 memset (&workshare_clauses, 0, sizeof (workshare_clauses));
3947 workshare_clauses.nowait = true;
3949 gfc_start_block (&block);
3950 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
3951 code->loc);
3952 pushlevel ();
3953 stmt = gfc_trans_omp_workshare (code, &workshare_clauses);
3954 if (TREE_CODE (stmt) != BIND_EXPR)
3955 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
3956 else
3957 poplevel (0, 0);
3958 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
3959 omp_clauses);
3960 OMP_PARALLEL_COMBINED (stmt) = 1;
3961 gfc_add_expr_to_block (&block, stmt);
3962 return gfc_finish_block (&block);
3965 static tree
3966 gfc_trans_omp_sections (gfc_code *code, gfc_omp_clauses *clauses)
3968 stmtblock_t block, body;
3969 tree omp_clauses, stmt;
3970 bool has_lastprivate = clauses->lists[OMP_LIST_LASTPRIVATE] != NULL;
3972 gfc_start_block (&block);
3974 omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
3976 gfc_init_block (&body);
3977 for (code = code->block; code; code = code->block)
3979 /* Last section is special because of lastprivate, so even if it
3980 is empty, chain it in. */
3981 stmt = gfc_trans_omp_code (code->next,
3982 has_lastprivate && code->block == NULL);
3983 if (! IS_EMPTY_STMT (stmt))
3985 stmt = build1_v (OMP_SECTION, stmt);
3986 gfc_add_expr_to_block (&body, stmt);
3989 stmt = gfc_finish_block (&body);
3991 stmt = build2_loc (input_location, OMP_SECTIONS, void_type_node, stmt,
3992 omp_clauses);
3993 gfc_add_expr_to_block (&block, stmt);
3995 return gfc_finish_block (&block);
3998 static tree
3999 gfc_trans_omp_single (gfc_code *code, gfc_omp_clauses *clauses)
4001 tree omp_clauses = gfc_trans_omp_clauses (NULL, clauses, code->loc);
4002 tree stmt = gfc_trans_omp_code (code->block->next, true);
4003 stmt = build2_loc (input_location, OMP_SINGLE, void_type_node, stmt,
4004 omp_clauses);
4005 return stmt;
4008 static tree
4009 gfc_trans_omp_task (gfc_code *code)
4011 stmtblock_t block;
4012 tree stmt, omp_clauses;
4014 gfc_start_block (&block);
4015 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
4016 code->loc);
4017 stmt = gfc_trans_omp_code (code->block->next, true);
4018 stmt = build2_loc (input_location, OMP_TASK, void_type_node, stmt,
4019 omp_clauses);
4020 gfc_add_expr_to_block (&block, stmt);
4021 return gfc_finish_block (&block);
4024 static tree
4025 gfc_trans_omp_taskgroup (gfc_code *code)
4027 tree stmt = gfc_trans_code (code->block->next);
4028 return build1_loc (input_location, OMP_TASKGROUP, void_type_node, stmt);
4031 static tree
4032 gfc_trans_omp_taskwait (void)
4034 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
4035 return build_call_expr_loc (input_location, decl, 0);
4038 static tree
4039 gfc_trans_omp_taskyield (void)
4041 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
4042 return build_call_expr_loc (input_location, decl, 0);
4045 static tree
4046 gfc_trans_omp_distribute (gfc_code *code, gfc_omp_clauses *clausesa)
4048 stmtblock_t block;
4049 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
4050 tree stmt, omp_clauses = NULL_TREE;
4052 gfc_start_block (&block);
4053 if (clausesa == NULL)
4055 clausesa = clausesa_buf;
4056 gfc_split_omp_clauses (code, clausesa);
4058 if (flag_openmp)
4059 omp_clauses
4060 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
4061 code->loc);
4062 switch (code->op)
4064 case EXEC_OMP_DISTRIBUTE:
4065 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
4066 case EXEC_OMP_TEAMS_DISTRIBUTE:
4067 /* This is handled in gfc_trans_omp_do. */
4068 gcc_unreachable ();
4069 break;
4070 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
4071 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
4072 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
4073 stmt = gfc_trans_omp_parallel_do (code, &block, clausesa);
4074 if (TREE_CODE (stmt) != BIND_EXPR)
4075 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
4076 else
4077 poplevel (0, 0);
4078 break;
4079 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
4080 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
4081 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
4082 stmt = gfc_trans_omp_parallel_do_simd (code, &block, clausesa);
4083 if (TREE_CODE (stmt) != BIND_EXPR)
4084 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
4085 else
4086 poplevel (0, 0);
4087 break;
4088 case EXEC_OMP_DISTRIBUTE_SIMD:
4089 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
4090 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
4091 stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
4092 &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
4093 if (TREE_CODE (stmt) != BIND_EXPR)
4094 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
4095 else
4096 poplevel (0, 0);
4097 break;
4098 default:
4099 gcc_unreachable ();
4101 if (flag_openmp)
4103 tree distribute = make_node (OMP_DISTRIBUTE);
4104 TREE_TYPE (distribute) = void_type_node;
4105 OMP_FOR_BODY (distribute) = stmt;
4106 OMP_FOR_CLAUSES (distribute) = omp_clauses;
4107 stmt = distribute;
4109 gfc_add_expr_to_block (&block, stmt);
4110 return gfc_finish_block (&block);
4113 static tree
4114 gfc_trans_omp_teams (gfc_code *code, gfc_omp_clauses *clausesa)
4116 stmtblock_t block;
4117 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
4118 tree stmt, omp_clauses = NULL_TREE;
4120 gfc_start_block (&block);
4121 if (clausesa == NULL)
4123 clausesa = clausesa_buf;
4124 gfc_split_omp_clauses (code, clausesa);
4126 if (flag_openmp)
4127 omp_clauses
4128 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TEAMS],
4129 code->loc);
4130 switch (code->op)
4132 case EXEC_OMP_TARGET_TEAMS:
4133 case EXEC_OMP_TEAMS:
4134 stmt = gfc_trans_omp_code (code->block->next, true);
4135 break;
4136 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
4137 case EXEC_OMP_TEAMS_DISTRIBUTE:
4138 stmt = gfc_trans_omp_do (code, EXEC_OMP_DISTRIBUTE, NULL,
4139 &clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
4140 NULL);
4141 break;
4142 default:
4143 stmt = gfc_trans_omp_distribute (code, clausesa);
4144 break;
4146 stmt = build2_loc (input_location, OMP_TEAMS, void_type_node, stmt,
4147 omp_clauses);
4148 gfc_add_expr_to_block (&block, stmt);
4149 return gfc_finish_block (&block);
4152 static tree
4153 gfc_trans_omp_target (gfc_code *code)
4155 stmtblock_t block;
4156 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
4157 tree stmt, omp_clauses = NULL_TREE;
4159 gfc_start_block (&block);
4160 gfc_split_omp_clauses (code, clausesa);
4161 if (flag_openmp)
4162 omp_clauses
4163 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TARGET],
4164 code->loc);
4165 if (code->op == EXEC_OMP_TARGET)
4166 stmt = gfc_trans_omp_code (code->block->next, true);
4167 else
4168 stmt = gfc_trans_omp_teams (code, clausesa);
4169 if (TREE_CODE (stmt) != BIND_EXPR)
4170 stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
4171 if (flag_openmp)
4172 stmt = build2_loc (input_location, OMP_TARGET, void_type_node, stmt,
4173 omp_clauses);
4174 gfc_add_expr_to_block (&block, stmt);
4175 return gfc_finish_block (&block);
4178 static tree
4179 gfc_trans_omp_target_data (gfc_code *code)
4181 stmtblock_t block;
4182 tree stmt, omp_clauses;
4184 gfc_start_block (&block);
4185 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
4186 code->loc);
4187 stmt = gfc_trans_omp_code (code->block->next, true);
4188 stmt = build2_loc (input_location, OMP_TARGET_DATA, void_type_node, stmt,
4189 omp_clauses);
4190 gfc_add_expr_to_block (&block, stmt);
4191 return gfc_finish_block (&block);
4194 static tree
4195 gfc_trans_omp_target_update (gfc_code *code)
4197 stmtblock_t block;
4198 tree stmt, omp_clauses;
4200 gfc_start_block (&block);
4201 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
4202 code->loc);
4203 stmt = build1_loc (input_location, OMP_TARGET_UPDATE, void_type_node,
4204 omp_clauses);
4205 gfc_add_expr_to_block (&block, stmt);
4206 return gfc_finish_block (&block);
4209 static tree
4210 gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses)
4212 tree res, tmp, stmt;
4213 stmtblock_t block, *pblock = NULL;
4214 stmtblock_t singleblock;
4215 int saved_ompws_flags;
4216 bool singleblock_in_progress = false;
4217 /* True if previous gfc_code in workshare construct is not workshared. */
4218 bool prev_singleunit;
4220 code = code->block->next;
4222 pushlevel ();
4224 gfc_start_block (&block);
4225 pblock = &block;
4227 ompws_flags = OMPWS_WORKSHARE_FLAG;
4228 prev_singleunit = false;
4230 /* Translate statements one by one to trees until we reach
4231 the end of the workshare construct. Adjacent gfc_codes that
4232 are a single unit of work are clustered and encapsulated in a
4233 single OMP_SINGLE construct. */
4234 for (; code; code = code->next)
4236 if (code->here != 0)
4238 res = gfc_trans_label_here (code);
4239 gfc_add_expr_to_block (pblock, res);
4242 /* No dependence analysis, use for clauses with wait.
4243 If this is the last gfc_code, use default omp_clauses. */
4244 if (code->next == NULL && clauses->nowait)
4245 ompws_flags |= OMPWS_NOWAIT;
4247 /* By default, every gfc_code is a single unit of work. */
4248 ompws_flags |= OMPWS_CURR_SINGLEUNIT;
4249 ompws_flags &= ~OMPWS_SCALARIZER_WS;
4251 switch (code->op)
4253 case EXEC_NOP:
4254 res = NULL_TREE;
4255 break;
4257 case EXEC_ASSIGN:
4258 res = gfc_trans_assign (code);
4259 break;
4261 case EXEC_POINTER_ASSIGN:
4262 res = gfc_trans_pointer_assign (code);
4263 break;
4265 case EXEC_INIT_ASSIGN:
4266 res = gfc_trans_init_assign (code);
4267 break;
4269 case EXEC_FORALL:
4270 res = gfc_trans_forall (code);
4271 break;
4273 case EXEC_WHERE:
4274 res = gfc_trans_where (code);
4275 break;
4277 case EXEC_OMP_ATOMIC:
4278 res = gfc_trans_omp_directive (code);
4279 break;
4281 case EXEC_OMP_PARALLEL:
4282 case EXEC_OMP_PARALLEL_DO:
4283 case EXEC_OMP_PARALLEL_SECTIONS:
4284 case EXEC_OMP_PARALLEL_WORKSHARE:
4285 case EXEC_OMP_CRITICAL:
4286 saved_ompws_flags = ompws_flags;
4287 ompws_flags = 0;
4288 res = gfc_trans_omp_directive (code);
4289 ompws_flags = saved_ompws_flags;
4290 break;
4292 default:
4293 gfc_internal_error ("gfc_trans_omp_workshare(): Bad statement code");
4296 gfc_set_backend_locus (&code->loc);
4298 if (res != NULL_TREE && ! IS_EMPTY_STMT (res))
4300 if (prev_singleunit)
4302 if (ompws_flags & OMPWS_CURR_SINGLEUNIT)
4303 /* Add current gfc_code to single block. */
4304 gfc_add_expr_to_block (&singleblock, res);
4305 else
4307 /* Finish single block and add it to pblock. */
4308 tmp = gfc_finish_block (&singleblock);
4309 tmp = build2_loc (input_location, OMP_SINGLE,
4310 void_type_node, tmp, NULL_TREE);
4311 gfc_add_expr_to_block (pblock, tmp);
4312 /* Add current gfc_code to pblock. */
4313 gfc_add_expr_to_block (pblock, res);
4314 singleblock_in_progress = false;
4317 else
4319 if (ompws_flags & OMPWS_CURR_SINGLEUNIT)
4321 /* Start single block. */
4322 gfc_init_block (&singleblock);
4323 gfc_add_expr_to_block (&singleblock, res);
4324 singleblock_in_progress = true;
4326 else
4327 /* Add the new statement to the block. */
4328 gfc_add_expr_to_block (pblock, res);
4330 prev_singleunit = (ompws_flags & OMPWS_CURR_SINGLEUNIT) != 0;
4334 /* Finish remaining SINGLE block, if we were in the middle of one. */
4335 if (singleblock_in_progress)
4337 /* Finish single block and add it to pblock. */
4338 tmp = gfc_finish_block (&singleblock);
4339 tmp = build2_loc (input_location, OMP_SINGLE, void_type_node, tmp,
4340 clauses->nowait
4341 ? build_omp_clause (input_location, OMP_CLAUSE_NOWAIT)
4342 : NULL_TREE);
4343 gfc_add_expr_to_block (pblock, tmp);
4346 stmt = gfc_finish_block (pblock);
4347 if (TREE_CODE (stmt) != BIND_EXPR)
4349 if (!IS_EMPTY_STMT (stmt))
4351 tree bindblock = poplevel (1, 0);
4352 stmt = build3_v (BIND_EXPR, NULL, stmt, bindblock);
4354 else
4355 poplevel (0, 0);
4357 else
4358 poplevel (0, 0);
4360 if (IS_EMPTY_STMT (stmt) && !clauses->nowait)
4361 stmt = gfc_trans_omp_barrier ();
4363 ompws_flags = 0;
4364 return stmt;
4367 tree
4368 gfc_trans_oacc_declare (stmtblock_t *block, gfc_namespace *ns)
4370 tree oacc_clauses;
4371 oacc_clauses = gfc_trans_omp_clauses (block, ns->oacc_declare_clauses,
4372 ns->oacc_declare_clauses->loc);
4373 return build1_loc (ns->oacc_declare_clauses->loc.lb->location,
4374 OACC_DECLARE, void_type_node, oacc_clauses);
4377 tree
4378 gfc_trans_oacc_directive (gfc_code *code)
4380 switch (code->op)
4382 case EXEC_OACC_PARALLEL_LOOP:
4383 case EXEC_OACC_KERNELS_LOOP:
4384 return gfc_trans_oacc_combined_directive (code);
4385 case EXEC_OACC_PARALLEL:
4386 case EXEC_OACC_KERNELS:
4387 case EXEC_OACC_DATA:
4388 case EXEC_OACC_HOST_DATA:
4389 return gfc_trans_oacc_construct (code);
4390 case EXEC_OACC_LOOP:
4391 return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses,
4392 NULL);
4393 case EXEC_OACC_UPDATE:
4394 case EXEC_OACC_CACHE:
4395 case EXEC_OACC_ENTER_DATA:
4396 case EXEC_OACC_EXIT_DATA:
4397 return gfc_trans_oacc_executable_directive (code);
4398 case EXEC_OACC_WAIT:
4399 return gfc_trans_oacc_wait_directive (code);
4400 default:
4401 gcc_unreachable ();
4405 tree
4406 gfc_trans_omp_directive (gfc_code *code)
4408 switch (code->op)
4410 case EXEC_OMP_ATOMIC:
4411 return gfc_trans_omp_atomic (code);
4412 case EXEC_OMP_BARRIER:
4413 return gfc_trans_omp_barrier ();
4414 case EXEC_OMP_CANCEL:
4415 return gfc_trans_omp_cancel (code);
4416 case EXEC_OMP_CANCELLATION_POINT:
4417 return gfc_trans_omp_cancellation_point (code);
4418 case EXEC_OMP_CRITICAL:
4419 return gfc_trans_omp_critical (code);
4420 case EXEC_OMP_DISTRIBUTE:
4421 case EXEC_OMP_DO:
4422 case EXEC_OMP_SIMD:
4423 return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses,
4424 NULL);
4425 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
4426 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
4427 case EXEC_OMP_DISTRIBUTE_SIMD:
4428 return gfc_trans_omp_distribute (code, NULL);
4429 case EXEC_OMP_DO_SIMD:
4430 return gfc_trans_omp_do_simd (code, NULL, NULL, NULL_TREE);
4431 case EXEC_OMP_FLUSH:
4432 return gfc_trans_omp_flush ();
4433 case EXEC_OMP_MASTER:
4434 return gfc_trans_omp_master (code);
4435 case EXEC_OMP_ORDERED:
4436 return gfc_trans_omp_ordered (code);
4437 case EXEC_OMP_PARALLEL:
4438 return gfc_trans_omp_parallel (code);
4439 case EXEC_OMP_PARALLEL_DO:
4440 return gfc_trans_omp_parallel_do (code, NULL, NULL);
4441 case EXEC_OMP_PARALLEL_DO_SIMD:
4442 return gfc_trans_omp_parallel_do_simd (code, NULL, NULL);
4443 case EXEC_OMP_PARALLEL_SECTIONS:
4444 return gfc_trans_omp_parallel_sections (code);
4445 case EXEC_OMP_PARALLEL_WORKSHARE:
4446 return gfc_trans_omp_parallel_workshare (code);
4447 case EXEC_OMP_SECTIONS:
4448 return gfc_trans_omp_sections (code, code->ext.omp_clauses);
4449 case EXEC_OMP_SINGLE:
4450 return gfc_trans_omp_single (code, code->ext.omp_clauses);
4451 case EXEC_OMP_TARGET:
4452 case EXEC_OMP_TARGET_TEAMS:
4453 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
4454 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
4455 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
4456 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
4457 return gfc_trans_omp_target (code);
4458 case EXEC_OMP_TARGET_DATA:
4459 return gfc_trans_omp_target_data (code);
4460 case EXEC_OMP_TARGET_UPDATE:
4461 return gfc_trans_omp_target_update (code);
4462 case EXEC_OMP_TASK:
4463 return gfc_trans_omp_task (code);
4464 case EXEC_OMP_TASKGROUP:
4465 return gfc_trans_omp_taskgroup (code);
4466 case EXEC_OMP_TASKWAIT:
4467 return gfc_trans_omp_taskwait ();
4468 case EXEC_OMP_TASKYIELD:
4469 return gfc_trans_omp_taskyield ();
4470 case EXEC_OMP_TEAMS:
4471 case EXEC_OMP_TEAMS_DISTRIBUTE:
4472 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
4473 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
4474 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
4475 return gfc_trans_omp_teams (code, NULL);
4476 case EXEC_OMP_WORKSHARE:
4477 return gfc_trans_omp_workshare (code, code->ext.omp_clauses);
4478 default:
4479 gcc_unreachable ();
4483 void
4484 gfc_trans_omp_declare_simd (gfc_namespace *ns)
4486 if (ns->entries)
4487 return;
4489 gfc_omp_declare_simd *ods;
4490 for (ods = ns->omp_declare_simd; ods; ods = ods->next)
4492 tree c = gfc_trans_omp_clauses (NULL, ods->clauses, ods->where, true);
4493 tree fndecl = ns->proc_name->backend_decl;
4494 if (c != NULL_TREE)
4495 c = tree_cons (NULL_TREE, c, NULL_TREE);
4496 c = build_tree_list (get_identifier ("omp declare simd"), c);
4497 TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
4498 DECL_ATTRIBUTES (fndecl) = c;