]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/fortran/trans-openmp.c
Update copyright years.
[thirdparty/gcc.git] / gcc / fortran / trans-openmp.c
1 /* OpenMP directive translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2005-2020 Free Software Foundation, Inc.
3 Contributed by Jakub Jelinek <jakub@redhat.com>
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "options.h"
26 #include "tree.h"
27 #include "gfortran.h"
28 #include "gimple-expr.h"
29 #include "trans.h"
30 #include "stringpool.h"
31 #include "fold-const.h"
32 #include "gimplify.h" /* For create_tmp_var_raw. */
33 #include "trans-stmt.h"
34 #include "trans-types.h"
35 #include "trans-array.h"
36 #include "trans-const.h"
37 #include "arith.h"
38 #include "gomp-constants.h"
39 #include "omp-general.h"
40 #include "omp-low.h"
41 #undef GCC_DIAG_STYLE
42 #define GCC_DIAG_STYLE __gcc_tdiag__
43 #include "diagnostic-core.h"
44 #undef GCC_DIAG_STYLE
45 #define GCC_DIAG_STYLE __gcc_gfc__
46 #include "attribs.h"
47
48 int ompws_flags;
49
50 /* True if OpenMP should regard this DECL as being a scalar which has Fortran's
51 allocatable or pointer attribute. */
52
53 bool
54 gfc_omp_is_allocatable_or_ptr (const_tree decl)
55 {
56 return (DECL_P (decl)
57 && (GFC_DECL_GET_SCALAR_POINTER (decl)
58 || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)));
59 }
60
61 /* True if the argument is an optional argument; except that false is also
62 returned for arguments with the value attribute (nonpointers) and for
63 assumed-shape variables (decl is a local variable containing arg->data).
64 Note that pvoid_type_node is for 'type(c_ptr), value. */
65
66 static bool
67 gfc_omp_is_optional_argument (const_tree decl)
68 {
69 return (TREE_CODE (decl) == PARM_DECL
70 && DECL_LANG_SPECIFIC (decl)
71 && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
72 && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
73 && GFC_DECL_OPTIONAL_ARGUMENT (decl));
74 }
75
76 /* Check whether this DECL belongs to a Fortran optional argument.
77 With 'for_present_check' set to false, decls which are optional parameters
78 themselve are returned as tree - or a NULL_TREE otherwise. Those decls are
79 always pointers. With 'for_present_check' set to true, the decl for checking
80 whether an argument is present is returned; for arguments with value
81 attribute this is the hidden argument and of BOOLEAN_TYPE. If the decl is
82 unrelated to optional arguments, NULL_TREE is returned. */
83
84 tree
85 gfc_omp_check_optional_argument (tree decl, bool for_present_check)
86 {
87 if (!for_present_check)
88 return gfc_omp_is_optional_argument (decl) ? decl : NULL_TREE;
89
90 if (!DECL_LANG_SPECIFIC (decl))
91 return NULL_TREE;
92
93 /* For assumed-shape arrays, a local decl with arg->data is used. */
94 if (TREE_CODE (decl) != PARM_DECL
95 && (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))
96 || GFC_ARRAY_TYPE_P (TREE_TYPE (decl))))
97 decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
98
99 if (TREE_CODE (decl) != PARM_DECL
100 || !DECL_LANG_SPECIFIC (decl)
101 || !GFC_DECL_OPTIONAL_ARGUMENT (decl))
102 return NULL_TREE;
103
104 /* Scalars with VALUE attribute which are passed by value use a hidden
105 argument to denote the present status. They are passed as nonpointer type
106 with one exception: 'type(c_ptr), value' as 'void*'. */
107 /* Cf. trans-expr.c's gfc_conv_expr_present. */
108 if (TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE
109 || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
110 {
111 char name[GFC_MAX_SYMBOL_LEN + 2];
112 tree tree_name;
113
114 name[0] = '_';
115 strcpy (&name[1], IDENTIFIER_POINTER (DECL_NAME (decl)));
116 tree_name = get_identifier (name);
117
118 /* Walk function argument list to find the hidden arg. */
119 decl = DECL_ARGUMENTS (DECL_CONTEXT (decl));
120 for ( ; decl != NULL_TREE; decl = TREE_CHAIN (decl))
121 if (DECL_NAME (decl) == tree_name
122 && DECL_ARTIFICIAL (decl))
123 break;
124
125 gcc_assert (decl);
126 return decl;
127 }
128
129 return decl;
130 }
131
132
133 /* Returns tree with NULL if it is not an array descriptor and with the tree to
134 access the 'data' component otherwise. With type_only = true, it returns the
135 TREE_TYPE without creating a new tree. */
136
137 tree
138 gfc_omp_array_data (tree decl, bool type_only)
139 {
140 tree type = TREE_TYPE (decl);
141
142 if (POINTER_TYPE_P (type))
143 type = TREE_TYPE (type);
144
145 if (!GFC_DESCRIPTOR_TYPE_P (type))
146 return NULL_TREE;
147
148 if (type_only)
149 return GFC_TYPE_ARRAY_DATAPTR_TYPE (type);
150
151 if (POINTER_TYPE_P (TREE_TYPE (decl)))
152 decl = build_fold_indirect_ref (decl);
153
154 decl = gfc_conv_descriptor_data_get (decl);
155 STRIP_NOPS (decl);
156 return decl;
157 }
158
159 /* True if OpenMP should privatize what this DECL points to rather
160 than the DECL itself. */
161
162 bool
163 gfc_omp_privatize_by_reference (const_tree decl)
164 {
165 tree type = TREE_TYPE (decl);
166
167 if (TREE_CODE (type) == REFERENCE_TYPE
168 && (!DECL_ARTIFICIAL (decl) || TREE_CODE (decl) == PARM_DECL))
169 return true;
170
171 if (TREE_CODE (type) == POINTER_TYPE
172 && gfc_omp_is_optional_argument (decl))
173 return true;
174
175 if (TREE_CODE (type) == POINTER_TYPE)
176 {
177 while (TREE_CODE (decl) == COMPONENT_REF)
178 decl = TREE_OPERAND (decl, 1);
179
180 /* Array POINTER/ALLOCATABLE have aggregate types, all user variables
181 that have POINTER_TYPE type and aren't scalar pointers, scalar
182 allocatables, Cray pointees or C pointers are supposed to be
183 privatized by reference. */
184 if (GFC_DECL_GET_SCALAR_POINTER (decl)
185 || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
186 || GFC_DECL_CRAY_POINTEE (decl)
187 || GFC_DECL_ASSOCIATE_VAR_P (decl)
188 || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
189 return false;
190
191 if (!DECL_ARTIFICIAL (decl)
192 && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
193 return true;
194
195 /* Some arrays are expanded as DECL_ARTIFICIAL pointers
196 by the frontend. */
197 if (DECL_LANG_SPECIFIC (decl)
198 && GFC_DECL_SAVED_DESCRIPTOR (decl))
199 return true;
200 }
201
202 return false;
203 }
204
205 /* True if OpenMP sharing attribute of DECL is predetermined. */
206
207 enum omp_clause_default_kind
208 gfc_omp_predetermined_sharing (tree decl)
209 {
210 /* Associate names preserve the association established during ASSOCIATE.
211 As they are implemented either as pointers to the selector or array
212 descriptor and shouldn't really change in the ASSOCIATE region,
213 this decl can be either shared or firstprivate. If it is a pointer,
214 use firstprivate, as it is cheaper that way, otherwise make it shared. */
215 if (GFC_DECL_ASSOCIATE_VAR_P (decl))
216 {
217 if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
218 return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
219 else
220 return OMP_CLAUSE_DEFAULT_SHARED;
221 }
222
223 if (DECL_ARTIFICIAL (decl)
224 && ! GFC_DECL_RESULT (decl)
225 && ! (DECL_LANG_SPECIFIC (decl)
226 && GFC_DECL_SAVED_DESCRIPTOR (decl)))
227 return OMP_CLAUSE_DEFAULT_SHARED;
228
229 /* Cray pointees shouldn't be listed in any clauses and should be
230 gimplified to dereference of the corresponding Cray pointer.
231 Make them all private, so that they are emitted in the debug
232 information. */
233 if (GFC_DECL_CRAY_POINTEE (decl))
234 return OMP_CLAUSE_DEFAULT_PRIVATE;
235
236 /* Assumed-size arrays are predetermined shared. */
237 if (TREE_CODE (decl) == PARM_DECL
238 && GFC_ARRAY_TYPE_P (TREE_TYPE (decl))
239 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN
240 && GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (decl),
241 GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)) - 1)
242 == NULL)
243 return OMP_CLAUSE_DEFAULT_SHARED;
244
245 /* Dummy procedures aren't considered variables by OpenMP, thus are
246 disallowed in OpenMP clauses. They are represented as PARM_DECLs
247 in the middle-end, so return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE here
248 to avoid complaining about their uses with default(none). */
249 if (TREE_CODE (decl) == PARM_DECL
250 && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
251 && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == FUNCTION_TYPE)
252 return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
253
254 /* COMMON and EQUIVALENCE decls are shared. They
255 are only referenced through DECL_VALUE_EXPR of the variables
256 contained in them. If those are privatized, they will not be
257 gimplified to the COMMON or EQUIVALENCE decls. */
258 if (GFC_DECL_COMMON_OR_EQUIV (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
259 return OMP_CLAUSE_DEFAULT_SHARED;
260
261 if (GFC_DECL_RESULT (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
262 return OMP_CLAUSE_DEFAULT_SHARED;
263
264 /* These are either array or derived parameters, or vtables.
265 In the former cases, the OpenMP standard doesn't consider them to be
266 variables at all (they can't be redefined), but they can nevertheless appear
267 in parallel/task regions and for default(none) purposes treat them as shared.
268 For vtables likely the same handling is desirable. */
269 if (VAR_P (decl) && TREE_READONLY (decl)
270 && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
271 return OMP_CLAUSE_DEFAULT_SHARED;
272
273 return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
274 }
275
276 /* Return decl that should be used when reporting DEFAULT(NONE)
277 diagnostics. */
278
279 tree
280 gfc_omp_report_decl (tree decl)
281 {
282 if (DECL_ARTIFICIAL (decl)
283 && DECL_LANG_SPECIFIC (decl)
284 && GFC_DECL_SAVED_DESCRIPTOR (decl))
285 return GFC_DECL_SAVED_DESCRIPTOR (decl);
286
287 return decl;
288 }
289
290 /* Return true if TYPE has any allocatable components. */
291
292 static bool
293 gfc_has_alloc_comps (tree type, tree decl)
294 {
295 tree field, ftype;
296
297 if (POINTER_TYPE_P (type))
298 {
299 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
300 type = TREE_TYPE (type);
301 else if (GFC_DECL_GET_SCALAR_POINTER (decl))
302 return false;
303 }
304
305 if (GFC_DESCRIPTOR_TYPE_P (type) || GFC_ARRAY_TYPE_P (type))
306 type = gfc_get_element_type (type);
307
308 if (TREE_CODE (type) != RECORD_TYPE)
309 return false;
310
311 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
312 {
313 ftype = TREE_TYPE (field);
314 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
315 return true;
316 if (GFC_DESCRIPTOR_TYPE_P (ftype)
317 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
318 return true;
319 if (gfc_has_alloc_comps (ftype, field))
320 return true;
321 }
322 return false;
323 }
324
325 /* Return true if DECL in private clause needs
326 OMP_CLAUSE_PRIVATE_OUTER_REF on the private clause. */
327 bool
328 gfc_omp_private_outer_ref (tree decl)
329 {
330 tree type = TREE_TYPE (decl);
331
332 if (gfc_omp_privatize_by_reference (decl))
333 type = TREE_TYPE (type);
334
335 if (GFC_DESCRIPTOR_TYPE_P (type)
336 && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
337 return true;
338
339 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
340 return true;
341
342 if (gfc_has_alloc_comps (type, decl))
343 return true;
344
345 return false;
346 }
347
348 /* Callback for gfc_omp_unshare_expr. */
349
350 static tree
351 gfc_omp_unshare_expr_r (tree *tp, int *walk_subtrees, void *)
352 {
353 tree t = *tp;
354 enum tree_code code = TREE_CODE (t);
355
356 /* Stop at types, decls, constants like copy_tree_r. */
357 if (TREE_CODE_CLASS (code) == tcc_type
358 || TREE_CODE_CLASS (code) == tcc_declaration
359 || TREE_CODE_CLASS (code) == tcc_constant
360 || code == BLOCK)
361 *walk_subtrees = 0;
362 else if (handled_component_p (t)
363 || TREE_CODE (t) == MEM_REF)
364 {
365 *tp = unshare_expr (t);
366 *walk_subtrees = 0;
367 }
368
369 return NULL_TREE;
370 }
371
372 /* Unshare in expr anything that the FE which normally doesn't
373 care much about tree sharing (because during gimplification
374 everything is unshared) could cause problems with tree sharing
375 at omp-low.c time. */
376
377 static tree
378 gfc_omp_unshare_expr (tree expr)
379 {
380 walk_tree (&expr, gfc_omp_unshare_expr_r, NULL, NULL);
381 return expr;
382 }
383
384 enum walk_alloc_comps
385 {
386 WALK_ALLOC_COMPS_DTOR,
387 WALK_ALLOC_COMPS_DEFAULT_CTOR,
388 WALK_ALLOC_COMPS_COPY_CTOR
389 };
390
391 /* Handle allocatable components in OpenMP clauses. */
392
393 static tree
394 gfc_walk_alloc_comps (tree decl, tree dest, tree var,
395 enum walk_alloc_comps kind)
396 {
397 stmtblock_t block, tmpblock;
398 tree type = TREE_TYPE (decl), then_b, tem, field;
399 gfc_init_block (&block);
400
401 if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
402 {
403 if (GFC_DESCRIPTOR_TYPE_P (type))
404 {
405 gfc_init_block (&tmpblock);
406 tem = gfc_full_array_size (&tmpblock, decl,
407 GFC_TYPE_ARRAY_RANK (type));
408 then_b = gfc_finish_block (&tmpblock);
409 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (then_b));
410 tem = gfc_omp_unshare_expr (tem);
411 tem = fold_build2_loc (input_location, MINUS_EXPR,
412 gfc_array_index_type, tem,
413 gfc_index_one_node);
414 }
415 else
416 {
417 bool compute_nelts = false;
418 if (!TYPE_DOMAIN (type)
419 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE
420 || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node
421 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node)
422 compute_nelts = true;
423 else if (VAR_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
424 {
425 tree a = DECL_ATTRIBUTES (TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
426 if (lookup_attribute ("omp dummy var", a))
427 compute_nelts = true;
428 }
429 if (compute_nelts)
430 {
431 tem = fold_build2 (EXACT_DIV_EXPR, sizetype,
432 TYPE_SIZE_UNIT (type),
433 TYPE_SIZE_UNIT (TREE_TYPE (type)));
434 tem = size_binop (MINUS_EXPR, tem, size_one_node);
435 }
436 else
437 tem = array_type_nelts (type);
438 tem = fold_convert (gfc_array_index_type, tem);
439 }
440
441 tree nelems = gfc_evaluate_now (tem, &block);
442 tree index = gfc_create_var (gfc_array_index_type, "S");
443
444 gfc_init_block (&tmpblock);
445 tem = gfc_conv_array_data (decl);
446 tree declvar = build_fold_indirect_ref_loc (input_location, tem);
447 tree declvref = gfc_build_array_ref (declvar, index, NULL);
448 tree destvar, destvref = NULL_TREE;
449 if (dest)
450 {
451 tem = gfc_conv_array_data (dest);
452 destvar = build_fold_indirect_ref_loc (input_location, tem);
453 destvref = gfc_build_array_ref (destvar, index, NULL);
454 }
455 gfc_add_expr_to_block (&tmpblock,
456 gfc_walk_alloc_comps (declvref, destvref,
457 var, kind));
458
459 gfc_loopinfo loop;
460 gfc_init_loopinfo (&loop);
461 loop.dimen = 1;
462 loop.from[0] = gfc_index_zero_node;
463 loop.loopvar[0] = index;
464 loop.to[0] = nelems;
465 gfc_trans_scalarizing_loops (&loop, &tmpblock);
466 gfc_add_block_to_block (&block, &loop.pre);
467 return gfc_finish_block (&block);
468 }
469 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (var))
470 {
471 decl = build_fold_indirect_ref_loc (input_location, decl);
472 if (dest)
473 dest = build_fold_indirect_ref_loc (input_location, dest);
474 type = TREE_TYPE (decl);
475 }
476
477 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
478 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
479 {
480 tree ftype = TREE_TYPE (field);
481 tree declf, destf = NULL_TREE;
482 bool has_alloc_comps = gfc_has_alloc_comps (ftype, field);
483 if ((!GFC_DESCRIPTOR_TYPE_P (ftype)
484 || GFC_TYPE_ARRAY_AKIND (ftype) != GFC_ARRAY_ALLOCATABLE)
485 && !GFC_DECL_GET_SCALAR_ALLOCATABLE (field)
486 && !has_alloc_comps)
487 continue;
488 declf = fold_build3_loc (input_location, COMPONENT_REF, ftype,
489 decl, field, NULL_TREE);
490 if (dest)
491 destf = fold_build3_loc (input_location, COMPONENT_REF, ftype,
492 dest, field, NULL_TREE);
493
494 tem = NULL_TREE;
495 switch (kind)
496 {
497 case WALK_ALLOC_COMPS_DTOR:
498 break;
499 case WALK_ALLOC_COMPS_DEFAULT_CTOR:
500 if (GFC_DESCRIPTOR_TYPE_P (ftype)
501 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
502 {
503 gfc_add_modify (&block, unshare_expr (destf),
504 unshare_expr (declf));
505 tem = gfc_duplicate_allocatable_nocopy
506 (destf, declf, ftype,
507 GFC_TYPE_ARRAY_RANK (ftype));
508 }
509 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
510 tem = gfc_duplicate_allocatable_nocopy (destf, declf, ftype, 0);
511 break;
512 case WALK_ALLOC_COMPS_COPY_CTOR:
513 if (GFC_DESCRIPTOR_TYPE_P (ftype)
514 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
515 tem = gfc_duplicate_allocatable (destf, declf, ftype,
516 GFC_TYPE_ARRAY_RANK (ftype),
517 NULL_TREE);
518 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
519 tem = gfc_duplicate_allocatable (destf, declf, ftype, 0,
520 NULL_TREE);
521 break;
522 }
523 if (tem)
524 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
525 if (has_alloc_comps)
526 {
527 gfc_init_block (&tmpblock);
528 gfc_add_expr_to_block (&tmpblock,
529 gfc_walk_alloc_comps (declf, destf,
530 field, kind));
531 then_b = gfc_finish_block (&tmpblock);
532 if (GFC_DESCRIPTOR_TYPE_P (ftype)
533 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
534 tem = gfc_conv_descriptor_data_get (unshare_expr (declf));
535 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
536 tem = unshare_expr (declf);
537 else
538 tem = NULL_TREE;
539 if (tem)
540 {
541 tem = fold_convert (pvoid_type_node, tem);
542 tem = fold_build2_loc (input_location, NE_EXPR,
543 logical_type_node, tem,
544 null_pointer_node);
545 then_b = build3_loc (input_location, COND_EXPR, void_type_node,
546 tem, then_b,
547 build_empty_stmt (input_location));
548 }
549 gfc_add_expr_to_block (&block, then_b);
550 }
551 if (kind == WALK_ALLOC_COMPS_DTOR)
552 {
553 if (GFC_DESCRIPTOR_TYPE_P (ftype)
554 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
555 {
556 tem = gfc_conv_descriptor_data_get (unshare_expr (declf));
557 tem = gfc_deallocate_with_status (tem, NULL_TREE, NULL_TREE,
558 NULL_TREE, NULL_TREE, true,
559 NULL,
560 GFC_CAF_COARRAY_NOCOARRAY);
561 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
562 }
563 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
564 {
565 tem = gfc_call_free (unshare_expr (declf));
566 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
567 }
568 }
569 }
570
571 return gfc_finish_block (&block);
572 }
573
574 /* Return code to initialize DECL with its default constructor, or
575 NULL if there's nothing to do. */
576
577 tree
578 gfc_omp_clause_default_ctor (tree clause, tree decl, tree outer)
579 {
580 tree type = TREE_TYPE (decl), size, ptr, cond, then_b, else_b;
581 stmtblock_t block, cond_block;
582
583 gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_PRIVATE
584 || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LASTPRIVATE
585 || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR
586 || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_REDUCTION);
587
588 if ((! GFC_DESCRIPTOR_TYPE_P (type)
589 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
590 && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
591 || !POINTER_TYPE_P (type)))
592 {
593 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
594 {
595 gcc_assert (outer);
596 gfc_start_block (&block);
597 tree tem = gfc_walk_alloc_comps (outer, decl,
598 OMP_CLAUSE_DECL (clause),
599 WALK_ALLOC_COMPS_DEFAULT_CTOR);
600 gfc_add_expr_to_block (&block, tem);
601 return gfc_finish_block (&block);
602 }
603 return NULL_TREE;
604 }
605
606 gcc_assert (outer != NULL_TREE);
607
608 /* Allocatable arrays and scalars in PRIVATE clauses need to be set to
609 "not currently allocated" allocation status if outer
610 array is "not currently allocated", otherwise should be allocated. */
611 gfc_start_block (&block);
612
613 gfc_init_block (&cond_block);
614
615 if (GFC_DESCRIPTOR_TYPE_P (type))
616 {
617 gfc_add_modify (&cond_block, decl, outer);
618 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
619 size = gfc_conv_descriptor_ubound_get (decl, rank);
620 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
621 size,
622 gfc_conv_descriptor_lbound_get (decl, rank));
623 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
624 size, gfc_index_one_node);
625 if (GFC_TYPE_ARRAY_RANK (type) > 1)
626 size = fold_build2_loc (input_location, MULT_EXPR,
627 gfc_array_index_type, size,
628 gfc_conv_descriptor_stride_get (decl, rank));
629 tree esize = fold_convert (gfc_array_index_type,
630 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
631 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
632 size, esize);
633 size = unshare_expr (size);
634 size = gfc_evaluate_now (fold_convert (size_type_node, size),
635 &cond_block);
636 }
637 else
638 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
639 ptr = gfc_create_var (pvoid_type_node, NULL);
640 gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
641 if (GFC_DESCRIPTOR_TYPE_P (type))
642 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl), ptr);
643 else
644 gfc_add_modify (&cond_block, unshare_expr (decl),
645 fold_convert (TREE_TYPE (decl), ptr));
646 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
647 {
648 tree tem = gfc_walk_alloc_comps (outer, decl,
649 OMP_CLAUSE_DECL (clause),
650 WALK_ALLOC_COMPS_DEFAULT_CTOR);
651 gfc_add_expr_to_block (&cond_block, tem);
652 }
653 then_b = gfc_finish_block (&cond_block);
654
655 /* Reduction clause requires allocated ALLOCATABLE. */
656 if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_REDUCTION)
657 {
658 gfc_init_block (&cond_block);
659 if (GFC_DESCRIPTOR_TYPE_P (type))
660 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl),
661 null_pointer_node);
662 else
663 gfc_add_modify (&cond_block, unshare_expr (decl),
664 build_zero_cst (TREE_TYPE (decl)));
665 else_b = gfc_finish_block (&cond_block);
666
667 tree tem = fold_convert (pvoid_type_node,
668 GFC_DESCRIPTOR_TYPE_P (type)
669 ? gfc_conv_descriptor_data_get (outer) : outer);
670 tem = unshare_expr (tem);
671 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
672 tem, null_pointer_node);
673 gfc_add_expr_to_block (&block,
674 build3_loc (input_location, COND_EXPR,
675 void_type_node, cond, then_b,
676 else_b));
677 /* Avoid -W*uninitialized warnings. */
678 if (DECL_P (decl))
679 TREE_NO_WARNING (decl) = 1;
680 }
681 else
682 gfc_add_expr_to_block (&block, then_b);
683
684 return gfc_finish_block (&block);
685 }
686
687 /* Build and return code for a copy constructor from SRC to DEST. */
688
689 tree
690 gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
691 {
692 tree type = TREE_TYPE (dest), ptr, size, call;
693 tree cond, then_b, else_b;
694 stmtblock_t block, cond_block;
695
696 gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE
697 || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
698
699 if ((! GFC_DESCRIPTOR_TYPE_P (type)
700 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
701 && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
702 || !POINTER_TYPE_P (type)))
703 {
704 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
705 {
706 gfc_start_block (&block);
707 gfc_add_modify (&block, dest, src);
708 tree tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause),
709 WALK_ALLOC_COMPS_COPY_CTOR);
710 gfc_add_expr_to_block (&block, tem);
711 return gfc_finish_block (&block);
712 }
713 else
714 return build2_v (MODIFY_EXPR, dest, src);
715 }
716
717 /* Allocatable arrays in FIRSTPRIVATE clauses need to be allocated
718 and copied from SRC. */
719 gfc_start_block (&block);
720
721 gfc_init_block (&cond_block);
722
723 gfc_add_modify (&cond_block, dest, src);
724 if (GFC_DESCRIPTOR_TYPE_P (type))
725 {
726 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
727 size = gfc_conv_descriptor_ubound_get (dest, rank);
728 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
729 size,
730 gfc_conv_descriptor_lbound_get (dest, rank));
731 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
732 size, gfc_index_one_node);
733 if (GFC_TYPE_ARRAY_RANK (type) > 1)
734 size = fold_build2_loc (input_location, MULT_EXPR,
735 gfc_array_index_type, size,
736 gfc_conv_descriptor_stride_get (dest, rank));
737 tree esize = fold_convert (gfc_array_index_type,
738 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
739 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
740 size, esize);
741 size = unshare_expr (size);
742 size = gfc_evaluate_now (fold_convert (size_type_node, size),
743 &cond_block);
744 }
745 else
746 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
747 ptr = gfc_create_var (pvoid_type_node, NULL);
748 gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
749 if (GFC_DESCRIPTOR_TYPE_P (type))
750 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest), ptr);
751 else
752 gfc_add_modify (&cond_block, unshare_expr (dest),
753 fold_convert (TREE_TYPE (dest), ptr));
754
755 tree srcptr = GFC_DESCRIPTOR_TYPE_P (type)
756 ? gfc_conv_descriptor_data_get (src) : src;
757 srcptr = unshare_expr (srcptr);
758 srcptr = fold_convert (pvoid_type_node, srcptr);
759 call = build_call_expr_loc (input_location,
760 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr,
761 srcptr, size);
762 gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
763 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
764 {
765 tree tem = gfc_walk_alloc_comps (src, dest,
766 OMP_CLAUSE_DECL (clause),
767 WALK_ALLOC_COMPS_COPY_CTOR);
768 gfc_add_expr_to_block (&cond_block, tem);
769 }
770 then_b = gfc_finish_block (&cond_block);
771
772 gfc_init_block (&cond_block);
773 if (GFC_DESCRIPTOR_TYPE_P (type))
774 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest),
775 null_pointer_node);
776 else
777 gfc_add_modify (&cond_block, unshare_expr (dest),
778 build_zero_cst (TREE_TYPE (dest)));
779 else_b = gfc_finish_block (&cond_block);
780
781 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
782 unshare_expr (srcptr), null_pointer_node);
783 gfc_add_expr_to_block (&block,
784 build3_loc (input_location, COND_EXPR,
785 void_type_node, cond, then_b, else_b));
786 /* Avoid -W*uninitialized warnings. */
787 if (DECL_P (dest))
788 TREE_NO_WARNING (dest) = 1;
789
790 return gfc_finish_block (&block);
791 }
792
793 /* Similarly, except use an intrinsic or pointer assignment operator
794 instead. */
795
796 tree
797 gfc_omp_clause_assign_op (tree clause, tree dest, tree src)
798 {
799 tree type = TREE_TYPE (dest), ptr, size, call, nonalloc;
800 tree cond, then_b, else_b;
801 stmtblock_t block, cond_block, cond_block2, inner_block;
802
803 if ((! GFC_DESCRIPTOR_TYPE_P (type)
804 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
805 && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
806 || !POINTER_TYPE_P (type)))
807 {
808 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
809 {
810 gfc_start_block (&block);
811 /* First dealloc any allocatable components in DEST. */
812 tree tem = gfc_walk_alloc_comps (dest, NULL_TREE,
813 OMP_CLAUSE_DECL (clause),
814 WALK_ALLOC_COMPS_DTOR);
815 gfc_add_expr_to_block (&block, tem);
816 /* Then copy over toplevel data. */
817 gfc_add_modify (&block, dest, src);
818 /* Finally allocate any allocatable components and copy. */
819 tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause),
820 WALK_ALLOC_COMPS_COPY_CTOR);
821 gfc_add_expr_to_block (&block, tem);
822 return gfc_finish_block (&block);
823 }
824 else
825 return build2_v (MODIFY_EXPR, dest, src);
826 }
827
828 gfc_start_block (&block);
829
830 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
831 {
832 then_b = gfc_walk_alloc_comps (dest, NULL_TREE, OMP_CLAUSE_DECL (clause),
833 WALK_ALLOC_COMPS_DTOR);
834 tree tem = fold_convert (pvoid_type_node,
835 GFC_DESCRIPTOR_TYPE_P (type)
836 ? gfc_conv_descriptor_data_get (dest) : dest);
837 tem = unshare_expr (tem);
838 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
839 tem, null_pointer_node);
840 tem = build3_loc (input_location, COND_EXPR, void_type_node, cond,
841 then_b, build_empty_stmt (input_location));
842 gfc_add_expr_to_block (&block, tem);
843 }
844
845 gfc_init_block (&cond_block);
846
847 if (GFC_DESCRIPTOR_TYPE_P (type))
848 {
849 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
850 size = gfc_conv_descriptor_ubound_get (src, rank);
851 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
852 size,
853 gfc_conv_descriptor_lbound_get (src, rank));
854 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
855 size, gfc_index_one_node);
856 if (GFC_TYPE_ARRAY_RANK (type) > 1)
857 size = fold_build2_loc (input_location, MULT_EXPR,
858 gfc_array_index_type, size,
859 gfc_conv_descriptor_stride_get (src, rank));
860 tree esize = fold_convert (gfc_array_index_type,
861 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
862 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
863 size, esize);
864 size = unshare_expr (size);
865 size = gfc_evaluate_now (fold_convert (size_type_node, size),
866 &cond_block);
867 }
868 else
869 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
870 ptr = gfc_create_var (pvoid_type_node, NULL);
871
872 tree destptr = GFC_DESCRIPTOR_TYPE_P (type)
873 ? gfc_conv_descriptor_data_get (dest) : dest;
874 destptr = unshare_expr (destptr);
875 destptr = fold_convert (pvoid_type_node, destptr);
876 gfc_add_modify (&cond_block, ptr, destptr);
877
878 nonalloc = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
879 destptr, null_pointer_node);
880 cond = nonalloc;
881 if (GFC_DESCRIPTOR_TYPE_P (type))
882 {
883 int i;
884 for (i = 0; i < GFC_TYPE_ARRAY_RANK (type); i++)
885 {
886 tree rank = gfc_rank_cst[i];
887 tree tem = gfc_conv_descriptor_ubound_get (src, rank);
888 tem = fold_build2_loc (input_location, MINUS_EXPR,
889 gfc_array_index_type, tem,
890 gfc_conv_descriptor_lbound_get (src, rank));
891 tem = fold_build2_loc (input_location, PLUS_EXPR,
892 gfc_array_index_type, tem,
893 gfc_conv_descriptor_lbound_get (dest, rank));
894 tem = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
895 tem, gfc_conv_descriptor_ubound_get (dest,
896 rank));
897 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
898 logical_type_node, cond, tem);
899 }
900 }
901
902 gfc_init_block (&cond_block2);
903
904 if (GFC_DESCRIPTOR_TYPE_P (type))
905 {
906 gfc_init_block (&inner_block);
907 gfc_allocate_using_malloc (&inner_block, ptr, size, NULL_TREE);
908 then_b = gfc_finish_block (&inner_block);
909
910 gfc_init_block (&inner_block);
911 gfc_add_modify (&inner_block, ptr,
912 gfc_call_realloc (&inner_block, ptr, size));
913 else_b = gfc_finish_block (&inner_block);
914
915 gfc_add_expr_to_block (&cond_block2,
916 build3_loc (input_location, COND_EXPR,
917 void_type_node,
918 unshare_expr (nonalloc),
919 then_b, else_b));
920 gfc_add_modify (&cond_block2, dest, src);
921 gfc_conv_descriptor_data_set (&cond_block2, unshare_expr (dest), ptr);
922 }
923 else
924 {
925 gfc_allocate_using_malloc (&cond_block2, ptr, size, NULL_TREE);
926 gfc_add_modify (&cond_block2, unshare_expr (dest),
927 fold_convert (type, ptr));
928 }
929 then_b = gfc_finish_block (&cond_block2);
930 else_b = build_empty_stmt (input_location);
931
932 gfc_add_expr_to_block (&cond_block,
933 build3_loc (input_location, COND_EXPR,
934 void_type_node, unshare_expr (cond),
935 then_b, else_b));
936
937 tree srcptr = GFC_DESCRIPTOR_TYPE_P (type)
938 ? gfc_conv_descriptor_data_get (src) : src;
939 srcptr = unshare_expr (srcptr);
940 srcptr = fold_convert (pvoid_type_node, srcptr);
941 call = build_call_expr_loc (input_location,
942 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr,
943 srcptr, size);
944 gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
945 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
946 {
947 tree tem = gfc_walk_alloc_comps (src, dest,
948 OMP_CLAUSE_DECL (clause),
949 WALK_ALLOC_COMPS_COPY_CTOR);
950 gfc_add_expr_to_block (&cond_block, tem);
951 }
952 then_b = gfc_finish_block (&cond_block);
953
954 if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_COPYIN)
955 {
956 gfc_init_block (&cond_block);
957 if (GFC_DESCRIPTOR_TYPE_P (type))
958 {
959 tree tmp = gfc_conv_descriptor_data_get (unshare_expr (dest));
960 tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE,
961 NULL_TREE, NULL_TREE, true, NULL,
962 GFC_CAF_COARRAY_NOCOARRAY);
963 gfc_add_expr_to_block (&cond_block, tmp);
964 }
965 else
966 {
967 destptr = gfc_evaluate_now (destptr, &cond_block);
968 gfc_add_expr_to_block (&cond_block, gfc_call_free (destptr));
969 gfc_add_modify (&cond_block, unshare_expr (dest),
970 build_zero_cst (TREE_TYPE (dest)));
971 }
972 else_b = gfc_finish_block (&cond_block);
973
974 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
975 unshare_expr (srcptr), null_pointer_node);
976 gfc_add_expr_to_block (&block,
977 build3_loc (input_location, COND_EXPR,
978 void_type_node, cond,
979 then_b, else_b));
980 }
981 else
982 gfc_add_expr_to_block (&block, then_b);
983
984 return gfc_finish_block (&block);
985 }
986
987 static void
988 gfc_omp_linear_clause_add_loop (stmtblock_t *block, tree dest, tree src,
989 tree add, tree nelems)
990 {
991 stmtblock_t tmpblock;
992 tree desta, srca, index = gfc_create_var (gfc_array_index_type, "S");
993 nelems = gfc_evaluate_now (nelems, block);
994
995 gfc_init_block (&tmpblock);
996 if (TREE_CODE (TREE_TYPE (dest)) == ARRAY_TYPE)
997 {
998 desta = gfc_build_array_ref (dest, index, NULL);
999 srca = gfc_build_array_ref (src, index, NULL);
1000 }
1001 else
1002 {
1003 gcc_assert (POINTER_TYPE_P (TREE_TYPE (dest)));
1004 tree idx = fold_build2 (MULT_EXPR, sizetype,
1005 fold_convert (sizetype, index),
1006 TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (dest))));
1007 desta = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR,
1008 TREE_TYPE (dest), dest,
1009 idx));
1010 srca = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR,
1011 TREE_TYPE (src), src,
1012 idx));
1013 }
1014 gfc_add_modify (&tmpblock, desta,
1015 fold_build2 (PLUS_EXPR, TREE_TYPE (desta),
1016 srca, add));
1017
1018 gfc_loopinfo loop;
1019 gfc_init_loopinfo (&loop);
1020 loop.dimen = 1;
1021 loop.from[0] = gfc_index_zero_node;
1022 loop.loopvar[0] = index;
1023 loop.to[0] = nelems;
1024 gfc_trans_scalarizing_loops (&loop, &tmpblock);
1025 gfc_add_block_to_block (block, &loop.pre);
1026 }
1027
1028 /* Build and return code for a constructor of DEST that initializes
1029 it to SRC plus ADD (ADD is scalar integer). */
1030
1031 tree
1032 gfc_omp_clause_linear_ctor (tree clause, tree dest, tree src, tree add)
1033 {
1034 tree type = TREE_TYPE (dest), ptr, size, nelems = NULL_TREE;
1035 stmtblock_t block;
1036
1037 gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
1038
1039 gfc_start_block (&block);
1040 add = gfc_evaluate_now (add, &block);
1041
1042 if ((! GFC_DESCRIPTOR_TYPE_P (type)
1043 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
1044 && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
1045 || !POINTER_TYPE_P (type)))
1046 {
1047 bool compute_nelts = false;
1048 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1049 if (!TYPE_DOMAIN (type)
1050 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE
1051 || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node
1052 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node)
1053 compute_nelts = true;
1054 else if (VAR_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
1055 {
1056 tree a = DECL_ATTRIBUTES (TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
1057 if (lookup_attribute ("omp dummy var", a))
1058 compute_nelts = true;
1059 }
1060 if (compute_nelts)
1061 {
1062 nelems = fold_build2 (EXACT_DIV_EXPR, sizetype,
1063 TYPE_SIZE_UNIT (type),
1064 TYPE_SIZE_UNIT (TREE_TYPE (type)));
1065 nelems = size_binop (MINUS_EXPR, nelems, size_one_node);
1066 }
1067 else
1068 nelems = array_type_nelts (type);
1069 nelems = fold_convert (gfc_array_index_type, nelems);
1070
1071 gfc_omp_linear_clause_add_loop (&block, dest, src, add, nelems);
1072 return gfc_finish_block (&block);
1073 }
1074
1075 /* Allocatable arrays in LINEAR clauses need to be allocated
1076 and copied from SRC. */
1077 gfc_add_modify (&block, dest, src);
1078 if (GFC_DESCRIPTOR_TYPE_P (type))
1079 {
1080 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
1081 size = gfc_conv_descriptor_ubound_get (dest, rank);
1082 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
1083 size,
1084 gfc_conv_descriptor_lbound_get (dest, rank));
1085 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1086 size, gfc_index_one_node);
1087 if (GFC_TYPE_ARRAY_RANK (type) > 1)
1088 size = fold_build2_loc (input_location, MULT_EXPR,
1089 gfc_array_index_type, size,
1090 gfc_conv_descriptor_stride_get (dest, rank));
1091 tree esize = fold_convert (gfc_array_index_type,
1092 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
1093 nelems = gfc_evaluate_now (unshare_expr (size), &block);
1094 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1095 nelems, unshare_expr (esize));
1096 size = gfc_evaluate_now (fold_convert (size_type_node, size),
1097 &block);
1098 nelems = fold_build2_loc (input_location, MINUS_EXPR,
1099 gfc_array_index_type, nelems,
1100 gfc_index_one_node);
1101 }
1102 else
1103 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
1104 ptr = gfc_create_var (pvoid_type_node, NULL);
1105 gfc_allocate_using_malloc (&block, ptr, size, NULL_TREE);
1106 if (GFC_DESCRIPTOR_TYPE_P (type))
1107 {
1108 gfc_conv_descriptor_data_set (&block, unshare_expr (dest), ptr);
1109 tree etype = gfc_get_element_type (type);
1110 ptr = fold_convert (build_pointer_type (etype), ptr);
1111 tree srcptr = gfc_conv_descriptor_data_get (unshare_expr (src));
1112 srcptr = fold_convert (build_pointer_type (etype), srcptr);
1113 gfc_omp_linear_clause_add_loop (&block, ptr, srcptr, add, nelems);
1114 }
1115 else
1116 {
1117 gfc_add_modify (&block, unshare_expr (dest),
1118 fold_convert (TREE_TYPE (dest), ptr));
1119 ptr = fold_convert (TREE_TYPE (dest), ptr);
1120 tree dstm = build_fold_indirect_ref (ptr);
1121 tree srcm = build_fold_indirect_ref (unshare_expr (src));
1122 gfc_add_modify (&block, dstm,
1123 fold_build2 (PLUS_EXPR, TREE_TYPE (add), srcm, add));
1124 }
1125 return gfc_finish_block (&block);
1126 }
1127
1128 /* Build and return code destructing DECL. Return NULL if nothing
1129 to be done. */
1130
1131 tree
1132 gfc_omp_clause_dtor (tree clause, tree decl)
1133 {
1134 tree type = TREE_TYPE (decl), tem;
1135
1136 if ((! GFC_DESCRIPTOR_TYPE_P (type)
1137 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
1138 && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
1139 || !POINTER_TYPE_P (type)))
1140 {
1141 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
1142 return gfc_walk_alloc_comps (decl, NULL_TREE,
1143 OMP_CLAUSE_DECL (clause),
1144 WALK_ALLOC_COMPS_DTOR);
1145 return NULL_TREE;
1146 }
1147
1148 if (GFC_DESCRIPTOR_TYPE_P (type))
1149 {
1150 /* Allocatable arrays in FIRSTPRIVATE/LASTPRIVATE etc. clauses need
1151 to be deallocated if they were allocated. */
1152 tem = gfc_conv_descriptor_data_get (decl);
1153 tem = gfc_deallocate_with_status (tem, NULL_TREE, NULL_TREE, NULL_TREE,
1154 NULL_TREE, true, NULL,
1155 GFC_CAF_COARRAY_NOCOARRAY);
1156 }
1157 else
1158 tem = gfc_call_free (decl);
1159 tem = gfc_omp_unshare_expr (tem);
1160
1161 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
1162 {
1163 stmtblock_t block;
1164 tree then_b;
1165
1166 gfc_init_block (&block);
1167 gfc_add_expr_to_block (&block,
1168 gfc_walk_alloc_comps (decl, NULL_TREE,
1169 OMP_CLAUSE_DECL (clause),
1170 WALK_ALLOC_COMPS_DTOR));
1171 gfc_add_expr_to_block (&block, tem);
1172 then_b = gfc_finish_block (&block);
1173
1174 tem = fold_convert (pvoid_type_node,
1175 GFC_DESCRIPTOR_TYPE_P (type)
1176 ? gfc_conv_descriptor_data_get (decl) : decl);
1177 tem = unshare_expr (tem);
1178 tree cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1179 tem, null_pointer_node);
1180 tem = build3_loc (input_location, COND_EXPR, void_type_node, cond,
1181 then_b, build_empty_stmt (input_location));
1182 }
1183 return tem;
1184 }
1185
1186 /* Build a conditional expression in BLOCK. If COND_VAL is not
1187 null, then the block THEN_B is executed, otherwise ELSE_VAL
1188 is assigned to VAL. */
1189
1190 static void
1191 gfc_build_cond_assign (stmtblock_t *block, tree val, tree cond_val,
1192 tree then_b, tree else_val)
1193 {
1194 stmtblock_t cond_block;
1195 tree cond, else_b = NULL_TREE;
1196 tree val_ty = TREE_TYPE (val);
1197
1198 if (else_val)
1199 {
1200 gfc_init_block (&cond_block);
1201 gfc_add_modify (&cond_block, val, fold_convert (val_ty, else_val));
1202 else_b = gfc_finish_block (&cond_block);
1203 }
1204 cond = fold_build2_loc (input_location, NE_EXPR,
1205 logical_type_node,
1206 cond_val, null_pointer_node);
1207 gfc_add_expr_to_block (block,
1208 build3_loc (input_location,
1209 COND_EXPR,
1210 void_type_node,
1211 cond, then_b,
1212 else_b));
1213 }
1214
1215 /* Build a conditional expression in BLOCK, returning a temporary
1216 variable containing the result. If COND_VAL is not null, then
1217 THEN_VAL will be assigned to the variable, otherwise ELSE_VAL
1218 is assigned.
1219 */
1220
1221 static tree
1222 gfc_build_cond_assign_expr (stmtblock_t *block, tree cond_val,
1223 tree then_val, tree else_val)
1224 {
1225 tree val;
1226 tree val_ty = TREE_TYPE (then_val);
1227 stmtblock_t cond_block;
1228
1229 val = create_tmp_var (val_ty);
1230
1231 gfc_init_block (&cond_block);
1232 gfc_add_modify (&cond_block, val, then_val);
1233 tree then_b = gfc_finish_block (&cond_block);
1234
1235 gfc_build_cond_assign (block, val, cond_val, then_b, else_val);
1236
1237 return val;
1238 }
1239
1240 void
1241 gfc_omp_finish_clause (tree c, gimple_seq *pre_p)
1242 {
1243 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
1244 return;
1245
1246 tree decl = OMP_CLAUSE_DECL (c);
1247
1248 /* Assumed-size arrays can't be mapped implicitly, they have to be
1249 mapped explicitly using array sections. */
1250 if (TREE_CODE (decl) == PARM_DECL
1251 && GFC_ARRAY_TYPE_P (TREE_TYPE (decl))
1252 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN
1253 && GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (decl),
1254 GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)) - 1)
1255 == NULL)
1256 {
1257 error_at (OMP_CLAUSE_LOCATION (c),
1258 "implicit mapping of assumed size array %qD", decl);
1259 return;
1260 }
1261
1262 tree c2 = NULL_TREE, c3 = NULL_TREE, c4 = NULL_TREE;
1263 tree present = (gfc_omp_is_optional_argument (decl)
1264 ? gfc_omp_check_optional_argument (decl, true) : NULL_TREE);
1265 if (POINTER_TYPE_P (TREE_TYPE (decl)))
1266 {
1267 if (!gfc_omp_privatize_by_reference (decl)
1268 && !GFC_DECL_GET_SCALAR_POINTER (decl)
1269 && !GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
1270 && !GFC_DECL_CRAY_POINTEE (decl)
1271 && !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
1272 return;
1273 tree orig_decl = decl;
1274 c4 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
1275 OMP_CLAUSE_SET_MAP_KIND (c4, GOMP_MAP_POINTER);
1276 OMP_CLAUSE_DECL (c4) = decl;
1277 OMP_CLAUSE_SIZE (c4) = size_int (0);
1278 decl = build_fold_indirect_ref (decl);
1279 if (present
1280 && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
1281 || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
1282 {
1283 c2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
1284 OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER);
1285 OMP_CLAUSE_DECL (c2) = decl;
1286 OMP_CLAUSE_SIZE (c2) = size_int (0);
1287
1288 stmtblock_t block;
1289 gfc_start_block (&block);
1290 tree ptr = decl;
1291 ptr = gfc_build_cond_assign_expr (&block, present, decl,
1292 null_pointer_node);
1293 gimplify_and_add (gfc_finish_block (&block), pre_p);
1294 ptr = build_fold_indirect_ref (ptr);
1295 OMP_CLAUSE_DECL (c) = ptr;
1296 OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
1297 }
1298 else
1299 {
1300 OMP_CLAUSE_DECL (c) = decl;
1301 OMP_CLAUSE_SIZE (c) = NULL_TREE;
1302 }
1303 if (TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE
1304 && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
1305 || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
1306 {
1307 c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
1308 OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_POINTER);
1309 OMP_CLAUSE_DECL (c3) = unshare_expr (decl);
1310 OMP_CLAUSE_SIZE (c3) = size_int (0);
1311 decl = build_fold_indirect_ref (decl);
1312 OMP_CLAUSE_DECL (c) = decl;
1313 }
1314 }
1315 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
1316 {
1317 stmtblock_t block;
1318 gfc_start_block (&block);
1319 tree type = TREE_TYPE (decl);
1320 tree ptr = gfc_conv_descriptor_data_get (decl);
1321
1322 if (present)
1323 ptr = gfc_build_cond_assign_expr (&block, present, ptr,
1324 null_pointer_node);
1325 ptr = fold_convert (build_pointer_type (char_type_node), ptr);
1326 ptr = build_fold_indirect_ref (ptr);
1327 OMP_CLAUSE_DECL (c) = ptr;
1328 c2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
1329 OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_TO_PSET);
1330 if (present)
1331 {
1332 ptr = create_tmp_var (TREE_TYPE (TREE_OPERAND (decl, 0)));
1333 gfc_add_modify (&block, ptr, TREE_OPERAND (decl, 0));
1334
1335 OMP_CLAUSE_DECL (c2) = build_fold_indirect_ref (ptr);
1336 }
1337 else
1338 OMP_CLAUSE_DECL (c2) = decl;
1339 OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (type);
1340 c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
1341 OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_POINTER);
1342 if (present)
1343 {
1344 ptr = gfc_conv_descriptor_data_get (decl);
1345 ptr = gfc_build_addr_expr (NULL, ptr);
1346 ptr = gfc_build_cond_assign_expr (&block, present,
1347 ptr, null_pointer_node);
1348 ptr = build_fold_indirect_ref (ptr);
1349 OMP_CLAUSE_DECL (c3) = ptr;
1350 }
1351 else
1352 OMP_CLAUSE_DECL (c3) = gfc_conv_descriptor_data_get (decl);
1353 OMP_CLAUSE_SIZE (c3) = size_int (0);
1354 tree size = create_tmp_var (gfc_array_index_type);
1355 tree elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
1356 elemsz = fold_convert (gfc_array_index_type, elemsz);
1357 if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER
1358 || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT)
1359 {
1360 stmtblock_t cond_block;
1361 tree tem, then_b, else_b, zero, cond;
1362
1363 gfc_init_block (&cond_block);
1364 tem = gfc_full_array_size (&cond_block, decl,
1365 GFC_TYPE_ARRAY_RANK (type));
1366 gfc_add_modify (&cond_block, size, tem);
1367 gfc_add_modify (&cond_block, size,
1368 fold_build2 (MULT_EXPR, gfc_array_index_type,
1369 size, elemsz));
1370 then_b = gfc_finish_block (&cond_block);
1371 gfc_init_block (&cond_block);
1372 zero = build_int_cst (gfc_array_index_type, 0);
1373 gfc_add_modify (&cond_block, size, zero);
1374 else_b = gfc_finish_block (&cond_block);
1375 tem = gfc_conv_descriptor_data_get (decl);
1376 tem = fold_convert (pvoid_type_node, tem);
1377 cond = fold_build2_loc (input_location, NE_EXPR,
1378 boolean_type_node, tem, null_pointer_node);
1379 if (present)
1380 {
1381 tem = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1382 present, null_pointer_node);
1383 cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
1384 boolean_type_node, tem, cond);
1385 }
1386 gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR,
1387 void_type_node, cond,
1388 then_b, else_b));
1389 }
1390 else if (present)
1391 {
1392 stmtblock_t cond_block;
1393 tree then_b;
1394
1395 gfc_init_block (&cond_block);
1396 gfc_add_modify (&cond_block, size,
1397 gfc_full_array_size (&cond_block, decl,
1398 GFC_TYPE_ARRAY_RANK (type)));
1399 gfc_add_modify (&cond_block, size,
1400 fold_build2 (MULT_EXPR, gfc_array_index_type,
1401 size, elemsz));
1402 then_b = gfc_finish_block (&cond_block);
1403
1404 gfc_build_cond_assign (&block, size, present, then_b,
1405 build_int_cst (gfc_array_index_type, 0));
1406 }
1407 else
1408 {
1409 gfc_add_modify (&block, size,
1410 gfc_full_array_size (&block, decl,
1411 GFC_TYPE_ARRAY_RANK (type)));
1412 gfc_add_modify (&block, size,
1413 fold_build2 (MULT_EXPR, gfc_array_index_type,
1414 size, elemsz));
1415 }
1416 OMP_CLAUSE_SIZE (c) = size;
1417 tree stmt = gfc_finish_block (&block);
1418 gimplify_and_add (stmt, pre_p);
1419 }
1420 tree last = c;
1421 if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
1422 OMP_CLAUSE_SIZE (c)
1423 = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
1424 : TYPE_SIZE_UNIT (TREE_TYPE (decl));
1425 if (c2)
1426 {
1427 OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (last);
1428 OMP_CLAUSE_CHAIN (last) = c2;
1429 last = c2;
1430 }
1431 if (c3)
1432 {
1433 OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (last);
1434 OMP_CLAUSE_CHAIN (last) = c3;
1435 last = c3;
1436 }
1437 if (c4)
1438 {
1439 OMP_CLAUSE_CHAIN (c4) = OMP_CLAUSE_CHAIN (last);
1440 OMP_CLAUSE_CHAIN (last) = c4;
1441 }
1442 }
1443
1444
1445 /* Return true if DECL is a scalar variable (for the purpose of
1446 implicit firstprivatization). */
1447
1448 bool
1449 gfc_omp_scalar_p (tree decl)
1450 {
1451 tree type = TREE_TYPE (decl);
1452 if (TREE_CODE (type) == REFERENCE_TYPE)
1453 type = TREE_TYPE (type);
1454 if (TREE_CODE (type) == POINTER_TYPE)
1455 {
1456 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
1457 || GFC_DECL_GET_SCALAR_POINTER (decl))
1458 type = TREE_TYPE (type);
1459 if (GFC_ARRAY_TYPE_P (type)
1460 || GFC_CLASS_TYPE_P (type))
1461 return false;
1462 }
1463 if ((TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == INTEGER_TYPE)
1464 && TYPE_STRING_FLAG (type))
1465 return false;
1466 if (INTEGRAL_TYPE_P (type)
1467 || SCALAR_FLOAT_TYPE_P (type)
1468 || COMPLEX_FLOAT_TYPE_P (type))
1469 return true;
1470 return false;
1471 }
1472
1473
1474 /* Return true if DECL's DECL_VALUE_EXPR (if any) should be
1475 disregarded in OpenMP construct, because it is going to be
1476 remapped during OpenMP lowering. SHARED is true if DECL
1477 is going to be shared, false if it is going to be privatized. */
1478
1479 bool
1480 gfc_omp_disregard_value_expr (tree decl, bool shared)
1481 {
1482 if (GFC_DECL_COMMON_OR_EQUIV (decl)
1483 && DECL_HAS_VALUE_EXPR_P (decl))
1484 {
1485 tree value = DECL_VALUE_EXPR (decl);
1486
1487 if (TREE_CODE (value) == COMPONENT_REF
1488 && VAR_P (TREE_OPERAND (value, 0))
1489 && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
1490 {
1491 /* If variable in COMMON or EQUIVALENCE is privatized, return
1492 true, as just that variable is supposed to be privatized,
1493 not the whole COMMON or whole EQUIVALENCE.
1494 For shared variables in COMMON or EQUIVALENCE, let them be
1495 gimplified to DECL_VALUE_EXPR, so that for multiple shared vars
1496 from the same COMMON or EQUIVALENCE just one sharing of the
1497 whole COMMON or EQUIVALENCE is enough. */
1498 return ! shared;
1499 }
1500 }
1501
1502 if (GFC_DECL_RESULT (decl) && DECL_HAS_VALUE_EXPR_P (decl))
1503 return ! shared;
1504
1505 return false;
1506 }
1507
1508 /* Return true if DECL that is shared iff SHARED is true should
1509 be put into OMP_CLAUSE_PRIVATE with OMP_CLAUSE_PRIVATE_DEBUG
1510 flag set. */
1511
1512 bool
1513 gfc_omp_private_debug_clause (tree decl, bool shared)
1514 {
1515 if (GFC_DECL_CRAY_POINTEE (decl))
1516 return true;
1517
1518 if (GFC_DECL_COMMON_OR_EQUIV (decl)
1519 && DECL_HAS_VALUE_EXPR_P (decl))
1520 {
1521 tree value = DECL_VALUE_EXPR (decl);
1522
1523 if (TREE_CODE (value) == COMPONENT_REF
1524 && VAR_P (TREE_OPERAND (value, 0))
1525 && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
1526 return shared;
1527 }
1528
1529 return false;
1530 }
1531
1532 /* Register language specific type size variables as potentially OpenMP
1533 firstprivate variables. */
1534
1535 void
1536 gfc_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
1537 {
1538 if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
1539 {
1540 int r;
1541
1542 gcc_assert (TYPE_LANG_SPECIFIC (type) != NULL);
1543 for (r = 0; r < GFC_TYPE_ARRAY_RANK (type); r++)
1544 {
1545 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_LBOUND (type, r));
1546 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_UBOUND (type, r));
1547 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_STRIDE (type, r));
1548 }
1549 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_SIZE (type));
1550 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_OFFSET (type));
1551 }
1552 }
1553
1554
1555 static inline tree
1556 gfc_trans_add_clause (tree node, tree tail)
1557 {
1558 OMP_CLAUSE_CHAIN (node) = tail;
1559 return node;
1560 }
1561
1562 static tree
1563 gfc_trans_omp_variable (gfc_symbol *sym, bool declare_simd)
1564 {
1565 if (declare_simd)
1566 {
1567 int cnt = 0;
1568 gfc_symbol *proc_sym;
1569 gfc_formal_arglist *f;
1570
1571 gcc_assert (sym->attr.dummy);
1572 proc_sym = sym->ns->proc_name;
1573 if (proc_sym->attr.entry_master)
1574 ++cnt;
1575 if (gfc_return_by_reference (proc_sym))
1576 {
1577 ++cnt;
1578 if (proc_sym->ts.type == BT_CHARACTER)
1579 ++cnt;
1580 }
1581 for (f = gfc_sym_get_dummy_args (proc_sym); f; f = f->next)
1582 if (f->sym == sym)
1583 break;
1584 else if (f->sym)
1585 ++cnt;
1586 gcc_assert (f);
1587 return build_int_cst (integer_type_node, cnt);
1588 }
1589
1590 tree t = gfc_get_symbol_decl (sym);
1591 tree parent_decl;
1592 int parent_flag;
1593 bool return_value;
1594 bool alternate_entry;
1595 bool entry_master;
1596
1597 return_value = sym->attr.function && sym->result == sym;
1598 alternate_entry = sym->attr.function && sym->attr.entry
1599 && sym->result == sym;
1600 entry_master = sym->attr.result
1601 && sym->ns->proc_name->attr.entry_master
1602 && !gfc_return_by_reference (sym->ns->proc_name);
1603 parent_decl = current_function_decl
1604 ? DECL_CONTEXT (current_function_decl) : NULL_TREE;
1605
1606 if ((t == parent_decl && return_value)
1607 || (sym->ns && sym->ns->proc_name
1608 && sym->ns->proc_name->backend_decl == parent_decl
1609 && (alternate_entry || entry_master)))
1610 parent_flag = 1;
1611 else
1612 parent_flag = 0;
1613
1614 /* Special case for assigning the return value of a function.
1615 Self recursive functions must have an explicit return value. */
1616 if (return_value && (t == current_function_decl || parent_flag))
1617 t = gfc_get_fake_result_decl (sym, parent_flag);
1618
1619 /* Similarly for alternate entry points. */
1620 else if (alternate_entry
1621 && (sym->ns->proc_name->backend_decl == current_function_decl
1622 || parent_flag))
1623 {
1624 gfc_entry_list *el = NULL;
1625
1626 for (el = sym->ns->entries; el; el = el->next)
1627 if (sym == el->sym)
1628 {
1629 t = gfc_get_fake_result_decl (sym, parent_flag);
1630 break;
1631 }
1632 }
1633
1634 else if (entry_master
1635 && (sym->ns->proc_name->backend_decl == current_function_decl
1636 || parent_flag))
1637 t = gfc_get_fake_result_decl (sym, parent_flag);
1638
1639 return t;
1640 }
1641
1642 static tree
1643 gfc_trans_omp_variable_list (enum omp_clause_code code,
1644 gfc_omp_namelist *namelist, tree list,
1645 bool declare_simd)
1646 {
1647 for (; namelist != NULL; namelist = namelist->next)
1648 if (namelist->sym->attr.referenced || declare_simd)
1649 {
1650 tree t = gfc_trans_omp_variable (namelist->sym, declare_simd);
1651 if (t != error_mark_node)
1652 {
1653 tree node = build_omp_clause (input_location, code);
1654 OMP_CLAUSE_DECL (node) = t;
1655 list = gfc_trans_add_clause (node, list);
1656 }
1657 }
1658 return list;
1659 }
1660
1661 struct omp_udr_find_orig_data
1662 {
1663 gfc_omp_udr *omp_udr;
1664 bool omp_orig_seen;
1665 };
1666
1667 static int
1668 omp_udr_find_orig (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
1669 void *data)
1670 {
1671 struct omp_udr_find_orig_data *cd = (struct omp_udr_find_orig_data *) data;
1672 if ((*e)->expr_type == EXPR_VARIABLE
1673 && (*e)->symtree->n.sym == cd->omp_udr->omp_orig)
1674 cd->omp_orig_seen = true;
1675
1676 return 0;
1677 }
1678
1679 static void
1680 gfc_trans_omp_array_reduction_or_udr (tree c, gfc_omp_namelist *n, locus where)
1681 {
1682 gfc_symbol *sym = n->sym;
1683 gfc_symtree *root1 = NULL, *root2 = NULL, *root3 = NULL, *root4 = NULL;
1684 gfc_symtree *symtree1, *symtree2, *symtree3, *symtree4 = NULL;
1685 gfc_symbol init_val_sym, outer_sym, intrinsic_sym;
1686 gfc_symbol omp_var_copy[4];
1687 gfc_expr *e1, *e2, *e3, *e4;
1688 gfc_ref *ref;
1689 tree decl, backend_decl, stmt, type, outer_decl;
1690 locus old_loc = gfc_current_locus;
1691 const char *iname;
1692 bool t;
1693 gfc_omp_udr *udr = n->udr ? n->udr->udr : NULL;
1694
1695 decl = OMP_CLAUSE_DECL (c);
1696 gfc_current_locus = where;
1697 type = TREE_TYPE (decl);
1698 outer_decl = create_tmp_var_raw (type);
1699 if (TREE_CODE (decl) == PARM_DECL
1700 && TREE_CODE (type) == REFERENCE_TYPE
1701 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type))
1702 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (type)) == GFC_ARRAY_ALLOCATABLE)
1703 {
1704 decl = build_fold_indirect_ref (decl);
1705 type = TREE_TYPE (type);
1706 }
1707
1708 /* Create a fake symbol for init value. */
1709 memset (&init_val_sym, 0, sizeof (init_val_sym));
1710 init_val_sym.ns = sym->ns;
1711 init_val_sym.name = sym->name;
1712 init_val_sym.ts = sym->ts;
1713 init_val_sym.attr.referenced = 1;
1714 init_val_sym.declared_at = where;
1715 init_val_sym.attr.flavor = FL_VARIABLE;
1716 if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK)
1717 backend_decl = omp_reduction_init (c, gfc_sym_type (&init_val_sym));
1718 else if (udr->initializer_ns)
1719 backend_decl = NULL;
1720 else
1721 switch (sym->ts.type)
1722 {
1723 case BT_LOGICAL:
1724 case BT_INTEGER:
1725 case BT_REAL:
1726 case BT_COMPLEX:
1727 backend_decl = build_zero_cst (gfc_sym_type (&init_val_sym));
1728 break;
1729 default:
1730 backend_decl = NULL_TREE;
1731 break;
1732 }
1733 init_val_sym.backend_decl = backend_decl;
1734
1735 /* Create a fake symbol for the outer array reference. */
1736 outer_sym = *sym;
1737 if (sym->as)
1738 outer_sym.as = gfc_copy_array_spec (sym->as);
1739 outer_sym.attr.dummy = 0;
1740 outer_sym.attr.result = 0;
1741 outer_sym.attr.flavor = FL_VARIABLE;
1742 outer_sym.backend_decl = outer_decl;
1743 if (decl != OMP_CLAUSE_DECL (c))
1744 outer_sym.backend_decl = build_fold_indirect_ref (outer_decl);
1745
1746 /* Create fake symtrees for it. */
1747 symtree1 = gfc_new_symtree (&root1, sym->name);
1748 symtree1->n.sym = sym;
1749 gcc_assert (symtree1 == root1);
1750
1751 symtree2 = gfc_new_symtree (&root2, sym->name);
1752 symtree2->n.sym = &init_val_sym;
1753 gcc_assert (symtree2 == root2);
1754
1755 symtree3 = gfc_new_symtree (&root3, sym->name);
1756 symtree3->n.sym = &outer_sym;
1757 gcc_assert (symtree3 == root3);
1758
1759 memset (omp_var_copy, 0, sizeof omp_var_copy);
1760 if (udr)
1761 {
1762 omp_var_copy[0] = *udr->omp_out;
1763 omp_var_copy[1] = *udr->omp_in;
1764 *udr->omp_out = outer_sym;
1765 *udr->omp_in = *sym;
1766 if (udr->initializer_ns)
1767 {
1768 omp_var_copy[2] = *udr->omp_priv;
1769 omp_var_copy[3] = *udr->omp_orig;
1770 *udr->omp_priv = *sym;
1771 *udr->omp_orig = outer_sym;
1772 }
1773 }
1774
1775 /* Create expressions. */
1776 e1 = gfc_get_expr ();
1777 e1->expr_type = EXPR_VARIABLE;
1778 e1->where = where;
1779 e1->symtree = symtree1;
1780 e1->ts = sym->ts;
1781 if (sym->attr.dimension)
1782 {
1783 e1->ref = ref = gfc_get_ref ();
1784 ref->type = REF_ARRAY;
1785 ref->u.ar.where = where;
1786 ref->u.ar.as = sym->as;
1787 ref->u.ar.type = AR_FULL;
1788 ref->u.ar.dimen = 0;
1789 }
1790 t = gfc_resolve_expr (e1);
1791 gcc_assert (t);
1792
1793 e2 = NULL;
1794 if (backend_decl != NULL_TREE)
1795 {
1796 e2 = gfc_get_expr ();
1797 e2->expr_type = EXPR_VARIABLE;
1798 e2->where = where;
1799 e2->symtree = symtree2;
1800 e2->ts = sym->ts;
1801 t = gfc_resolve_expr (e2);
1802 gcc_assert (t);
1803 }
1804 else if (udr->initializer_ns == NULL)
1805 {
1806 gcc_assert (sym->ts.type == BT_DERIVED);
1807 e2 = gfc_default_initializer (&sym->ts);
1808 gcc_assert (e2);
1809 t = gfc_resolve_expr (e2);
1810 gcc_assert (t);
1811 }
1812 else if (n->udr->initializer->op == EXEC_ASSIGN)
1813 {
1814 e2 = gfc_copy_expr (n->udr->initializer->expr2);
1815 t = gfc_resolve_expr (e2);
1816 gcc_assert (t);
1817 }
1818 if (udr && udr->initializer_ns)
1819 {
1820 struct omp_udr_find_orig_data cd;
1821 cd.omp_udr = udr;
1822 cd.omp_orig_seen = false;
1823 gfc_code_walker (&n->udr->initializer,
1824 gfc_dummy_code_callback, omp_udr_find_orig, &cd);
1825 if (cd.omp_orig_seen)
1826 OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c) = 1;
1827 }
1828
1829 e3 = gfc_copy_expr (e1);
1830 e3->symtree = symtree3;
1831 t = gfc_resolve_expr (e3);
1832 gcc_assert (t);
1833
1834 iname = NULL;
1835 e4 = NULL;
1836 switch (OMP_CLAUSE_REDUCTION_CODE (c))
1837 {
1838 case PLUS_EXPR:
1839 case MINUS_EXPR:
1840 e4 = gfc_add (e3, e1);
1841 break;
1842 case MULT_EXPR:
1843 e4 = gfc_multiply (e3, e1);
1844 break;
1845 case TRUTH_ANDIF_EXPR:
1846 e4 = gfc_and (e3, e1);
1847 break;
1848 case TRUTH_ORIF_EXPR:
1849 e4 = gfc_or (e3, e1);
1850 break;
1851 case EQ_EXPR:
1852 e4 = gfc_eqv (e3, e1);
1853 break;
1854 case NE_EXPR:
1855 e4 = gfc_neqv (e3, e1);
1856 break;
1857 case MIN_EXPR:
1858 iname = "min";
1859 break;
1860 case MAX_EXPR:
1861 iname = "max";
1862 break;
1863 case BIT_AND_EXPR:
1864 iname = "iand";
1865 break;
1866 case BIT_IOR_EXPR:
1867 iname = "ior";
1868 break;
1869 case BIT_XOR_EXPR:
1870 iname = "ieor";
1871 break;
1872 case ERROR_MARK:
1873 if (n->udr->combiner->op == EXEC_ASSIGN)
1874 {
1875 gfc_free_expr (e3);
1876 e3 = gfc_copy_expr (n->udr->combiner->expr1);
1877 e4 = gfc_copy_expr (n->udr->combiner->expr2);
1878 t = gfc_resolve_expr (e3);
1879 gcc_assert (t);
1880 t = gfc_resolve_expr (e4);
1881 gcc_assert (t);
1882 }
1883 break;
1884 default:
1885 gcc_unreachable ();
1886 }
1887 if (iname != NULL)
1888 {
1889 memset (&intrinsic_sym, 0, sizeof (intrinsic_sym));
1890 intrinsic_sym.ns = sym->ns;
1891 intrinsic_sym.name = iname;
1892 intrinsic_sym.ts = sym->ts;
1893 intrinsic_sym.attr.referenced = 1;
1894 intrinsic_sym.attr.intrinsic = 1;
1895 intrinsic_sym.attr.function = 1;
1896 intrinsic_sym.attr.implicit_type = 1;
1897 intrinsic_sym.result = &intrinsic_sym;
1898 intrinsic_sym.declared_at = where;
1899
1900 symtree4 = gfc_new_symtree (&root4, iname);
1901 symtree4->n.sym = &intrinsic_sym;
1902 gcc_assert (symtree4 == root4);
1903
1904 e4 = gfc_get_expr ();
1905 e4->expr_type = EXPR_FUNCTION;
1906 e4->where = where;
1907 e4->symtree = symtree4;
1908 e4->value.function.actual = gfc_get_actual_arglist ();
1909 e4->value.function.actual->expr = e3;
1910 e4->value.function.actual->next = gfc_get_actual_arglist ();
1911 e4->value.function.actual->next->expr = e1;
1912 }
1913 if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK)
1914 {
1915 /* e1 and e3 have been stored as arguments of e4, avoid sharing. */
1916 e1 = gfc_copy_expr (e1);
1917 e3 = gfc_copy_expr (e3);
1918 t = gfc_resolve_expr (e4);
1919 gcc_assert (t);
1920 }
1921
1922 /* Create the init statement list. */
1923 pushlevel ();
1924 if (e2)
1925 stmt = gfc_trans_assignment (e1, e2, false, false);
1926 else
1927 stmt = gfc_trans_call (n->udr->initializer, false,
1928 NULL_TREE, NULL_TREE, false);
1929 if (TREE_CODE (stmt) != BIND_EXPR)
1930 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
1931 else
1932 poplevel (0, 0);
1933 OMP_CLAUSE_REDUCTION_INIT (c) = stmt;
1934
1935 /* Create the merge statement list. */
1936 pushlevel ();
1937 if (e4)
1938 stmt = gfc_trans_assignment (e3, e4, false, true);
1939 else
1940 stmt = gfc_trans_call (n->udr->combiner, false,
1941 NULL_TREE, NULL_TREE, false);
1942 if (TREE_CODE (stmt) != BIND_EXPR)
1943 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
1944 else
1945 poplevel (0, 0);
1946 OMP_CLAUSE_REDUCTION_MERGE (c) = stmt;
1947
1948 /* And stick the placeholder VAR_DECL into the clause as well. */
1949 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = outer_decl;
1950
1951 gfc_current_locus = old_loc;
1952
1953 gfc_free_expr (e1);
1954 if (e2)
1955 gfc_free_expr (e2);
1956 gfc_free_expr (e3);
1957 if (e4)
1958 gfc_free_expr (e4);
1959 free (symtree1);
1960 free (symtree2);
1961 free (symtree3);
1962 free (symtree4);
1963 if (outer_sym.as)
1964 gfc_free_array_spec (outer_sym.as);
1965
1966 if (udr)
1967 {
1968 *udr->omp_out = omp_var_copy[0];
1969 *udr->omp_in = omp_var_copy[1];
1970 if (udr->initializer_ns)
1971 {
1972 *udr->omp_priv = omp_var_copy[2];
1973 *udr->omp_orig = omp_var_copy[3];
1974 }
1975 }
1976 }
1977
1978 static tree
1979 gfc_trans_omp_reduction_list (gfc_omp_namelist *namelist, tree list,
1980 locus where, bool mark_addressable)
1981 {
1982 for (; namelist != NULL; namelist = namelist->next)
1983 if (namelist->sym->attr.referenced)
1984 {
1985 tree t = gfc_trans_omp_variable (namelist->sym, false);
1986 if (t != error_mark_node)
1987 {
1988 tree node = build_omp_clause (gfc_get_location (&namelist->where),
1989 OMP_CLAUSE_REDUCTION);
1990 OMP_CLAUSE_DECL (node) = t;
1991 if (mark_addressable)
1992 TREE_ADDRESSABLE (t) = 1;
1993 switch (namelist->u.reduction_op)
1994 {
1995 case OMP_REDUCTION_PLUS:
1996 OMP_CLAUSE_REDUCTION_CODE (node) = PLUS_EXPR;
1997 break;
1998 case OMP_REDUCTION_MINUS:
1999 OMP_CLAUSE_REDUCTION_CODE (node) = MINUS_EXPR;
2000 break;
2001 case OMP_REDUCTION_TIMES:
2002 OMP_CLAUSE_REDUCTION_CODE (node) = MULT_EXPR;
2003 break;
2004 case OMP_REDUCTION_AND:
2005 OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ANDIF_EXPR;
2006 break;
2007 case OMP_REDUCTION_OR:
2008 OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ORIF_EXPR;
2009 break;
2010 case OMP_REDUCTION_EQV:
2011 OMP_CLAUSE_REDUCTION_CODE (node) = EQ_EXPR;
2012 break;
2013 case OMP_REDUCTION_NEQV:
2014 OMP_CLAUSE_REDUCTION_CODE (node) = NE_EXPR;
2015 break;
2016 case OMP_REDUCTION_MAX:
2017 OMP_CLAUSE_REDUCTION_CODE (node) = MAX_EXPR;
2018 break;
2019 case OMP_REDUCTION_MIN:
2020 OMP_CLAUSE_REDUCTION_CODE (node) = MIN_EXPR;
2021 break;
2022 case OMP_REDUCTION_IAND:
2023 OMP_CLAUSE_REDUCTION_CODE (node) = BIT_AND_EXPR;
2024 break;
2025 case OMP_REDUCTION_IOR:
2026 OMP_CLAUSE_REDUCTION_CODE (node) = BIT_IOR_EXPR;
2027 break;
2028 case OMP_REDUCTION_IEOR:
2029 OMP_CLAUSE_REDUCTION_CODE (node) = BIT_XOR_EXPR;
2030 break;
2031 case OMP_REDUCTION_USER:
2032 OMP_CLAUSE_REDUCTION_CODE (node) = ERROR_MARK;
2033 break;
2034 default:
2035 gcc_unreachable ();
2036 }
2037 if (namelist->sym->attr.dimension
2038 || namelist->u.reduction_op == OMP_REDUCTION_USER
2039 || namelist->sym->attr.allocatable)
2040 gfc_trans_omp_array_reduction_or_udr (node, namelist, where);
2041 list = gfc_trans_add_clause (node, list);
2042 }
2043 }
2044 return list;
2045 }
2046
2047 static inline tree
2048 gfc_convert_expr_to_tree (stmtblock_t *block, gfc_expr *expr)
2049 {
2050 gfc_se se;
2051 tree result;
2052
2053 gfc_init_se (&se, NULL );
2054 gfc_conv_expr (&se, expr);
2055 gfc_add_block_to_block (block, &se.pre);
2056 result = gfc_evaluate_now (se.expr, block);
2057 gfc_add_block_to_block (block, &se.post);
2058
2059 return result;
2060 }
2061
2062 static vec<tree, va_heap, vl_embed> *doacross_steps;
2063
2064
2065 /* Translate an array section or array element. */
2066
2067 static void
2068 gfc_trans_omp_array_section (stmtblock_t *block, gfc_omp_namelist *n,
2069 tree decl, bool element, gomp_map_kind ptr_kind,
2070 tree node, tree &node2, tree &node3, tree &node4)
2071 {
2072 gfc_se se;
2073 tree ptr, ptr2;
2074
2075 gfc_init_se (&se, NULL);
2076
2077 if (element)
2078 {
2079 gfc_conv_expr_reference (&se, n->expr);
2080 gfc_add_block_to_block (block, &se.pre);
2081 ptr = se.expr;
2082 OMP_CLAUSE_SIZE (node) = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
2083 }
2084 else
2085 {
2086 gfc_conv_expr_descriptor (&se, n->expr);
2087 ptr = gfc_conv_array_data (se.expr);
2088 tree type = TREE_TYPE (se.expr);
2089 gfc_add_block_to_block (block, &se.pre);
2090 OMP_CLAUSE_SIZE (node) = gfc_full_array_size (block, se.expr,
2091 GFC_TYPE_ARRAY_RANK (type));
2092 tree elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
2093 elemsz = fold_convert (gfc_array_index_type, elemsz);
2094 OMP_CLAUSE_SIZE (node) = fold_build2 (MULT_EXPR, gfc_array_index_type,
2095 OMP_CLAUSE_SIZE (node), elemsz);
2096 }
2097 gfc_add_block_to_block (block, &se.post);
2098 ptr = fold_convert (build_pointer_type (char_type_node), ptr);
2099 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
2100
2101 if (POINTER_TYPE_P (TREE_TYPE (decl))
2102 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
2103 && ptr_kind == GOMP_MAP_POINTER)
2104 {
2105 node4 = build_omp_clause (input_location,
2106 OMP_CLAUSE_MAP);
2107 OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER);
2108 OMP_CLAUSE_DECL (node4) = decl;
2109 OMP_CLAUSE_SIZE (node4) = size_int (0);
2110 decl = build_fold_indirect_ref (decl);
2111 }
2112 ptr = fold_convert (sizetype, ptr);
2113 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
2114 {
2115 tree type = TREE_TYPE (decl);
2116 ptr2 = gfc_conv_descriptor_data_get (decl);
2117 node2 = build_omp_clause (input_location,
2118 OMP_CLAUSE_MAP);
2119 OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
2120 OMP_CLAUSE_DECL (node2) = decl;
2121 OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
2122 node3 = build_omp_clause (input_location,
2123 OMP_CLAUSE_MAP);
2124 OMP_CLAUSE_SET_MAP_KIND (node3, ptr_kind);
2125 OMP_CLAUSE_DECL (node3)
2126 = gfc_conv_descriptor_data_get (decl);
2127 if (ptr_kind == GOMP_MAP_ATTACH_DETACH)
2128 STRIP_NOPS (OMP_CLAUSE_DECL (node3));
2129 }
2130 else
2131 {
2132 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2133 ptr2 = build_fold_addr_expr (decl);
2134 else
2135 {
2136 gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl)));
2137 ptr2 = decl;
2138 }
2139 node3 = build_omp_clause (input_location,
2140 OMP_CLAUSE_MAP);
2141 OMP_CLAUSE_SET_MAP_KIND (node3, ptr_kind);
2142 OMP_CLAUSE_DECL (node3) = decl;
2143 }
2144 ptr2 = fold_convert (sizetype, ptr2);
2145 OMP_CLAUSE_SIZE (node3)
2146 = fold_build2 (MINUS_EXPR, sizetype, ptr, ptr2);
2147 }
2148
2149 static tree
2150 gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
2151 locus where, bool declare_simd = false)
2152 {
2153 tree omp_clauses = NULL_TREE, chunk_size, c;
2154 int list, ifc;
2155 enum omp_clause_code clause_code;
2156 gfc_se se;
2157
2158 if (clauses == NULL)
2159 return NULL_TREE;
2160
2161 for (list = 0; list < OMP_LIST_NUM; list++)
2162 {
2163 gfc_omp_namelist *n = clauses->lists[list];
2164
2165 if (n == NULL)
2166 continue;
2167 switch (list)
2168 {
2169 case OMP_LIST_REDUCTION:
2170 /* An OpenACC async clause indicates the need to set reduction
2171 arguments addressable, to allow asynchronous copy-out. */
2172 omp_clauses = gfc_trans_omp_reduction_list (n, omp_clauses, where,
2173 clauses->async);
2174 break;
2175 case OMP_LIST_PRIVATE:
2176 clause_code = OMP_CLAUSE_PRIVATE;
2177 goto add_clause;
2178 case OMP_LIST_SHARED:
2179 clause_code = OMP_CLAUSE_SHARED;
2180 goto add_clause;
2181 case OMP_LIST_FIRSTPRIVATE:
2182 clause_code = OMP_CLAUSE_FIRSTPRIVATE;
2183 goto add_clause;
2184 case OMP_LIST_LASTPRIVATE:
2185 clause_code = OMP_CLAUSE_LASTPRIVATE;
2186 goto add_clause;
2187 case OMP_LIST_COPYIN:
2188 clause_code = OMP_CLAUSE_COPYIN;
2189 goto add_clause;
2190 case OMP_LIST_COPYPRIVATE:
2191 clause_code = OMP_CLAUSE_COPYPRIVATE;
2192 goto add_clause;
2193 case OMP_LIST_UNIFORM:
2194 clause_code = OMP_CLAUSE_UNIFORM;
2195 goto add_clause;
2196 case OMP_LIST_USE_DEVICE:
2197 case OMP_LIST_USE_DEVICE_PTR:
2198 clause_code = OMP_CLAUSE_USE_DEVICE_PTR;
2199 goto add_clause;
2200 case OMP_LIST_USE_DEVICE_ADDR:
2201 clause_code = OMP_CLAUSE_USE_DEVICE_ADDR;
2202 goto add_clause;
2203 case OMP_LIST_IS_DEVICE_PTR:
2204 clause_code = OMP_CLAUSE_IS_DEVICE_PTR;
2205 goto add_clause;
2206
2207 add_clause:
2208 omp_clauses
2209 = gfc_trans_omp_variable_list (clause_code, n, omp_clauses,
2210 declare_simd);
2211 break;
2212 case OMP_LIST_ALIGNED:
2213 for (; n != NULL; n = n->next)
2214 if (n->sym->attr.referenced || declare_simd)
2215 {
2216 tree t = gfc_trans_omp_variable (n->sym, declare_simd);
2217 if (t != error_mark_node)
2218 {
2219 tree node = build_omp_clause (input_location,
2220 OMP_CLAUSE_ALIGNED);
2221 OMP_CLAUSE_DECL (node) = t;
2222 if (n->expr)
2223 {
2224 tree alignment_var;
2225
2226 if (declare_simd)
2227 alignment_var = gfc_conv_constant_to_tree (n->expr);
2228 else
2229 {
2230 gfc_init_se (&se, NULL);
2231 gfc_conv_expr (&se, n->expr);
2232 gfc_add_block_to_block (block, &se.pre);
2233 alignment_var = gfc_evaluate_now (se.expr, block);
2234 gfc_add_block_to_block (block, &se.post);
2235 }
2236 OMP_CLAUSE_ALIGNED_ALIGNMENT (node) = alignment_var;
2237 }
2238 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2239 }
2240 }
2241 break;
2242 case OMP_LIST_LINEAR:
2243 {
2244 gfc_expr *last_step_expr = NULL;
2245 tree last_step = NULL_TREE;
2246 bool last_step_parm = false;
2247
2248 for (; n != NULL; n = n->next)
2249 {
2250 if (n->expr)
2251 {
2252 last_step_expr = n->expr;
2253 last_step = NULL_TREE;
2254 last_step_parm = false;
2255 }
2256 if (n->sym->attr.referenced || declare_simd)
2257 {
2258 tree t = gfc_trans_omp_variable (n->sym, declare_simd);
2259 if (t != error_mark_node)
2260 {
2261 tree node = build_omp_clause (input_location,
2262 OMP_CLAUSE_LINEAR);
2263 OMP_CLAUSE_DECL (node) = t;
2264 omp_clause_linear_kind kind;
2265 switch (n->u.linear_op)
2266 {
2267 case OMP_LINEAR_DEFAULT:
2268 kind = OMP_CLAUSE_LINEAR_DEFAULT;
2269 break;
2270 case OMP_LINEAR_REF:
2271 kind = OMP_CLAUSE_LINEAR_REF;
2272 break;
2273 case OMP_LINEAR_VAL:
2274 kind = OMP_CLAUSE_LINEAR_VAL;
2275 break;
2276 case OMP_LINEAR_UVAL:
2277 kind = OMP_CLAUSE_LINEAR_UVAL;
2278 break;
2279 default:
2280 gcc_unreachable ();
2281 }
2282 OMP_CLAUSE_LINEAR_KIND (node) = kind;
2283 if (last_step_expr && last_step == NULL_TREE)
2284 {
2285 if (!declare_simd)
2286 {
2287 gfc_init_se (&se, NULL);
2288 gfc_conv_expr (&se, last_step_expr);
2289 gfc_add_block_to_block (block, &se.pre);
2290 last_step = gfc_evaluate_now (se.expr, block);
2291 gfc_add_block_to_block (block, &se.post);
2292 }
2293 else if (last_step_expr->expr_type == EXPR_VARIABLE)
2294 {
2295 gfc_symbol *s = last_step_expr->symtree->n.sym;
2296 last_step = gfc_trans_omp_variable (s, true);
2297 last_step_parm = true;
2298 }
2299 else
2300 last_step
2301 = gfc_conv_constant_to_tree (last_step_expr);
2302 }
2303 if (last_step_parm)
2304 {
2305 OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (node) = 1;
2306 OMP_CLAUSE_LINEAR_STEP (node) = last_step;
2307 }
2308 else
2309 {
2310 if (kind == OMP_CLAUSE_LINEAR_REF)
2311 {
2312 tree type;
2313 if (n->sym->attr.flavor == FL_PROCEDURE)
2314 {
2315 type = gfc_get_function_type (n->sym);
2316 type = build_pointer_type (type);
2317 }
2318 else
2319 type = gfc_sym_type (n->sym);
2320 if (POINTER_TYPE_P (type))
2321 type = TREE_TYPE (type);
2322 /* Otherwise to be determined what exactly
2323 should be done. */
2324 tree t = fold_convert (sizetype, last_step);
2325 t = size_binop (MULT_EXPR, t,
2326 TYPE_SIZE_UNIT (type));
2327 OMP_CLAUSE_LINEAR_STEP (node) = t;
2328 }
2329 else
2330 {
2331 tree type
2332 = gfc_typenode_for_spec (&n->sym->ts);
2333 OMP_CLAUSE_LINEAR_STEP (node)
2334 = fold_convert (type, last_step);
2335 }
2336 }
2337 if (n->sym->attr.dimension || n->sym->attr.allocatable)
2338 OMP_CLAUSE_LINEAR_ARRAY (node) = 1;
2339 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2340 }
2341 }
2342 }
2343 }
2344 break;
2345 case OMP_LIST_DEPEND:
2346 for (; n != NULL; n = n->next)
2347 {
2348 if (n->u.depend_op == OMP_DEPEND_SINK_FIRST)
2349 {
2350 tree vec = NULL_TREE;
2351 unsigned int i;
2352 for (i = 0; ; i++)
2353 {
2354 tree addend = integer_zero_node, t;
2355 bool neg = false;
2356 if (n->expr)
2357 {
2358 addend = gfc_conv_constant_to_tree (n->expr);
2359 if (TREE_CODE (addend) == INTEGER_CST
2360 && tree_int_cst_sgn (addend) == -1)
2361 {
2362 neg = true;
2363 addend = const_unop (NEGATE_EXPR,
2364 TREE_TYPE (addend), addend);
2365 }
2366 }
2367 t = gfc_trans_omp_variable (n->sym, false);
2368 if (t != error_mark_node)
2369 {
2370 if (i < vec_safe_length (doacross_steps)
2371 && !integer_zerop (addend)
2372 && (*doacross_steps)[i])
2373 {
2374 tree step = (*doacross_steps)[i];
2375 addend = fold_convert (TREE_TYPE (step), addend);
2376 addend = build2 (TRUNC_DIV_EXPR,
2377 TREE_TYPE (step), addend, step);
2378 }
2379 vec = tree_cons (addend, t, vec);
2380 if (neg)
2381 OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1;
2382 }
2383 if (n->next == NULL
2384 || n->next->u.depend_op != OMP_DEPEND_SINK)
2385 break;
2386 n = n->next;
2387 }
2388 if (vec == NULL_TREE)
2389 continue;
2390
2391 tree node = build_omp_clause (input_location,
2392 OMP_CLAUSE_DEPEND);
2393 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_SINK;
2394 OMP_CLAUSE_DECL (node) = nreverse (vec);
2395 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2396 continue;
2397 }
2398
2399 if (!n->sym->attr.referenced)
2400 continue;
2401
2402 tree node = build_omp_clause (input_location, OMP_CLAUSE_DEPEND);
2403 if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
2404 {
2405 tree decl = gfc_trans_omp_variable (n->sym, false);
2406 if (gfc_omp_privatize_by_reference (decl))
2407 decl = build_fold_indirect_ref (decl);
2408 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
2409 {
2410 decl = gfc_conv_descriptor_data_get (decl);
2411 decl = fold_convert (build_pointer_type (char_type_node),
2412 decl);
2413 decl = build_fold_indirect_ref (decl);
2414 }
2415 else if (DECL_P (decl))
2416 TREE_ADDRESSABLE (decl) = 1;
2417 OMP_CLAUSE_DECL (node) = decl;
2418 }
2419 else
2420 {
2421 tree ptr;
2422 gfc_init_se (&se, NULL);
2423 if (n->expr->ref->u.ar.type == AR_ELEMENT)
2424 {
2425 gfc_conv_expr_reference (&se, n->expr);
2426 ptr = se.expr;
2427 }
2428 else
2429 {
2430 gfc_conv_expr_descriptor (&se, n->expr);
2431 ptr = gfc_conv_array_data (se.expr);
2432 }
2433 gfc_add_block_to_block (block, &se.pre);
2434 gfc_add_block_to_block (block, &se.post);
2435 ptr = fold_convert (build_pointer_type (char_type_node),
2436 ptr);
2437 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
2438 }
2439 switch (n->u.depend_op)
2440 {
2441 case OMP_DEPEND_IN:
2442 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_IN;
2443 break;
2444 case OMP_DEPEND_OUT:
2445 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_OUT;
2446 break;
2447 case OMP_DEPEND_INOUT:
2448 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_INOUT;
2449 break;
2450 default:
2451 gcc_unreachable ();
2452 }
2453 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2454 }
2455 break;
2456 case OMP_LIST_MAP:
2457 for (; n != NULL; n = n->next)
2458 {
2459 if (!n->sym->attr.referenced)
2460 continue;
2461
2462 tree node = build_omp_clause (input_location, OMP_CLAUSE_MAP);
2463 tree node2 = NULL_TREE;
2464 tree node3 = NULL_TREE;
2465 tree node4 = NULL_TREE;
2466 tree decl = gfc_trans_omp_variable (n->sym, false);
2467 if (DECL_P (decl))
2468 TREE_ADDRESSABLE (decl) = 1;
2469 if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
2470 {
2471 tree present = (gfc_omp_is_optional_argument (decl)
2472 ? gfc_omp_check_optional_argument (decl, true)
2473 : NULL_TREE);
2474 if (n->sym->ts.type == BT_CLASS)
2475 {
2476 tree type = TREE_TYPE (decl);
2477 if (n->sym->attr.optional)
2478 sorry ("optional class parameter");
2479 if (POINTER_TYPE_P (type))
2480 {
2481 node4 = build_omp_clause (input_location,
2482 OMP_CLAUSE_MAP);
2483 OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER);
2484 OMP_CLAUSE_DECL (node4) = decl;
2485 OMP_CLAUSE_SIZE (node4) = size_int (0);
2486 decl = build_fold_indirect_ref (decl);
2487 }
2488 tree ptr = gfc_class_data_get (decl);
2489 ptr = build_fold_indirect_ref (ptr);
2490 OMP_CLAUSE_DECL (node) = ptr;
2491 OMP_CLAUSE_SIZE (node) = gfc_class_vtab_size_get (decl);
2492 node2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
2493 OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
2494 OMP_CLAUSE_DECL (node2) = decl;
2495 OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
2496 node3 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
2497 OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_ATTACH_DETACH);
2498 OMP_CLAUSE_DECL (node3) = gfc_class_data_get (decl);
2499 OMP_CLAUSE_SIZE (node3) = size_int (0);
2500 goto finalize_map_clause;
2501 }
2502 else if (POINTER_TYPE_P (TREE_TYPE (decl))
2503 && (gfc_omp_privatize_by_reference (decl)
2504 || GFC_DECL_GET_SCALAR_POINTER (decl)
2505 || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
2506 || GFC_DECL_CRAY_POINTEE (decl)
2507 || GFC_DESCRIPTOR_TYPE_P
2508 (TREE_TYPE (TREE_TYPE (decl)))
2509 || n->sym->ts.type == BT_DERIVED))
2510 {
2511 tree orig_decl = decl;
2512 node4 = build_omp_clause (input_location,
2513 OMP_CLAUSE_MAP);
2514 OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER);
2515 OMP_CLAUSE_DECL (node4) = decl;
2516 OMP_CLAUSE_SIZE (node4) = size_int (0);
2517 decl = build_fold_indirect_ref (decl);
2518 if ((TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE
2519 || gfc_omp_is_optional_argument (orig_decl))
2520 && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
2521 || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
2522 {
2523 node3 = build_omp_clause (input_location,
2524 OMP_CLAUSE_MAP);
2525 OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_POINTER);
2526 OMP_CLAUSE_DECL (node3) = decl;
2527 OMP_CLAUSE_SIZE (node3) = size_int (0);
2528 decl = build_fold_indirect_ref (decl);
2529 }
2530 }
2531 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))
2532 && n->u.map_op != OMP_MAP_ATTACH
2533 && n->u.map_op != OMP_MAP_DETACH)
2534 {
2535 tree type = TREE_TYPE (decl);
2536 tree ptr = gfc_conv_descriptor_data_get (decl);
2537 if (present)
2538 ptr = gfc_build_cond_assign_expr (block, present, ptr,
2539 null_pointer_node);
2540 ptr = fold_convert (build_pointer_type (char_type_node),
2541 ptr);
2542 ptr = build_fold_indirect_ref (ptr);
2543 OMP_CLAUSE_DECL (node) = ptr;
2544 node2 = build_omp_clause (input_location,
2545 OMP_CLAUSE_MAP);
2546 OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
2547 OMP_CLAUSE_DECL (node2) = decl;
2548 OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
2549 node3 = build_omp_clause (input_location,
2550 OMP_CLAUSE_MAP);
2551 OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_POINTER);
2552 if (present)
2553 {
2554 ptr = gfc_conv_descriptor_data_get (decl);
2555 ptr = gfc_build_addr_expr (NULL, ptr);
2556 ptr = gfc_build_cond_assign_expr (block, present, ptr,
2557 null_pointer_node);
2558 ptr = build_fold_indirect_ref (ptr);
2559 OMP_CLAUSE_DECL (node3) = ptr;
2560 }
2561 else
2562 OMP_CLAUSE_DECL (node3)
2563 = gfc_conv_descriptor_data_get (decl);
2564 OMP_CLAUSE_SIZE (node3) = size_int (0);
2565
2566 /* We have to check for n->sym->attr.dimension because
2567 of scalar coarrays. */
2568 if (n->sym->attr.pointer && n->sym->attr.dimension)
2569 {
2570 stmtblock_t cond_block;
2571 tree size
2572 = gfc_create_var (gfc_array_index_type, NULL);
2573 tree tem, then_b, else_b, zero, cond;
2574
2575 gfc_init_block (&cond_block);
2576 tem
2577 = gfc_full_array_size (&cond_block, decl,
2578 GFC_TYPE_ARRAY_RANK (type));
2579 gfc_add_modify (&cond_block, size, tem);
2580 then_b = gfc_finish_block (&cond_block);
2581 gfc_init_block (&cond_block);
2582 zero = build_int_cst (gfc_array_index_type, 0);
2583 gfc_add_modify (&cond_block, size, zero);
2584 else_b = gfc_finish_block (&cond_block);
2585 tem = gfc_conv_descriptor_data_get (decl);
2586 tem = fold_convert (pvoid_type_node, tem);
2587 cond = fold_build2_loc (input_location, NE_EXPR,
2588 boolean_type_node,
2589 tem, null_pointer_node);
2590 if (present)
2591 {
2592 tree tmp = fold_build2_loc (input_location,
2593 NE_EXPR,
2594 boolean_type_node,
2595 present,
2596 null_pointer_node);
2597 cond = fold_build2_loc (input_location,
2598 TRUTH_ANDIF_EXPR,
2599 boolean_type_node,
2600 tmp, cond);
2601 }
2602 gfc_add_expr_to_block (block,
2603 build3_loc (input_location,
2604 COND_EXPR,
2605 void_type_node,
2606 cond, then_b,
2607 else_b));
2608 OMP_CLAUSE_SIZE (node) = size;
2609 }
2610 else if (n->sym->attr.dimension)
2611 {
2612 stmtblock_t cond_block;
2613 gfc_init_block (&cond_block);
2614 tree size = gfc_full_array_size (&cond_block, decl,
2615 GFC_TYPE_ARRAY_RANK (type));
2616 if (present)
2617 {
2618 tree var = gfc_create_var (gfc_array_index_type,
2619 NULL);
2620 tree cond = fold_build2_loc (input_location,
2621 NE_EXPR,
2622 boolean_type_node,
2623 present,
2624 null_pointer_node);
2625 gfc_add_modify (&cond_block, var, size);
2626 cond = build3_loc (input_location, COND_EXPR,
2627 void_type_node, cond,
2628 gfc_finish_block (&cond_block),
2629 NULL_TREE);
2630 gfc_add_expr_to_block (block, cond);
2631 OMP_CLAUSE_SIZE (node) = var;
2632 }
2633 else
2634 {
2635 gfc_add_block_to_block (block, &cond_block);
2636 OMP_CLAUSE_SIZE (node) = size;
2637 }
2638 }
2639 if (n->sym->attr.dimension)
2640 {
2641 tree elemsz
2642 = TYPE_SIZE_UNIT (gfc_get_element_type (type));
2643 elemsz = fold_convert (gfc_array_index_type, elemsz);
2644 OMP_CLAUSE_SIZE (node)
2645 = fold_build2 (MULT_EXPR, gfc_array_index_type,
2646 OMP_CLAUSE_SIZE (node), elemsz);
2647 }
2648 }
2649 else if (present
2650 && TREE_CODE (decl) == INDIRECT_REF
2651 && (TREE_CODE (TREE_OPERAND (decl, 0))
2652 == INDIRECT_REF))
2653 {
2654 /* A single indirectref is handled by the middle end. */
2655 gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
2656 decl = TREE_OPERAND (decl, 0);
2657 decl = gfc_build_cond_assign_expr (block, present, decl,
2658 null_pointer_node);
2659 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (decl);
2660 }
2661 else
2662 OMP_CLAUSE_DECL (node) = decl;
2663 }
2664 else if (n->expr
2665 && n->expr->expr_type == EXPR_VARIABLE
2666 && n->expr->ref->type == REF_COMPONENT)
2667 {
2668 gfc_ref *lastcomp;
2669
2670 for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
2671 if (ref->type == REF_COMPONENT)
2672 lastcomp = ref;
2673
2674 symbol_attribute sym_attr;
2675
2676 if (lastcomp->u.c.component->ts.type == BT_CLASS)
2677 sym_attr = CLASS_DATA (lastcomp->u.c.component)->attr;
2678 else
2679 sym_attr = lastcomp->u.c.component->attr;
2680
2681 gfc_init_se (&se, NULL);
2682
2683 if (!sym_attr.dimension
2684 && lastcomp->u.c.component->ts.type != BT_CLASS
2685 && lastcomp->u.c.component->ts.type != BT_DERIVED)
2686 {
2687 /* Last component is a scalar. */
2688 gfc_conv_expr (&se, n->expr);
2689 gfc_add_block_to_block (block, &se.pre);
2690 OMP_CLAUSE_DECL (node) = se.expr;
2691 gfc_add_block_to_block (block, &se.post);
2692 goto finalize_map_clause;
2693 }
2694
2695 se.expr = gfc_maybe_dereference_var (n->sym, decl);
2696
2697 for (gfc_ref *ref = n->expr->ref;
2698 ref && ref != lastcomp->next;
2699 ref = ref->next)
2700 {
2701 if (ref->type == REF_COMPONENT)
2702 {
2703 if (ref->u.c.sym->attr.extension)
2704 conv_parent_component_references (&se, ref);
2705
2706 gfc_conv_component_ref (&se, ref);
2707 }
2708 else
2709 sorry ("unhandled derived-type component");
2710 }
2711
2712 tree inner = se.expr;
2713
2714 /* Last component is a derived type or class pointer. */
2715 if (lastcomp->u.c.component->ts.type == BT_DERIVED
2716 || lastcomp->u.c.component->ts.type == BT_CLASS)
2717 {
2718 if (sym_attr.allocatable || sym_attr.pointer)
2719 {
2720 tree data, size;
2721
2722 if (lastcomp->u.c.component->ts.type == BT_CLASS)
2723 {
2724 data = gfc_class_data_get (inner);
2725 size = gfc_class_vtab_size_get (inner);
2726 }
2727 else /* BT_DERIVED. */
2728 {
2729 data = inner;
2730 size = TYPE_SIZE_UNIT (TREE_TYPE (inner));
2731 }
2732
2733 OMP_CLAUSE_DECL (node)
2734 = build_fold_indirect_ref (data);
2735 OMP_CLAUSE_SIZE (node) = size;
2736 node2 = build_omp_clause (input_location,
2737 OMP_CLAUSE_MAP);
2738 OMP_CLAUSE_SET_MAP_KIND (node2,
2739 GOMP_MAP_ATTACH_DETACH);
2740 OMP_CLAUSE_DECL (node2) = data;
2741 OMP_CLAUSE_SIZE (node2) = size_int (0);
2742 }
2743 else
2744 {
2745 OMP_CLAUSE_DECL (node) = decl;
2746 OMP_CLAUSE_SIZE (node)
2747 = TYPE_SIZE_UNIT (TREE_TYPE (decl));
2748 }
2749 }
2750 else if (lastcomp->next
2751 && lastcomp->next->type == REF_ARRAY
2752 && lastcomp->next->u.ar.type == AR_FULL)
2753 {
2754 /* Just pass the (auto-dereferenced) decl through for
2755 bare attach and detach clauses. */
2756 if (n->u.map_op == OMP_MAP_ATTACH
2757 || n->u.map_op == OMP_MAP_DETACH)
2758 {
2759 OMP_CLAUSE_DECL (node) = inner;
2760 OMP_CLAUSE_SIZE (node) = size_zero_node;
2761 goto finalize_map_clause;
2762 }
2763
2764 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (inner)))
2765 {
2766 tree type = TREE_TYPE (inner);
2767 tree ptr = gfc_conv_descriptor_data_get (inner);
2768 ptr = build_fold_indirect_ref (ptr);
2769 OMP_CLAUSE_DECL (node) = ptr;
2770 node2 = build_omp_clause (input_location,
2771 OMP_CLAUSE_MAP);
2772 OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
2773 OMP_CLAUSE_DECL (node2) = inner;
2774 OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
2775 node3 = build_omp_clause (input_location,
2776 OMP_CLAUSE_MAP);
2777 OMP_CLAUSE_SET_MAP_KIND (node3,
2778 GOMP_MAP_ATTACH_DETACH);
2779 OMP_CLAUSE_DECL (node3)
2780 = gfc_conv_descriptor_data_get (inner);
2781 STRIP_NOPS (OMP_CLAUSE_DECL (node3));
2782 OMP_CLAUSE_SIZE (node3) = size_int (0);
2783 int rank = GFC_TYPE_ARRAY_RANK (type);
2784 OMP_CLAUSE_SIZE (node)
2785 = gfc_full_array_size (block, inner, rank);
2786 tree elemsz
2787 = TYPE_SIZE_UNIT (gfc_get_element_type (type));
2788 elemsz = fold_convert (gfc_array_index_type, elemsz);
2789 OMP_CLAUSE_SIZE (node)
2790 = fold_build2 (MULT_EXPR, gfc_array_index_type,
2791 OMP_CLAUSE_SIZE (node), elemsz);
2792 }
2793 else
2794 OMP_CLAUSE_DECL (node) = inner;
2795 }
2796 else /* An array element or section. */
2797 {
2798 bool element
2799 = (lastcomp->next
2800 && lastcomp->next->type == REF_ARRAY
2801 && lastcomp->next->u.ar.type == AR_ELEMENT);
2802
2803 gfc_trans_omp_array_section (block, n, inner, element,
2804 GOMP_MAP_ATTACH_DETACH,
2805 node, node2, node3, node4);
2806 }
2807 }
2808 else /* An array element or array section. */
2809 {
2810 bool element = n->expr->ref->u.ar.type == AR_ELEMENT;
2811 gfc_trans_omp_array_section (block, n, decl, element,
2812 GOMP_MAP_POINTER, node, node2,
2813 node3, node4);
2814 }
2815
2816 finalize_map_clause:
2817 switch (n->u.map_op)
2818 {
2819 case OMP_MAP_ALLOC:
2820 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALLOC);
2821 break;
2822 case OMP_MAP_IF_PRESENT:
2823 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_IF_PRESENT);
2824 break;
2825 case OMP_MAP_ATTACH:
2826 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ATTACH);
2827 break;
2828 case OMP_MAP_TO:
2829 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TO);
2830 break;
2831 case OMP_MAP_FROM:
2832 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FROM);
2833 break;
2834 case OMP_MAP_TOFROM:
2835 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TOFROM);
2836 break;
2837 case OMP_MAP_ALWAYS_TO:
2838 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TO);
2839 break;
2840 case OMP_MAP_ALWAYS_FROM:
2841 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_FROM);
2842 break;
2843 case OMP_MAP_ALWAYS_TOFROM:
2844 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TOFROM);
2845 break;
2846 case OMP_MAP_RELEASE:
2847 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_RELEASE);
2848 break;
2849 case OMP_MAP_DELETE:
2850 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_DELETE);
2851 break;
2852 case OMP_MAP_DETACH:
2853 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_DETACH);
2854 break;
2855 case OMP_MAP_FORCE_ALLOC:
2856 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_ALLOC);
2857 break;
2858 case OMP_MAP_FORCE_TO:
2859 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TO);
2860 break;
2861 case OMP_MAP_FORCE_FROM:
2862 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_FROM);
2863 break;
2864 case OMP_MAP_FORCE_TOFROM:
2865 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TOFROM);
2866 break;
2867 case OMP_MAP_FORCE_PRESENT:
2868 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_PRESENT);
2869 break;
2870 case OMP_MAP_FORCE_DEVICEPTR:
2871 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_DEVICEPTR);
2872 break;
2873 default:
2874 gcc_unreachable ();
2875 }
2876 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2877 if (node2)
2878 omp_clauses = gfc_trans_add_clause (node2, omp_clauses);
2879 if (node3)
2880 omp_clauses = gfc_trans_add_clause (node3, omp_clauses);
2881 if (node4)
2882 omp_clauses = gfc_trans_add_clause (node4, omp_clauses);
2883 }
2884 break;
2885 case OMP_LIST_TO:
2886 case OMP_LIST_FROM:
2887 case OMP_LIST_CACHE:
2888 for (; n != NULL; n = n->next)
2889 {
2890 if (!n->sym->attr.referenced)
2891 continue;
2892
2893 switch (list)
2894 {
2895 case OMP_LIST_TO:
2896 clause_code = OMP_CLAUSE_TO;
2897 break;
2898 case OMP_LIST_FROM:
2899 clause_code = OMP_CLAUSE_FROM;
2900 break;
2901 case OMP_LIST_CACHE:
2902 clause_code = OMP_CLAUSE__CACHE_;
2903 break;
2904 default:
2905 gcc_unreachable ();
2906 }
2907 tree node = build_omp_clause (input_location, clause_code);
2908 if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
2909 {
2910 tree decl = gfc_trans_omp_variable (n->sym, false);
2911 if (gfc_omp_privatize_by_reference (decl))
2912 {
2913 if (gfc_omp_is_allocatable_or_ptr (decl))
2914 decl = build_fold_indirect_ref (decl);
2915 decl = build_fold_indirect_ref (decl);
2916 }
2917 else if (DECL_P (decl))
2918 TREE_ADDRESSABLE (decl) = 1;
2919 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
2920 {
2921 tree type = TREE_TYPE (decl);
2922 tree ptr = gfc_conv_descriptor_data_get (decl);
2923 ptr = fold_convert (build_pointer_type (char_type_node),
2924 ptr);
2925 ptr = build_fold_indirect_ref (ptr);
2926 OMP_CLAUSE_DECL (node) = ptr;
2927 OMP_CLAUSE_SIZE (node)
2928 = gfc_full_array_size (block, decl,
2929 GFC_TYPE_ARRAY_RANK (type));
2930 tree elemsz
2931 = TYPE_SIZE_UNIT (gfc_get_element_type (type));
2932 elemsz = fold_convert (gfc_array_index_type, elemsz);
2933 OMP_CLAUSE_SIZE (node)
2934 = fold_build2 (MULT_EXPR, gfc_array_index_type,
2935 OMP_CLAUSE_SIZE (node), elemsz);
2936 }
2937 else
2938 {
2939 OMP_CLAUSE_DECL (node) = decl;
2940 if (gfc_omp_is_allocatable_or_ptr (decl))
2941 OMP_CLAUSE_SIZE (node)
2942 = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)));
2943 }
2944 }
2945 else
2946 {
2947 tree ptr;
2948 gfc_init_se (&se, NULL);
2949 if (n->expr->ref->u.ar.type == AR_ELEMENT)
2950 {
2951 gfc_conv_expr_reference (&se, n->expr);
2952 ptr = se.expr;
2953 gfc_add_block_to_block (block, &se.pre);
2954 OMP_CLAUSE_SIZE (node)
2955 = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
2956 }
2957 else
2958 {
2959 gfc_conv_expr_descriptor (&se, n->expr);
2960 ptr = gfc_conv_array_data (se.expr);
2961 tree type = TREE_TYPE (se.expr);
2962 gfc_add_block_to_block (block, &se.pre);
2963 OMP_CLAUSE_SIZE (node)
2964 = gfc_full_array_size (block, se.expr,
2965 GFC_TYPE_ARRAY_RANK (type));
2966 tree elemsz
2967 = TYPE_SIZE_UNIT (gfc_get_element_type (type));
2968 elemsz = fold_convert (gfc_array_index_type, elemsz);
2969 OMP_CLAUSE_SIZE (node)
2970 = fold_build2 (MULT_EXPR, gfc_array_index_type,
2971 OMP_CLAUSE_SIZE (node), elemsz);
2972 }
2973 gfc_add_block_to_block (block, &se.post);
2974 ptr = fold_convert (build_pointer_type (char_type_node),
2975 ptr);
2976 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
2977 }
2978 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2979 }
2980 break;
2981 default:
2982 break;
2983 }
2984 }
2985
2986 if (clauses->if_expr)
2987 {
2988 tree if_var;
2989
2990 gfc_init_se (&se, NULL);
2991 gfc_conv_expr (&se, clauses->if_expr);
2992 gfc_add_block_to_block (block, &se.pre);
2993 if_var = gfc_evaluate_now (se.expr, block);
2994 gfc_add_block_to_block (block, &se.post);
2995
2996 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF);
2997 OMP_CLAUSE_IF_MODIFIER (c) = ERROR_MARK;
2998 OMP_CLAUSE_IF_EXPR (c) = if_var;
2999 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3000 }
3001 for (ifc = 0; ifc < OMP_IF_LAST; ifc++)
3002 if (clauses->if_exprs[ifc])
3003 {
3004 tree if_var;
3005
3006 gfc_init_se (&se, NULL);
3007 gfc_conv_expr (&se, clauses->if_exprs[ifc]);
3008 gfc_add_block_to_block (block, &se.pre);
3009 if_var = gfc_evaluate_now (se.expr, block);
3010 gfc_add_block_to_block (block, &se.post);
3011
3012 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF);
3013 switch (ifc)
3014 {
3015 case OMP_IF_PARALLEL:
3016 OMP_CLAUSE_IF_MODIFIER (c) = OMP_PARALLEL;
3017 break;
3018 case OMP_IF_TASK:
3019 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TASK;
3020 break;
3021 case OMP_IF_TASKLOOP:
3022 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TASKLOOP;
3023 break;
3024 case OMP_IF_TARGET:
3025 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET;
3026 break;
3027 case OMP_IF_TARGET_DATA:
3028 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_DATA;
3029 break;
3030 case OMP_IF_TARGET_UPDATE:
3031 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_UPDATE;
3032 break;
3033 case OMP_IF_TARGET_ENTER_DATA:
3034 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_ENTER_DATA;
3035 break;
3036 case OMP_IF_TARGET_EXIT_DATA:
3037 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_EXIT_DATA;
3038 break;
3039 default:
3040 gcc_unreachable ();
3041 }
3042 OMP_CLAUSE_IF_EXPR (c) = if_var;
3043 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3044 }
3045
3046 if (clauses->final_expr)
3047 {
3048 tree final_var;
3049
3050 gfc_init_se (&se, NULL);
3051 gfc_conv_expr (&se, clauses->final_expr);
3052 gfc_add_block_to_block (block, &se.pre);
3053 final_var = gfc_evaluate_now (se.expr, block);
3054 gfc_add_block_to_block (block, &se.post);
3055
3056 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FINAL);
3057 OMP_CLAUSE_FINAL_EXPR (c) = final_var;
3058 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3059 }
3060
3061 if (clauses->num_threads)
3062 {
3063 tree num_threads;
3064
3065 gfc_init_se (&se, NULL);
3066 gfc_conv_expr (&se, clauses->num_threads);
3067 gfc_add_block_to_block (block, &se.pre);
3068 num_threads = gfc_evaluate_now (se.expr, block);
3069 gfc_add_block_to_block (block, &se.post);
3070
3071 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_THREADS);
3072 OMP_CLAUSE_NUM_THREADS_EXPR (c) = num_threads;
3073 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3074 }
3075
3076 chunk_size = NULL_TREE;
3077 if (clauses->chunk_size)
3078 {
3079 gfc_init_se (&se, NULL);
3080 gfc_conv_expr (&se, clauses->chunk_size);
3081 gfc_add_block_to_block (block, &se.pre);
3082 chunk_size = gfc_evaluate_now (se.expr, block);
3083 gfc_add_block_to_block (block, &se.post);
3084 }
3085
3086 if (clauses->sched_kind != OMP_SCHED_NONE)
3087 {
3088 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SCHEDULE);
3089 OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
3090 switch (clauses->sched_kind)
3091 {
3092 case OMP_SCHED_STATIC:
3093 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
3094 break;
3095 case OMP_SCHED_DYNAMIC:
3096 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
3097 break;
3098 case OMP_SCHED_GUIDED:
3099 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
3100 break;
3101 case OMP_SCHED_RUNTIME:
3102 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
3103 break;
3104 case OMP_SCHED_AUTO:
3105 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
3106 break;
3107 default:
3108 gcc_unreachable ();
3109 }
3110 if (clauses->sched_monotonic)
3111 OMP_CLAUSE_SCHEDULE_KIND (c)
3112 = (omp_clause_schedule_kind) (OMP_CLAUSE_SCHEDULE_KIND (c)
3113 | OMP_CLAUSE_SCHEDULE_MONOTONIC);
3114 else if (clauses->sched_nonmonotonic)
3115 OMP_CLAUSE_SCHEDULE_KIND (c)
3116 = (omp_clause_schedule_kind) (OMP_CLAUSE_SCHEDULE_KIND (c)
3117 | OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
3118 if (clauses->sched_simd)
3119 OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
3120 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3121 }
3122
3123 if (clauses->default_sharing != OMP_DEFAULT_UNKNOWN)
3124 {
3125 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEFAULT);
3126 switch (clauses->default_sharing)
3127 {
3128 case OMP_DEFAULT_NONE:
3129 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_NONE;
3130 break;
3131 case OMP_DEFAULT_SHARED:
3132 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_SHARED;
3133 break;
3134 case OMP_DEFAULT_PRIVATE:
3135 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRIVATE;
3136 break;
3137 case OMP_DEFAULT_FIRSTPRIVATE:
3138 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
3139 break;
3140 case OMP_DEFAULT_PRESENT:
3141 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRESENT;
3142 break;
3143 default:
3144 gcc_unreachable ();
3145 }
3146 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3147 }
3148
3149 if (clauses->nowait)
3150 {
3151 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOWAIT);
3152 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3153 }
3154
3155 if (clauses->ordered)
3156 {
3157 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ORDERED);
3158 OMP_CLAUSE_ORDERED_EXPR (c)
3159 = clauses->orderedc ? build_int_cst (integer_type_node,
3160 clauses->orderedc) : NULL_TREE;
3161 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3162 }
3163
3164 if (clauses->untied)
3165 {
3166 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_UNTIED);
3167 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3168 }
3169
3170 if (clauses->mergeable)
3171 {
3172 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_MERGEABLE);
3173 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3174 }
3175
3176 if (clauses->collapse)
3177 {
3178 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_COLLAPSE);
3179 OMP_CLAUSE_COLLAPSE_EXPR (c)
3180 = build_int_cst (integer_type_node, clauses->collapse);
3181 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3182 }
3183
3184 if (clauses->inbranch)
3185 {
3186 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_INBRANCH);
3187 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3188 }
3189
3190 if (clauses->notinbranch)
3191 {
3192 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOTINBRANCH);
3193 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3194 }
3195
3196 switch (clauses->cancel)
3197 {
3198 case OMP_CANCEL_UNKNOWN:
3199 break;
3200 case OMP_CANCEL_PARALLEL:
3201 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PARALLEL);
3202 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3203 break;
3204 case OMP_CANCEL_SECTIONS:
3205 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SECTIONS);
3206 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3207 break;
3208 case OMP_CANCEL_DO:
3209 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FOR);
3210 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3211 break;
3212 case OMP_CANCEL_TASKGROUP:
3213 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_TASKGROUP);
3214 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3215 break;
3216 }
3217
3218 if (clauses->proc_bind != OMP_PROC_BIND_UNKNOWN)
3219 {
3220 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PROC_BIND);
3221 switch (clauses->proc_bind)
3222 {
3223 case OMP_PROC_BIND_MASTER:
3224 OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_MASTER;
3225 break;
3226 case OMP_PROC_BIND_SPREAD:
3227 OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_SPREAD;
3228 break;
3229 case OMP_PROC_BIND_CLOSE:
3230 OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_CLOSE;
3231 break;
3232 default:
3233 gcc_unreachable ();
3234 }
3235 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3236 }
3237
3238 if (clauses->safelen_expr)
3239 {
3240 tree safelen_var;
3241
3242 gfc_init_se (&se, NULL);
3243 gfc_conv_expr (&se, clauses->safelen_expr);
3244 gfc_add_block_to_block (block, &se.pre);
3245 safelen_var = gfc_evaluate_now (se.expr, block);
3246 gfc_add_block_to_block (block, &se.post);
3247
3248 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SAFELEN);
3249 OMP_CLAUSE_SAFELEN_EXPR (c) = safelen_var;
3250 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3251 }
3252
3253 if (clauses->simdlen_expr)
3254 {
3255 if (declare_simd)
3256 {
3257 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMDLEN);
3258 OMP_CLAUSE_SIMDLEN_EXPR (c)
3259 = gfc_conv_constant_to_tree (clauses->simdlen_expr);
3260 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3261 }
3262 else
3263 {
3264 tree simdlen_var;
3265
3266 gfc_init_se (&se, NULL);
3267 gfc_conv_expr (&se, clauses->simdlen_expr);
3268 gfc_add_block_to_block (block, &se.pre);
3269 simdlen_var = gfc_evaluate_now (se.expr, block);
3270 gfc_add_block_to_block (block, &se.post);
3271
3272 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMDLEN);
3273 OMP_CLAUSE_SIMDLEN_EXPR (c) = simdlen_var;
3274 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3275 }
3276 }
3277
3278 if (clauses->num_teams)
3279 {
3280 tree num_teams;
3281
3282 gfc_init_se (&se, NULL);
3283 gfc_conv_expr (&se, clauses->num_teams);
3284 gfc_add_block_to_block (block, &se.pre);
3285 num_teams = gfc_evaluate_now (se.expr, block);
3286 gfc_add_block_to_block (block, &se.post);
3287
3288 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_TEAMS);
3289 OMP_CLAUSE_NUM_TEAMS_EXPR (c) = num_teams;
3290 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3291 }
3292
3293 if (clauses->device)
3294 {
3295 tree device;
3296
3297 gfc_init_se (&se, NULL);
3298 gfc_conv_expr (&se, clauses->device);
3299 gfc_add_block_to_block (block, &se.pre);
3300 device = gfc_evaluate_now (se.expr, block);
3301 gfc_add_block_to_block (block, &se.post);
3302
3303 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEVICE);
3304 OMP_CLAUSE_DEVICE_ID (c) = device;
3305 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3306 }
3307
3308 if (clauses->thread_limit)
3309 {
3310 tree thread_limit;
3311
3312 gfc_init_se (&se, NULL);
3313 gfc_conv_expr (&se, clauses->thread_limit);
3314 gfc_add_block_to_block (block, &se.pre);
3315 thread_limit = gfc_evaluate_now (se.expr, block);
3316 gfc_add_block_to_block (block, &se.post);
3317
3318 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_THREAD_LIMIT);
3319 OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = thread_limit;
3320 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3321 }
3322
3323 chunk_size = NULL_TREE;
3324 if (clauses->dist_chunk_size)
3325 {
3326 gfc_init_se (&se, NULL);
3327 gfc_conv_expr (&se, clauses->dist_chunk_size);
3328 gfc_add_block_to_block (block, &se.pre);
3329 chunk_size = gfc_evaluate_now (se.expr, block);
3330 gfc_add_block_to_block (block, &se.post);
3331 }
3332
3333 if (clauses->dist_sched_kind != OMP_SCHED_NONE)
3334 {
3335 c = build_omp_clause (gfc_get_location (&where),
3336 OMP_CLAUSE_DIST_SCHEDULE);
3337 OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
3338 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3339 }
3340
3341 if (clauses->grainsize)
3342 {
3343 tree grainsize;
3344
3345 gfc_init_se (&se, NULL);
3346 gfc_conv_expr (&se, clauses->grainsize);
3347 gfc_add_block_to_block (block, &se.pre);
3348 grainsize = gfc_evaluate_now (se.expr, block);
3349 gfc_add_block_to_block (block, &se.post);
3350
3351 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_GRAINSIZE);
3352 OMP_CLAUSE_GRAINSIZE_EXPR (c) = grainsize;
3353 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3354 }
3355
3356 if (clauses->num_tasks)
3357 {
3358 tree num_tasks;
3359
3360 gfc_init_se (&se, NULL);
3361 gfc_conv_expr (&se, clauses->num_tasks);
3362 gfc_add_block_to_block (block, &se.pre);
3363 num_tasks = gfc_evaluate_now (se.expr, block);
3364 gfc_add_block_to_block (block, &se.post);
3365
3366 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_TASKS);
3367 OMP_CLAUSE_NUM_TASKS_EXPR (c) = num_tasks;
3368 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3369 }
3370
3371 if (clauses->priority)
3372 {
3373 tree priority;
3374
3375 gfc_init_se (&se, NULL);
3376 gfc_conv_expr (&se, clauses->priority);
3377 gfc_add_block_to_block (block, &se.pre);
3378 priority = gfc_evaluate_now (se.expr, block);
3379 gfc_add_block_to_block (block, &se.post);
3380
3381 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PRIORITY);
3382 OMP_CLAUSE_PRIORITY_EXPR (c) = priority;
3383 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3384 }
3385
3386 if (clauses->hint)
3387 {
3388 tree hint;
3389
3390 gfc_init_se (&se, NULL);
3391 gfc_conv_expr (&se, clauses->hint);
3392 gfc_add_block_to_block (block, &se.pre);
3393 hint = gfc_evaluate_now (se.expr, block);
3394 gfc_add_block_to_block (block, &se.post);
3395
3396 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_HINT);
3397 OMP_CLAUSE_HINT_EXPR (c) = hint;
3398 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3399 }
3400
3401 if (clauses->simd)
3402 {
3403 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMD);
3404 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3405 }
3406 if (clauses->threads)
3407 {
3408 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_THREADS);
3409 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3410 }
3411 if (clauses->nogroup)
3412 {
3413 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOGROUP);
3414 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3415 }
3416 if (clauses->defaultmap)
3417 {
3418 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEFAULTMAP);
3419 OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, OMP_CLAUSE_DEFAULTMAP_TOFROM,
3420 OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR);
3421 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3422 }
3423 if (clauses->depend_source)
3424 {
3425 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEPEND);
3426 OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_SOURCE;
3427 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3428 }
3429
3430 if (clauses->async)
3431 {
3432 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ASYNC);
3433 if (clauses->async_expr)
3434 OMP_CLAUSE_ASYNC_EXPR (c)
3435 = gfc_convert_expr_to_tree (block, clauses->async_expr);
3436 else
3437 OMP_CLAUSE_ASYNC_EXPR (c) = NULL;
3438 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3439 }
3440 if (clauses->seq)
3441 {
3442 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SEQ);
3443 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3444 }
3445 if (clauses->par_auto)
3446 {
3447 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_AUTO);
3448 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3449 }
3450 if (clauses->if_present)
3451 {
3452 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF_PRESENT);
3453 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3454 }
3455 if (clauses->finalize)
3456 {
3457 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FINALIZE);
3458 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3459 }
3460 if (clauses->independent)
3461 {
3462 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_INDEPENDENT);
3463 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3464 }
3465 if (clauses->wait_list)
3466 {
3467 gfc_expr_list *el;
3468
3469 for (el = clauses->wait_list; el; el = el->next)
3470 {
3471 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_WAIT);
3472 OMP_CLAUSE_DECL (c) = gfc_convert_expr_to_tree (block, el->expr);
3473 OMP_CLAUSE_CHAIN (c) = omp_clauses;
3474 omp_clauses = c;
3475 }
3476 }
3477 if (clauses->num_gangs_expr)
3478 {
3479 tree num_gangs_var
3480 = gfc_convert_expr_to_tree (block, clauses->num_gangs_expr);
3481 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_GANGS);
3482 OMP_CLAUSE_NUM_GANGS_EXPR (c) = num_gangs_var;
3483 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3484 }
3485 if (clauses->num_workers_expr)
3486 {
3487 tree num_workers_var
3488 = gfc_convert_expr_to_tree (block, clauses->num_workers_expr);
3489 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_WORKERS);
3490 OMP_CLAUSE_NUM_WORKERS_EXPR (c) = num_workers_var;
3491 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3492 }
3493 if (clauses->vector_length_expr)
3494 {
3495 tree vector_length_var
3496 = gfc_convert_expr_to_tree (block, clauses->vector_length_expr);
3497 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_VECTOR_LENGTH);
3498 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c) = vector_length_var;
3499 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3500 }
3501 if (clauses->tile_list)
3502 {
3503 vec<tree, va_gc> *tvec;
3504 gfc_expr_list *el;
3505
3506 vec_alloc (tvec, 4);
3507
3508 for (el = clauses->tile_list; el; el = el->next)
3509 vec_safe_push (tvec, gfc_convert_expr_to_tree (block, el->expr));
3510
3511 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_TILE);
3512 OMP_CLAUSE_TILE_LIST (c) = build_tree_list_vec (tvec);
3513 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3514 tvec->truncate (0);
3515 }
3516 if (clauses->vector)
3517 {
3518 if (clauses->vector_expr)
3519 {
3520 tree vector_var
3521 = gfc_convert_expr_to_tree (block, clauses->vector_expr);
3522 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_VECTOR);
3523 OMP_CLAUSE_VECTOR_EXPR (c) = vector_var;
3524 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3525 }
3526 else
3527 {
3528 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_VECTOR);
3529 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3530 }
3531 }
3532 if (clauses->worker)
3533 {
3534 if (clauses->worker_expr)
3535 {
3536 tree worker_var
3537 = gfc_convert_expr_to_tree (block, clauses->worker_expr);
3538 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_WORKER);
3539 OMP_CLAUSE_WORKER_EXPR (c) = worker_var;
3540 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3541 }
3542 else
3543 {
3544 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_WORKER);
3545 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3546 }
3547 }
3548 if (clauses->gang)
3549 {
3550 tree arg;
3551 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_GANG);
3552 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3553 if (clauses->gang_num_expr)
3554 {
3555 arg = gfc_convert_expr_to_tree (block, clauses->gang_num_expr);
3556 OMP_CLAUSE_GANG_EXPR (c) = arg;
3557 }
3558 if (clauses->gang_static)
3559 {
3560 arg = clauses->gang_static_expr
3561 ? gfc_convert_expr_to_tree (block, clauses->gang_static_expr)
3562 : integer_minus_one_node;
3563 OMP_CLAUSE_GANG_STATIC_EXPR (c) = arg;
3564 }
3565 }
3566
3567 return nreverse (omp_clauses);
3568 }
3569
3570 /* Like gfc_trans_code, but force creation of a BIND_EXPR around it. */
3571
3572 static tree
3573 gfc_trans_omp_code (gfc_code *code, bool force_empty)
3574 {
3575 tree stmt;
3576
3577 pushlevel ();
3578 stmt = gfc_trans_code (code);
3579 if (TREE_CODE (stmt) != BIND_EXPR)
3580 {
3581 if (!IS_EMPTY_STMT (stmt) || force_empty)
3582 {
3583 tree block = poplevel (1, 0);
3584 stmt = build3_v (BIND_EXPR, NULL, stmt, block);
3585 }
3586 else
3587 poplevel (0, 0);
3588 }
3589 else
3590 poplevel (0, 0);
3591 return stmt;
3592 }
3593
3594 /* Translate OpenACC 'parallel', 'kernels', 'serial', 'data', 'host_data'
3595 construct. */
3596
3597 static tree
3598 gfc_trans_oacc_construct (gfc_code *code)
3599 {
3600 stmtblock_t block;
3601 tree stmt, oacc_clauses;
3602 enum tree_code construct_code;
3603
3604 switch (code->op)
3605 {
3606 case EXEC_OACC_PARALLEL:
3607 construct_code = OACC_PARALLEL;
3608 break;
3609 case EXEC_OACC_KERNELS:
3610 construct_code = OACC_KERNELS;
3611 break;
3612 case EXEC_OACC_SERIAL:
3613 construct_code = OACC_SERIAL;
3614 break;
3615 case EXEC_OACC_DATA:
3616 construct_code = OACC_DATA;
3617 break;
3618 case EXEC_OACC_HOST_DATA:
3619 construct_code = OACC_HOST_DATA;
3620 break;
3621 default:
3622 gcc_unreachable ();
3623 }
3624
3625 gfc_start_block (&block);
3626 oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
3627 code->loc);
3628 stmt = gfc_trans_omp_code (code->block->next, true);
3629 stmt = build2_loc (input_location, construct_code, void_type_node, stmt,
3630 oacc_clauses);
3631 gfc_add_expr_to_block (&block, stmt);
3632 return gfc_finish_block (&block);
3633 }
3634
3635 /* update, enter_data, exit_data, cache. */
3636 static tree
3637 gfc_trans_oacc_executable_directive (gfc_code *code)
3638 {
3639 stmtblock_t block;
3640 tree stmt, oacc_clauses;
3641 enum tree_code construct_code;
3642
3643 switch (code->op)
3644 {
3645 case EXEC_OACC_UPDATE:
3646 construct_code = OACC_UPDATE;
3647 break;
3648 case EXEC_OACC_ENTER_DATA:
3649 construct_code = OACC_ENTER_DATA;
3650 break;
3651 case EXEC_OACC_EXIT_DATA:
3652 construct_code = OACC_EXIT_DATA;
3653 break;
3654 case EXEC_OACC_CACHE:
3655 construct_code = OACC_CACHE;
3656 break;
3657 default:
3658 gcc_unreachable ();
3659 }
3660
3661 gfc_start_block (&block);
3662 oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
3663 code->loc);
3664 stmt = build1_loc (input_location, construct_code, void_type_node,
3665 oacc_clauses);
3666 gfc_add_expr_to_block (&block, stmt);
3667 return gfc_finish_block (&block);
3668 }
3669
3670 static tree
3671 gfc_trans_oacc_wait_directive (gfc_code *code)
3672 {
3673 stmtblock_t block;
3674 tree stmt, t;
3675 vec<tree, va_gc> *args;
3676 int nparms = 0;
3677 gfc_expr_list *el;
3678 gfc_omp_clauses *clauses = code->ext.omp_clauses;
3679 location_t loc = input_location;
3680
3681 for (el = clauses->wait_list; el; el = el->next)
3682 nparms++;
3683
3684 vec_alloc (args, nparms + 2);
3685 stmt = builtin_decl_explicit (BUILT_IN_GOACC_WAIT);
3686
3687 gfc_start_block (&block);
3688
3689 if (clauses->async_expr)
3690 t = gfc_convert_expr_to_tree (&block, clauses->async_expr);
3691 else
3692 t = build_int_cst (integer_type_node, -2);
3693
3694 args->quick_push (t);
3695 args->quick_push (build_int_cst (integer_type_node, nparms));
3696
3697 for (el = clauses->wait_list; el; el = el->next)
3698 args->quick_push (gfc_convert_expr_to_tree (&block, el->expr));
3699
3700 stmt = build_call_expr_loc_vec (loc, stmt, args);
3701 gfc_add_expr_to_block (&block, stmt);
3702
3703 vec_free (args);
3704
3705 return gfc_finish_block (&block);
3706 }
3707
3708 static tree gfc_trans_omp_sections (gfc_code *, gfc_omp_clauses *);
3709 static tree gfc_trans_omp_workshare (gfc_code *, gfc_omp_clauses *);
3710
3711 static tree
3712 gfc_trans_omp_atomic (gfc_code *code)
3713 {
3714 gfc_code *atomic_code = code;
3715 gfc_se lse;
3716 gfc_se rse;
3717 gfc_se vse;
3718 gfc_expr *expr2, *e;
3719 gfc_symbol *var;
3720 stmtblock_t block;
3721 tree lhsaddr, type, rhs, x;
3722 enum tree_code op = ERROR_MARK;
3723 enum tree_code aop = OMP_ATOMIC;
3724 bool var_on_left = false;
3725 enum omp_memory_order mo
3726 = ((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SEQ_CST)
3727 ? OMP_MEMORY_ORDER_SEQ_CST : OMP_MEMORY_ORDER_RELAXED);
3728
3729 code = code->block->next;
3730 gcc_assert (code->op == EXEC_ASSIGN);
3731 var = code->expr1->symtree->n.sym;
3732
3733 gfc_init_se (&lse, NULL);
3734 gfc_init_se (&rse, NULL);
3735 gfc_init_se (&vse, NULL);
3736 gfc_start_block (&block);
3737
3738 expr2 = code->expr2;
3739 if (((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
3740 != GFC_OMP_ATOMIC_WRITE)
3741 && expr2->expr_type == EXPR_FUNCTION
3742 && expr2->value.function.isym
3743 && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
3744 expr2 = expr2->value.function.actual->expr;
3745
3746 switch (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
3747 {
3748 case GFC_OMP_ATOMIC_READ:
3749 gfc_conv_expr (&vse, code->expr1);
3750 gfc_add_block_to_block (&block, &vse.pre);
3751
3752 gfc_conv_expr (&lse, expr2);
3753 gfc_add_block_to_block (&block, &lse.pre);
3754 type = TREE_TYPE (lse.expr);
3755 lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
3756
3757 x = build1 (OMP_ATOMIC_READ, type, lhsaddr);
3758 OMP_ATOMIC_MEMORY_ORDER (x) = mo;
3759 x = convert (TREE_TYPE (vse.expr), x);
3760 gfc_add_modify (&block, vse.expr, x);
3761
3762 gfc_add_block_to_block (&block, &lse.pre);
3763 gfc_add_block_to_block (&block, &rse.pre);
3764
3765 return gfc_finish_block (&block);
3766 case GFC_OMP_ATOMIC_CAPTURE:
3767 aop = OMP_ATOMIC_CAPTURE_NEW;
3768 if (expr2->expr_type == EXPR_VARIABLE)
3769 {
3770 aop = OMP_ATOMIC_CAPTURE_OLD;
3771 gfc_conv_expr (&vse, code->expr1);
3772 gfc_add_block_to_block (&block, &vse.pre);
3773
3774 gfc_conv_expr (&lse, expr2);
3775 gfc_add_block_to_block (&block, &lse.pre);
3776 gfc_init_se (&lse, NULL);
3777 code = code->next;
3778 var = code->expr1->symtree->n.sym;
3779 expr2 = code->expr2;
3780 if (expr2->expr_type == EXPR_FUNCTION
3781 && expr2->value.function.isym
3782 && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
3783 expr2 = expr2->value.function.actual->expr;
3784 }
3785 break;
3786 default:
3787 break;
3788 }
3789
3790 gfc_conv_expr (&lse, code->expr1);
3791 gfc_add_block_to_block (&block, &lse.pre);
3792 type = TREE_TYPE (lse.expr);
3793 lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
3794
3795 if (((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
3796 == GFC_OMP_ATOMIC_WRITE)
3797 || (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SWAP))
3798 {
3799 gfc_conv_expr (&rse, expr2);
3800 gfc_add_block_to_block (&block, &rse.pre);
3801 }
3802 else if (expr2->expr_type == EXPR_OP)
3803 {
3804 gfc_expr *e;
3805 switch (expr2->value.op.op)
3806 {
3807 case INTRINSIC_PLUS:
3808 op = PLUS_EXPR;
3809 break;
3810 case INTRINSIC_TIMES:
3811 op = MULT_EXPR;
3812 break;
3813 case INTRINSIC_MINUS:
3814 op = MINUS_EXPR;
3815 break;
3816 case INTRINSIC_DIVIDE:
3817 if (expr2->ts.type == BT_INTEGER)
3818 op = TRUNC_DIV_EXPR;
3819 else
3820 op = RDIV_EXPR;
3821 break;
3822 case INTRINSIC_AND:
3823 op = TRUTH_ANDIF_EXPR;
3824 break;
3825 case INTRINSIC_OR:
3826 op = TRUTH_ORIF_EXPR;
3827 break;
3828 case INTRINSIC_EQV:
3829 op = EQ_EXPR;
3830 break;
3831 case INTRINSIC_NEQV:
3832 op = NE_EXPR;
3833 break;
3834 default:
3835 gcc_unreachable ();
3836 }
3837 e = expr2->value.op.op1;
3838 if (e->expr_type == EXPR_FUNCTION
3839 && e->value.function.isym
3840 && e->value.function.isym->id == GFC_ISYM_CONVERSION)
3841 e = e->value.function.actual->expr;
3842 if (e->expr_type == EXPR_VARIABLE
3843 && e->symtree != NULL
3844 && e->symtree->n.sym == var)
3845 {
3846 expr2 = expr2->value.op.op2;
3847 var_on_left = true;
3848 }
3849 else
3850 {
3851 e = expr2->value.op.op2;
3852 if (e->expr_type == EXPR_FUNCTION
3853 && e->value.function.isym
3854 && e->value.function.isym->id == GFC_ISYM_CONVERSION)
3855 e = e->value.function.actual->expr;
3856 gcc_assert (e->expr_type == EXPR_VARIABLE
3857 && e->symtree != NULL
3858 && e->symtree->n.sym == var);
3859 expr2 = expr2->value.op.op1;
3860 var_on_left = false;
3861 }
3862 gfc_conv_expr (&rse, expr2);
3863 gfc_add_block_to_block (&block, &rse.pre);
3864 }
3865 else
3866 {
3867 gcc_assert (expr2->expr_type == EXPR_FUNCTION);
3868 switch (expr2->value.function.isym->id)
3869 {
3870 case GFC_ISYM_MIN:
3871 op = MIN_EXPR;
3872 break;
3873 case GFC_ISYM_MAX:
3874 op = MAX_EXPR;
3875 break;
3876 case GFC_ISYM_IAND:
3877 op = BIT_AND_EXPR;
3878 break;
3879 case GFC_ISYM_IOR:
3880 op = BIT_IOR_EXPR;
3881 break;
3882 case GFC_ISYM_IEOR:
3883 op = BIT_XOR_EXPR;
3884 break;
3885 default:
3886 gcc_unreachable ();
3887 }
3888 e = expr2->value.function.actual->expr;
3889 gcc_assert (e->expr_type == EXPR_VARIABLE
3890 && e->symtree != NULL
3891 && e->symtree->n.sym == var);
3892
3893 gfc_conv_expr (&rse, expr2->value.function.actual->next->expr);
3894 gfc_add_block_to_block (&block, &rse.pre);
3895 if (expr2->value.function.actual->next->next != NULL)
3896 {
3897 tree accum = gfc_create_var (TREE_TYPE (rse.expr), NULL);
3898 gfc_actual_arglist *arg;
3899
3900 gfc_add_modify (&block, accum, rse.expr);
3901 for (arg = expr2->value.function.actual->next->next; arg;
3902 arg = arg->next)
3903 {
3904 gfc_init_block (&rse.pre);
3905 gfc_conv_expr (&rse, arg->expr);
3906 gfc_add_block_to_block (&block, &rse.pre);
3907 x = fold_build2_loc (input_location, op, TREE_TYPE (accum),
3908 accum, rse.expr);
3909 gfc_add_modify (&block, accum, x);
3910 }
3911
3912 rse.expr = accum;
3913 }
3914
3915 expr2 = expr2->value.function.actual->next->expr;
3916 }
3917
3918 lhsaddr = save_expr (lhsaddr);
3919 if (TREE_CODE (lhsaddr) != SAVE_EXPR
3920 && (TREE_CODE (lhsaddr) != ADDR_EXPR
3921 || !VAR_P (TREE_OPERAND (lhsaddr, 0))))
3922 {
3923 /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
3924 it even after unsharing function body. */
3925 tree var = create_tmp_var_raw (TREE_TYPE (lhsaddr));
3926 DECL_CONTEXT (var) = current_function_decl;
3927 lhsaddr = build4 (TARGET_EXPR, TREE_TYPE (lhsaddr), var, lhsaddr,
3928 NULL_TREE, NULL_TREE);
3929 }
3930
3931 rhs = gfc_evaluate_now (rse.expr, &block);
3932
3933 if (((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
3934 == GFC_OMP_ATOMIC_WRITE)
3935 || (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SWAP))
3936 x = rhs;
3937 else
3938 {
3939 x = convert (TREE_TYPE (rhs),
3940 build_fold_indirect_ref_loc (input_location, lhsaddr));
3941 if (var_on_left)
3942 x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), x, rhs);
3943 else
3944 x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), rhs, x);
3945 }
3946
3947 if (TREE_CODE (TREE_TYPE (rhs)) == COMPLEX_TYPE
3948 && TREE_CODE (type) != COMPLEX_TYPE)
3949 x = fold_build1_loc (input_location, REALPART_EXPR,
3950 TREE_TYPE (TREE_TYPE (rhs)), x);
3951
3952 gfc_add_block_to_block (&block, &lse.pre);
3953 gfc_add_block_to_block (&block, &rse.pre);
3954
3955 if (aop == OMP_ATOMIC)
3956 {
3957 x = build2_v (OMP_ATOMIC, lhsaddr, convert (type, x));
3958 OMP_ATOMIC_MEMORY_ORDER (x) = mo;
3959 gfc_add_expr_to_block (&block, x);
3960 }
3961 else
3962 {
3963 if (aop == OMP_ATOMIC_CAPTURE_NEW)
3964 {
3965 code = code->next;
3966 expr2 = code->expr2;
3967 if (expr2->expr_type == EXPR_FUNCTION
3968 && expr2->value.function.isym
3969 && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
3970 expr2 = expr2->value.function.actual->expr;
3971
3972 gcc_assert (expr2->expr_type == EXPR_VARIABLE);
3973 gfc_conv_expr (&vse, code->expr1);
3974 gfc_add_block_to_block (&block, &vse.pre);
3975
3976 gfc_init_se (&lse, NULL);
3977 gfc_conv_expr (&lse, expr2);
3978 gfc_add_block_to_block (&block, &lse.pre);
3979 }
3980 x = build2 (aop, type, lhsaddr, convert (type, x));
3981 OMP_ATOMIC_MEMORY_ORDER (x) = mo;
3982 x = convert (TREE_TYPE (vse.expr), x);
3983 gfc_add_modify (&block, vse.expr, x);
3984 }
3985
3986 return gfc_finish_block (&block);
3987 }
3988
3989 static tree
3990 gfc_trans_omp_barrier (void)
3991 {
3992 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
3993 return build_call_expr_loc (input_location, decl, 0);
3994 }
3995
3996 static tree
3997 gfc_trans_omp_cancel (gfc_code *code)
3998 {
3999 int mask = 0;
4000 tree ifc = boolean_true_node;
4001 stmtblock_t block;
4002 switch (code->ext.omp_clauses->cancel)
4003 {
4004 case OMP_CANCEL_PARALLEL: mask = 1; break;
4005 case OMP_CANCEL_DO: mask = 2; break;
4006 case OMP_CANCEL_SECTIONS: mask = 4; break;
4007 case OMP_CANCEL_TASKGROUP: mask = 8; break;
4008 default: gcc_unreachable ();
4009 }
4010 gfc_start_block (&block);
4011 if (code->ext.omp_clauses->if_expr)
4012 {
4013 gfc_se se;
4014 tree if_var;
4015
4016 gfc_init_se (&se, NULL);
4017 gfc_conv_expr (&se, code->ext.omp_clauses->if_expr);
4018 gfc_add_block_to_block (&block, &se.pre);
4019 if_var = gfc_evaluate_now (se.expr, &block);
4020 gfc_add_block_to_block (&block, &se.post);
4021 tree type = TREE_TYPE (if_var);
4022 ifc = fold_build2_loc (input_location, NE_EXPR,
4023 boolean_type_node, if_var,
4024 build_zero_cst (type));
4025 }
4026 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
4027 tree c_bool_type = TREE_TYPE (TREE_TYPE (decl));
4028 ifc = fold_convert (c_bool_type, ifc);
4029 gfc_add_expr_to_block (&block,
4030 build_call_expr_loc (input_location, decl, 2,
4031 build_int_cst (integer_type_node,
4032 mask), ifc));
4033 return gfc_finish_block (&block);
4034 }
4035
4036 static tree
4037 gfc_trans_omp_cancellation_point (gfc_code *code)
4038 {
4039 int mask = 0;
4040 switch (code->ext.omp_clauses->cancel)
4041 {
4042 case OMP_CANCEL_PARALLEL: mask = 1; break;
4043 case OMP_CANCEL_DO: mask = 2; break;
4044 case OMP_CANCEL_SECTIONS: mask = 4; break;
4045 case OMP_CANCEL_TASKGROUP: mask = 8; break;
4046 default: gcc_unreachable ();
4047 }
4048 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCELLATION_POINT);
4049 return build_call_expr_loc (input_location, decl, 1,
4050 build_int_cst (integer_type_node, mask));
4051 }
4052
4053 static tree
4054 gfc_trans_omp_critical (gfc_code *code)
4055 {
4056 tree name = NULL_TREE, stmt;
4057 if (code->ext.omp_clauses != NULL)
4058 name = get_identifier (code->ext.omp_clauses->critical_name);
4059 stmt = gfc_trans_code (code->block->next);
4060 return build3_loc (input_location, OMP_CRITICAL, void_type_node, stmt,
4061 NULL_TREE, name);
4062 }
4063
4064 typedef struct dovar_init_d {
4065 tree var;
4066 tree init;
4067 } dovar_init;
4068
4069
4070 static tree
4071 gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
4072 gfc_omp_clauses *do_clauses, tree par_clauses)
4073 {
4074 gfc_se se;
4075 tree dovar, stmt, from, to, step, type, init, cond, incr, orig_decls;
4076 tree count = NULL_TREE, cycle_label, tmp, omp_clauses;
4077 stmtblock_t block;
4078 stmtblock_t body;
4079 gfc_omp_clauses *clauses = code->ext.omp_clauses;
4080 int i, collapse = clauses->collapse;
4081 vec<dovar_init> inits = vNULL;
4082 dovar_init *di;
4083 unsigned ix;
4084 vec<tree, va_heap, vl_embed> *saved_doacross_steps = doacross_steps;
4085 gfc_expr_list *tile = do_clauses ? do_clauses->tile_list : clauses->tile_list;
4086
4087 /* Both collapsed and tiled loops are lowered the same way. In
4088 OpenACC, those clauses are not compatible, so prioritize the tile
4089 clause, if present. */
4090 if (tile)
4091 {
4092 collapse = 0;
4093 for (gfc_expr_list *el = tile; el; el = el->next)
4094 collapse++;
4095 }
4096
4097 doacross_steps = NULL;
4098 if (clauses->orderedc)
4099 collapse = clauses->orderedc;
4100 if (collapse <= 0)
4101 collapse = 1;
4102
4103 code = code->block->next;
4104 gcc_assert (code->op == EXEC_DO);
4105
4106 init = make_tree_vec (collapse);
4107 cond = make_tree_vec (collapse);
4108 incr = make_tree_vec (collapse);
4109 orig_decls = clauses->orderedc ? make_tree_vec (collapse) : NULL_TREE;
4110
4111 if (pblock == NULL)
4112 {
4113 gfc_start_block (&block);
4114 pblock = &block;
4115 }
4116
4117 /* simd schedule modifier is only useful for composite do simd and other
4118 constructs including that, where gfc_trans_omp_do is only called
4119 on the simd construct and DO's clauses are translated elsewhere. */
4120 do_clauses->sched_simd = false;
4121
4122 omp_clauses = gfc_trans_omp_clauses (pblock, do_clauses, code->loc);
4123
4124 for (i = 0; i < collapse; i++)
4125 {
4126 int simple = 0;
4127 int dovar_found = 0;
4128 tree dovar_decl;
4129
4130 if (clauses)
4131 {
4132 gfc_omp_namelist *n = NULL;
4133 if (op != EXEC_OMP_DISTRIBUTE)
4134 for (n = clauses->lists[(op == EXEC_OMP_SIMD && collapse == 1)
4135 ? OMP_LIST_LINEAR : OMP_LIST_LASTPRIVATE];
4136 n != NULL; n = n->next)
4137 if (code->ext.iterator->var->symtree->n.sym == n->sym)
4138 break;
4139 if (n != NULL)
4140 dovar_found = 1;
4141 else if (n == NULL && op != EXEC_OMP_SIMD)
4142 for (n = clauses->lists[OMP_LIST_PRIVATE]; n != NULL; n = n->next)
4143 if (code->ext.iterator->var->symtree->n.sym == n->sym)
4144 break;
4145 if (n != NULL)
4146 dovar_found++;
4147 }
4148
4149 /* Evaluate all the expressions in the iterator. */
4150 gfc_init_se (&se, NULL);
4151 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
4152 gfc_add_block_to_block (pblock, &se.pre);
4153 dovar = se.expr;
4154 type = TREE_TYPE (dovar);
4155 gcc_assert (TREE_CODE (type) == INTEGER_TYPE);
4156
4157 gfc_init_se (&se, NULL);
4158 gfc_conv_expr_val (&se, code->ext.iterator->start);
4159 gfc_add_block_to_block (pblock, &se.pre);
4160 from = gfc_evaluate_now (se.expr, pblock);
4161
4162 gfc_init_se (&se, NULL);
4163 gfc_conv_expr_val (&se, code->ext.iterator->end);
4164 gfc_add_block_to_block (pblock, &se.pre);
4165 to = gfc_evaluate_now (se.expr, pblock);
4166
4167 gfc_init_se (&se, NULL);
4168 gfc_conv_expr_val (&se, code->ext.iterator->step);
4169 gfc_add_block_to_block (pblock, &se.pre);
4170 step = gfc_evaluate_now (se.expr, pblock);
4171 dovar_decl = dovar;
4172
4173 /* Special case simple loops. */
4174 if (VAR_P (dovar))
4175 {
4176 if (integer_onep (step))
4177 simple = 1;
4178 else if (tree_int_cst_equal (step, integer_minus_one_node))
4179 simple = -1;
4180 }
4181 else
4182 dovar_decl
4183 = gfc_trans_omp_variable (code->ext.iterator->var->symtree->n.sym,
4184 false);
4185
4186 /* Loop body. */
4187 if (simple)
4188 {
4189 TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, dovar, from);
4190 /* The condition should not be folded. */
4191 TREE_VEC_ELT (cond, i) = build2_loc (input_location, simple > 0
4192 ? LE_EXPR : GE_EXPR,
4193 logical_type_node, dovar, to);
4194 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR,
4195 type, dovar, step);
4196 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location,
4197 MODIFY_EXPR,
4198 type, dovar,
4199 TREE_VEC_ELT (incr, i));
4200 }
4201 else
4202 {
4203 /* STEP is not 1 or -1. Use:
4204 for (count = 0; count < (to + step - from) / step; count++)
4205 {
4206 dovar = from + count * step;
4207 body;
4208 cycle_label:;
4209 } */
4210 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, step, from);
4211 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, to, tmp);
4212 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, type, tmp,
4213 step);
4214 tmp = gfc_evaluate_now (tmp, pblock);
4215 count = gfc_create_var (type, "count");
4216 TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, count,
4217 build_int_cst (type, 0));
4218 /* The condition should not be folded. */
4219 TREE_VEC_ELT (cond, i) = build2_loc (input_location, LT_EXPR,
4220 logical_type_node,
4221 count, tmp);
4222 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR,
4223 type, count,
4224 build_int_cst (type, 1));
4225 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location,
4226 MODIFY_EXPR, type, count,
4227 TREE_VEC_ELT (incr, i));
4228
4229 /* Initialize DOVAR. */
4230 tmp = fold_build2_loc (input_location, MULT_EXPR, type, count, step);
4231 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, from, tmp);
4232 dovar_init e = {dovar, tmp};
4233 inits.safe_push (e);
4234 if (clauses->orderedc)
4235 {
4236 if (doacross_steps == NULL)
4237 vec_safe_grow_cleared (doacross_steps, clauses->orderedc);
4238 (*doacross_steps)[i] = step;
4239 }
4240 }
4241 if (orig_decls)
4242 TREE_VEC_ELT (orig_decls, i) = dovar_decl;
4243
4244 if (dovar_found == 2
4245 && op == EXEC_OMP_SIMD
4246 && collapse == 1
4247 && !simple)
4248 {
4249 for (tmp = omp_clauses; tmp; tmp = OMP_CLAUSE_CHAIN (tmp))
4250 if (OMP_CLAUSE_CODE (tmp) == OMP_CLAUSE_LINEAR
4251 && OMP_CLAUSE_DECL (tmp) == dovar)
4252 {
4253 OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
4254 break;
4255 }
4256 }
4257 if (!dovar_found)
4258 {
4259 if (op == EXEC_OMP_SIMD)
4260 {
4261 if (collapse == 1)
4262 {
4263 tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
4264 OMP_CLAUSE_LINEAR_STEP (tmp) = step;
4265 OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
4266 }
4267 else
4268 tmp = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
4269 if (!simple)
4270 dovar_found = 2;
4271 }
4272 else
4273 tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
4274 OMP_CLAUSE_DECL (tmp) = dovar_decl;
4275 omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
4276 }
4277 if (dovar_found == 2)
4278 {
4279 tree c = NULL;
4280
4281 tmp = NULL;
4282 if (!simple)
4283 {
4284 /* If dovar is lastprivate, but different counter is used,
4285 dovar += step needs to be added to
4286 OMP_CLAUSE_LASTPRIVATE_STMT, otherwise the copied dovar
4287 will have the value on entry of the last loop, rather
4288 than value after iterator increment. */
4289 if (clauses->orderedc)
4290 {
4291 if (clauses->collapse <= 1 || i >= clauses->collapse)
4292 tmp = count;
4293 else
4294 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4295 type, count, build_one_cst (type));
4296 tmp = fold_build2_loc (input_location, MULT_EXPR, type,
4297 tmp, step);
4298 tmp = fold_build2_loc (input_location, PLUS_EXPR, type,
4299 from, tmp);
4300 }
4301 else
4302 {
4303 tmp = gfc_evaluate_now (step, pblock);
4304 tmp = fold_build2_loc (input_location, PLUS_EXPR, type,
4305 dovar, tmp);
4306 }
4307 tmp = fold_build2_loc (input_location, MODIFY_EXPR, type,
4308 dovar, tmp);
4309 for (c = omp_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4310 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4311 && OMP_CLAUSE_DECL (c) == dovar_decl)
4312 {
4313 OMP_CLAUSE_LASTPRIVATE_STMT (c) = tmp;
4314 break;
4315 }
4316 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4317 && OMP_CLAUSE_DECL (c) == dovar_decl)
4318 {
4319 OMP_CLAUSE_LINEAR_STMT (c) = tmp;
4320 break;
4321 }
4322 }
4323 if (c == NULL && op == EXEC_OMP_DO && par_clauses != NULL)
4324 {
4325 for (c = par_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4326 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4327 && OMP_CLAUSE_DECL (c) == dovar_decl)
4328 {
4329 tree l = build_omp_clause (input_location,
4330 OMP_CLAUSE_LASTPRIVATE);
4331 OMP_CLAUSE_DECL (l) = dovar_decl;
4332 OMP_CLAUSE_CHAIN (l) = omp_clauses;
4333 OMP_CLAUSE_LASTPRIVATE_STMT (l) = tmp;
4334 omp_clauses = l;
4335 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_SHARED);
4336 break;
4337 }
4338 }
4339 gcc_assert (simple || c != NULL);
4340 }
4341 if (!simple)
4342 {
4343 if (op != EXEC_OMP_SIMD)
4344 tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
4345 else if (collapse == 1)
4346 {
4347 tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
4348 OMP_CLAUSE_LINEAR_STEP (tmp) = build_int_cst (type, 1);
4349 OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
4350 OMP_CLAUSE_LINEAR_NO_COPYOUT (tmp) = 1;
4351 }
4352 else
4353 tmp = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
4354 OMP_CLAUSE_DECL (tmp) = count;
4355 omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
4356 }
4357
4358 if (i + 1 < collapse)
4359 code = code->block->next;
4360 }
4361
4362 if (pblock != &block)
4363 {
4364 pushlevel ();
4365 gfc_start_block (&block);
4366 }
4367
4368 gfc_start_block (&body);
4369
4370 FOR_EACH_VEC_ELT (inits, ix, di)
4371 gfc_add_modify (&body, di->var, di->init);
4372 inits.release ();
4373
4374 /* Cycle statement is implemented with a goto. Exit statement must not be
4375 present for this loop. */
4376 cycle_label = gfc_build_label_decl (NULL_TREE);
4377
4378 /* Put these labels where they can be found later. */
4379
4380 code->cycle_label = cycle_label;
4381 code->exit_label = NULL_TREE;
4382
4383 /* Main loop body. */
4384 tmp = gfc_trans_omp_code (code->block->next, true);
4385 gfc_add_expr_to_block (&body, tmp);
4386
4387 /* Label for cycle statements (if needed). */
4388 if (TREE_USED (cycle_label))
4389 {
4390 tmp = build1_v (LABEL_EXPR, cycle_label);
4391 gfc_add_expr_to_block (&body, tmp);
4392 }
4393
4394 /* End of loop body. */
4395 switch (op)
4396 {
4397 case EXEC_OMP_SIMD: stmt = make_node (OMP_SIMD); break;
4398 case EXEC_OMP_DO: stmt = make_node (OMP_FOR); break;
4399 case EXEC_OMP_DISTRIBUTE: stmt = make_node (OMP_DISTRIBUTE); break;
4400 case EXEC_OMP_TASKLOOP: stmt = make_node (OMP_TASKLOOP); break;
4401 case EXEC_OACC_LOOP: stmt = make_node (OACC_LOOP); break;
4402 default: gcc_unreachable ();
4403 }
4404
4405 TREE_TYPE (stmt) = void_type_node;
4406 OMP_FOR_BODY (stmt) = gfc_finish_block (&body);
4407 OMP_FOR_CLAUSES (stmt) = omp_clauses;
4408 OMP_FOR_INIT (stmt) = init;
4409 OMP_FOR_COND (stmt) = cond;
4410 OMP_FOR_INCR (stmt) = incr;
4411 if (orig_decls)
4412 OMP_FOR_ORIG_DECLS (stmt) = orig_decls;
4413 gfc_add_expr_to_block (&block, stmt);
4414
4415 vec_free (doacross_steps);
4416 doacross_steps = saved_doacross_steps;
4417
4418 return gfc_finish_block (&block);
4419 }
4420
4421 /* Translate combined OpenACC 'parallel loop', 'kernels loop', 'serial loop'
4422 construct. */
4423
4424 static tree
4425 gfc_trans_oacc_combined_directive (gfc_code *code)
4426 {
4427 stmtblock_t block, *pblock = NULL;
4428 gfc_omp_clauses construct_clauses, loop_clauses;
4429 tree stmt, oacc_clauses = NULL_TREE;
4430 enum tree_code construct_code;
4431 location_t loc = input_location;
4432
4433 switch (code->op)
4434 {
4435 case EXEC_OACC_PARALLEL_LOOP:
4436 construct_code = OACC_PARALLEL;
4437 break;
4438 case EXEC_OACC_KERNELS_LOOP:
4439 construct_code = OACC_KERNELS;
4440 break;
4441 case EXEC_OACC_SERIAL_LOOP:
4442 construct_code = OACC_SERIAL;
4443 break;
4444 default:
4445 gcc_unreachable ();
4446 }
4447
4448 gfc_start_block (&block);
4449
4450 memset (&loop_clauses, 0, sizeof (loop_clauses));
4451 if (code->ext.omp_clauses != NULL)
4452 {
4453 memcpy (&construct_clauses, code->ext.omp_clauses,
4454 sizeof (construct_clauses));
4455 loop_clauses.collapse = construct_clauses.collapse;
4456 loop_clauses.gang = construct_clauses.gang;
4457 loop_clauses.gang_static = construct_clauses.gang_static;
4458 loop_clauses.gang_num_expr = construct_clauses.gang_num_expr;
4459 loop_clauses.gang_static_expr = construct_clauses.gang_static_expr;
4460 loop_clauses.vector = construct_clauses.vector;
4461 loop_clauses.vector_expr = construct_clauses.vector_expr;
4462 loop_clauses.worker = construct_clauses.worker;
4463 loop_clauses.worker_expr = construct_clauses.worker_expr;
4464 loop_clauses.seq = construct_clauses.seq;
4465 loop_clauses.par_auto = construct_clauses.par_auto;
4466 loop_clauses.independent = construct_clauses.independent;
4467 loop_clauses.tile_list = construct_clauses.tile_list;
4468 loop_clauses.lists[OMP_LIST_PRIVATE]
4469 = construct_clauses.lists[OMP_LIST_PRIVATE];
4470 loop_clauses.lists[OMP_LIST_REDUCTION]
4471 = construct_clauses.lists[OMP_LIST_REDUCTION];
4472 construct_clauses.gang = false;
4473 construct_clauses.gang_static = false;
4474 construct_clauses.gang_num_expr = NULL;
4475 construct_clauses.gang_static_expr = NULL;
4476 construct_clauses.vector = false;
4477 construct_clauses.vector_expr = NULL;
4478 construct_clauses.worker = false;
4479 construct_clauses.worker_expr = NULL;
4480 construct_clauses.seq = false;
4481 construct_clauses.par_auto = false;
4482 construct_clauses.independent = false;
4483 construct_clauses.independent = false;
4484 construct_clauses.tile_list = NULL;
4485 construct_clauses.lists[OMP_LIST_PRIVATE] = NULL;
4486 if (construct_code == OACC_KERNELS)
4487 construct_clauses.lists[OMP_LIST_REDUCTION] = NULL;
4488 oacc_clauses = gfc_trans_omp_clauses (&block, &construct_clauses,
4489 code->loc);
4490 }
4491 if (!loop_clauses.seq)
4492 pblock = &block;
4493 else
4494 pushlevel ();
4495 stmt = gfc_trans_omp_do (code, EXEC_OACC_LOOP, pblock, &loop_clauses, NULL);
4496 protected_set_expr_location (stmt, loc);
4497 if (TREE_CODE (stmt) != BIND_EXPR)
4498 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
4499 else
4500 poplevel (0, 0);
4501 stmt = build2_loc (loc, construct_code, void_type_node, stmt, oacc_clauses);
4502 gfc_add_expr_to_block (&block, stmt);
4503 return gfc_finish_block (&block);
4504 }
4505
4506 static tree
4507 gfc_trans_omp_flush (void)
4508 {
4509 tree decl = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
4510 return build_call_expr_loc (input_location, decl, 0);
4511 }
4512
4513 static tree
4514 gfc_trans_omp_master (gfc_code *code)
4515 {
4516 tree stmt = gfc_trans_code (code->block->next);
4517 if (IS_EMPTY_STMT (stmt))
4518 return stmt;
4519 return build1_v (OMP_MASTER, stmt);
4520 }
4521
4522 static tree
4523 gfc_trans_omp_ordered (gfc_code *code)
4524 {
4525 if (!flag_openmp)
4526 {
4527 if (!code->ext.omp_clauses->simd)
4528 return gfc_trans_code (code->block ? code->block->next : NULL);
4529 code->ext.omp_clauses->threads = 0;
4530 }
4531 tree omp_clauses = gfc_trans_omp_clauses (NULL, code->ext.omp_clauses,
4532 code->loc);
4533 return build2_loc (input_location, OMP_ORDERED, void_type_node,
4534 code->block ? gfc_trans_code (code->block->next)
4535 : NULL_TREE, omp_clauses);
4536 }
4537
4538 static tree
4539 gfc_trans_omp_parallel (gfc_code *code)
4540 {
4541 stmtblock_t block;
4542 tree stmt, omp_clauses;
4543
4544 gfc_start_block (&block);
4545 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
4546 code->loc);
4547 pushlevel ();
4548 stmt = gfc_trans_omp_code (code->block->next, true);
4549 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
4550 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
4551 omp_clauses);
4552 gfc_add_expr_to_block (&block, stmt);
4553 return gfc_finish_block (&block);
4554 }
4555
4556 enum
4557 {
4558 GFC_OMP_SPLIT_SIMD,
4559 GFC_OMP_SPLIT_DO,
4560 GFC_OMP_SPLIT_PARALLEL,
4561 GFC_OMP_SPLIT_DISTRIBUTE,
4562 GFC_OMP_SPLIT_TEAMS,
4563 GFC_OMP_SPLIT_TARGET,
4564 GFC_OMP_SPLIT_TASKLOOP,
4565 GFC_OMP_SPLIT_NUM
4566 };
4567
4568 enum
4569 {
4570 GFC_OMP_MASK_SIMD = (1 << GFC_OMP_SPLIT_SIMD),
4571 GFC_OMP_MASK_DO = (1 << GFC_OMP_SPLIT_DO),
4572 GFC_OMP_MASK_PARALLEL = (1 << GFC_OMP_SPLIT_PARALLEL),
4573 GFC_OMP_MASK_DISTRIBUTE = (1 << GFC_OMP_SPLIT_DISTRIBUTE),
4574 GFC_OMP_MASK_TEAMS = (1 << GFC_OMP_SPLIT_TEAMS),
4575 GFC_OMP_MASK_TARGET = (1 << GFC_OMP_SPLIT_TARGET),
4576 GFC_OMP_MASK_TASKLOOP = (1 << GFC_OMP_SPLIT_TASKLOOP)
4577 };
4578
4579 static void
4580 gfc_split_omp_clauses (gfc_code *code,
4581 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM])
4582 {
4583 int mask = 0, innermost = 0;
4584 memset (clausesa, 0, GFC_OMP_SPLIT_NUM * sizeof (gfc_omp_clauses));
4585 switch (code->op)
4586 {
4587 case EXEC_OMP_DISTRIBUTE:
4588 innermost = GFC_OMP_SPLIT_DISTRIBUTE;
4589 break;
4590 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
4591 mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
4592 innermost = GFC_OMP_SPLIT_DO;
4593 break;
4594 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
4595 mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL
4596 | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
4597 innermost = GFC_OMP_SPLIT_SIMD;
4598 break;
4599 case EXEC_OMP_DISTRIBUTE_SIMD:
4600 mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
4601 innermost = GFC_OMP_SPLIT_SIMD;
4602 break;
4603 case EXEC_OMP_DO:
4604 innermost = GFC_OMP_SPLIT_DO;
4605 break;
4606 case EXEC_OMP_DO_SIMD:
4607 mask = GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
4608 innermost = GFC_OMP_SPLIT_SIMD;
4609 break;
4610 case EXEC_OMP_PARALLEL:
4611 innermost = GFC_OMP_SPLIT_PARALLEL;
4612 break;
4613 case EXEC_OMP_PARALLEL_DO:
4614 mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
4615 innermost = GFC_OMP_SPLIT_DO;
4616 break;
4617 case EXEC_OMP_PARALLEL_DO_SIMD:
4618 mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
4619 innermost = GFC_OMP_SPLIT_SIMD;
4620 break;
4621 case EXEC_OMP_SIMD:
4622 innermost = GFC_OMP_SPLIT_SIMD;
4623 break;
4624 case EXEC_OMP_TARGET:
4625 innermost = GFC_OMP_SPLIT_TARGET;
4626 break;
4627 case EXEC_OMP_TARGET_PARALLEL:
4628 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL;
4629 innermost = GFC_OMP_SPLIT_PARALLEL;
4630 break;
4631 case EXEC_OMP_TARGET_PARALLEL_DO:
4632 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
4633 innermost = GFC_OMP_SPLIT_DO;
4634 break;
4635 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
4636 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO
4637 | GFC_OMP_MASK_SIMD;
4638 innermost = GFC_OMP_SPLIT_SIMD;
4639 break;
4640 case EXEC_OMP_TARGET_SIMD:
4641 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_SIMD;
4642 innermost = GFC_OMP_SPLIT_SIMD;
4643 break;
4644 case EXEC_OMP_TARGET_TEAMS:
4645 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS;
4646 innermost = GFC_OMP_SPLIT_TEAMS;
4647 break;
4648 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
4649 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS
4650 | GFC_OMP_MASK_DISTRIBUTE;
4651 innermost = GFC_OMP_SPLIT_DISTRIBUTE;
4652 break;
4653 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
4654 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
4655 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
4656 innermost = GFC_OMP_SPLIT_DO;
4657 break;
4658 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
4659 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
4660 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
4661 innermost = GFC_OMP_SPLIT_SIMD;
4662 break;
4663 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
4664 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS
4665 | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
4666 innermost = GFC_OMP_SPLIT_SIMD;
4667 break;
4668 case EXEC_OMP_TASKLOOP:
4669 innermost = GFC_OMP_SPLIT_TASKLOOP;
4670 break;
4671 case EXEC_OMP_TASKLOOP_SIMD:
4672 mask = GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
4673 innermost = GFC_OMP_SPLIT_SIMD;
4674 break;
4675 case EXEC_OMP_TEAMS:
4676 innermost = GFC_OMP_SPLIT_TEAMS;
4677 break;
4678 case EXEC_OMP_TEAMS_DISTRIBUTE:
4679 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE;
4680 innermost = GFC_OMP_SPLIT_DISTRIBUTE;
4681 break;
4682 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
4683 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
4684 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
4685 innermost = GFC_OMP_SPLIT_DO;
4686 break;
4687 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
4688 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
4689 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
4690 innermost = GFC_OMP_SPLIT_SIMD;
4691 break;
4692 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
4693 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
4694 innermost = GFC_OMP_SPLIT_SIMD;
4695 break;
4696 default:
4697 gcc_unreachable ();
4698 }
4699 if (mask == 0)
4700 {
4701 clausesa[innermost] = *code->ext.omp_clauses;
4702 return;
4703 }
4704 if (code->ext.omp_clauses != NULL)
4705 {
4706 if (mask & GFC_OMP_MASK_TARGET)
4707 {
4708 /* First the clauses that are unique to some constructs. */
4709 clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_MAP]
4710 = code->ext.omp_clauses->lists[OMP_LIST_MAP];
4711 clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_IS_DEVICE_PTR]
4712 = code->ext.omp_clauses->lists[OMP_LIST_IS_DEVICE_PTR];
4713 clausesa[GFC_OMP_SPLIT_TARGET].device
4714 = code->ext.omp_clauses->device;
4715 clausesa[GFC_OMP_SPLIT_TARGET].defaultmap
4716 = code->ext.omp_clauses->defaultmap;
4717 clausesa[GFC_OMP_SPLIT_TARGET].if_exprs[OMP_IF_TARGET]
4718 = code->ext.omp_clauses->if_exprs[OMP_IF_TARGET];
4719 /* And this is copied to all. */
4720 clausesa[GFC_OMP_SPLIT_PARALLEL].if_expr
4721 = code->ext.omp_clauses->if_expr;
4722 }
4723 if (mask & GFC_OMP_MASK_TEAMS)
4724 {
4725 /* First the clauses that are unique to some constructs. */
4726 clausesa[GFC_OMP_SPLIT_TEAMS].num_teams
4727 = code->ext.omp_clauses->num_teams;
4728 clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit
4729 = code->ext.omp_clauses->thread_limit;
4730 /* Shared and default clauses are allowed on parallel, teams
4731 and taskloop. */
4732 clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_SHARED]
4733 = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
4734 clausesa[GFC_OMP_SPLIT_TEAMS].default_sharing
4735 = code->ext.omp_clauses->default_sharing;
4736 }
4737 if (mask & GFC_OMP_MASK_DISTRIBUTE)
4738 {
4739 /* First the clauses that are unique to some constructs. */
4740 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_sched_kind
4741 = code->ext.omp_clauses->dist_sched_kind;
4742 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_chunk_size
4743 = code->ext.omp_clauses->dist_chunk_size;
4744 /* Duplicate collapse. */
4745 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].collapse
4746 = code->ext.omp_clauses->collapse;
4747 }
4748 if (mask & GFC_OMP_MASK_PARALLEL)
4749 {
4750 /* First the clauses that are unique to some constructs. */
4751 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_COPYIN]
4752 = code->ext.omp_clauses->lists[OMP_LIST_COPYIN];
4753 clausesa[GFC_OMP_SPLIT_PARALLEL].num_threads
4754 = code->ext.omp_clauses->num_threads;
4755 clausesa[GFC_OMP_SPLIT_PARALLEL].proc_bind
4756 = code->ext.omp_clauses->proc_bind;
4757 /* Shared and default clauses are allowed on parallel, teams
4758 and taskloop. */
4759 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_SHARED]
4760 = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
4761 clausesa[GFC_OMP_SPLIT_PARALLEL].default_sharing
4762 = code->ext.omp_clauses->default_sharing;
4763 clausesa[GFC_OMP_SPLIT_PARALLEL].if_exprs[OMP_IF_PARALLEL]
4764 = code->ext.omp_clauses->if_exprs[OMP_IF_PARALLEL];
4765 /* And this is copied to all. */
4766 clausesa[GFC_OMP_SPLIT_PARALLEL].if_expr
4767 = code->ext.omp_clauses->if_expr;
4768 }
4769 if (mask & GFC_OMP_MASK_DO)
4770 {
4771 /* First the clauses that are unique to some constructs. */
4772 clausesa[GFC_OMP_SPLIT_DO].ordered
4773 = code->ext.omp_clauses->ordered;
4774 clausesa[GFC_OMP_SPLIT_DO].orderedc
4775 = code->ext.omp_clauses->orderedc;
4776 clausesa[GFC_OMP_SPLIT_DO].sched_kind
4777 = code->ext.omp_clauses->sched_kind;
4778 if (innermost == GFC_OMP_SPLIT_SIMD)
4779 clausesa[GFC_OMP_SPLIT_DO].sched_simd
4780 = code->ext.omp_clauses->sched_simd;
4781 clausesa[GFC_OMP_SPLIT_DO].sched_monotonic
4782 = code->ext.omp_clauses->sched_monotonic;
4783 clausesa[GFC_OMP_SPLIT_DO].sched_nonmonotonic
4784 = code->ext.omp_clauses->sched_nonmonotonic;
4785 clausesa[GFC_OMP_SPLIT_DO].chunk_size
4786 = code->ext.omp_clauses->chunk_size;
4787 clausesa[GFC_OMP_SPLIT_DO].nowait
4788 = code->ext.omp_clauses->nowait;
4789 /* Duplicate collapse. */
4790 clausesa[GFC_OMP_SPLIT_DO].collapse
4791 = code->ext.omp_clauses->collapse;
4792 }
4793 if (mask & GFC_OMP_MASK_SIMD)
4794 {
4795 clausesa[GFC_OMP_SPLIT_SIMD].safelen_expr
4796 = code->ext.omp_clauses->safelen_expr;
4797 clausesa[GFC_OMP_SPLIT_SIMD].simdlen_expr
4798 = code->ext.omp_clauses->simdlen_expr;
4799 clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_ALIGNED]
4800 = code->ext.omp_clauses->lists[OMP_LIST_ALIGNED];
4801 /* Duplicate collapse. */
4802 clausesa[GFC_OMP_SPLIT_SIMD].collapse
4803 = code->ext.omp_clauses->collapse;
4804 }
4805 if (mask & GFC_OMP_MASK_TASKLOOP)
4806 {
4807 /* First the clauses that are unique to some constructs. */
4808 clausesa[GFC_OMP_SPLIT_TASKLOOP].nogroup
4809 = code->ext.omp_clauses->nogroup;
4810 clausesa[GFC_OMP_SPLIT_TASKLOOP].grainsize
4811 = code->ext.omp_clauses->grainsize;
4812 clausesa[GFC_OMP_SPLIT_TASKLOOP].num_tasks
4813 = code->ext.omp_clauses->num_tasks;
4814 clausesa[GFC_OMP_SPLIT_TASKLOOP].priority
4815 = code->ext.omp_clauses->priority;
4816 clausesa[GFC_OMP_SPLIT_TASKLOOP].final_expr
4817 = code->ext.omp_clauses->final_expr;
4818 clausesa[GFC_OMP_SPLIT_TASKLOOP].untied
4819 = code->ext.omp_clauses->untied;
4820 clausesa[GFC_OMP_SPLIT_TASKLOOP].mergeable
4821 = code->ext.omp_clauses->mergeable;
4822 clausesa[GFC_OMP_SPLIT_TASKLOOP].if_exprs[OMP_IF_TASKLOOP]
4823 = code->ext.omp_clauses->if_exprs[OMP_IF_TASKLOOP];
4824 /* And this is copied to all. */
4825 clausesa[GFC_OMP_SPLIT_TASKLOOP].if_expr
4826 = code->ext.omp_clauses->if_expr;
4827 /* Shared and default clauses are allowed on parallel, teams
4828 and taskloop. */
4829 clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_SHARED]
4830 = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
4831 clausesa[GFC_OMP_SPLIT_TASKLOOP].default_sharing
4832 = code->ext.omp_clauses->default_sharing;
4833 /* Duplicate collapse. */
4834 clausesa[GFC_OMP_SPLIT_TASKLOOP].collapse
4835 = code->ext.omp_clauses->collapse;
4836 }
4837 /* Private clause is supported on all constructs,
4838 it is enough to put it on the innermost one. For
4839 !$ omp parallel do put it on parallel though,
4840 as that's what we did for OpenMP 3.1. */
4841 clausesa[innermost == GFC_OMP_SPLIT_DO
4842 ? (int) GFC_OMP_SPLIT_PARALLEL
4843 : innermost].lists[OMP_LIST_PRIVATE]
4844 = code->ext.omp_clauses->lists[OMP_LIST_PRIVATE];
4845 /* Firstprivate clause is supported on all constructs but
4846 simd. Put it on the outermost of those and duplicate
4847 on parallel and teams. */
4848 if (mask & GFC_OMP_MASK_TARGET)
4849 clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_FIRSTPRIVATE]
4850 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
4851 if (mask & GFC_OMP_MASK_TEAMS)
4852 clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_FIRSTPRIVATE]
4853 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
4854 else if (mask & GFC_OMP_MASK_DISTRIBUTE)
4855 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_FIRSTPRIVATE]
4856 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
4857 if (mask & GFC_OMP_MASK_PARALLEL)
4858 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_FIRSTPRIVATE]
4859 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
4860 else if (mask & GFC_OMP_MASK_DO)
4861 clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_FIRSTPRIVATE]
4862 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
4863 /* Lastprivate is allowed on distribute, do and simd.
4864 In parallel do{, simd} we actually want to put it on
4865 parallel rather than do. */
4866 if (mask & GFC_OMP_MASK_DISTRIBUTE)
4867 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_LASTPRIVATE]
4868 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
4869 if (mask & GFC_OMP_MASK_PARALLEL)
4870 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_LASTPRIVATE]
4871 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
4872 else if (mask & GFC_OMP_MASK_DO)
4873 clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_LASTPRIVATE]
4874 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
4875 if (mask & GFC_OMP_MASK_SIMD)
4876 clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_LASTPRIVATE]
4877 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
4878 /* Reduction is allowed on simd, do, parallel and teams.
4879 Duplicate it on all of them, but omit on do if
4880 parallel is present. */
4881 if (mask & GFC_OMP_MASK_TEAMS)
4882 clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_REDUCTION]
4883 = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
4884 if (mask & GFC_OMP_MASK_PARALLEL)
4885 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_REDUCTION]
4886 = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
4887 else if (mask & GFC_OMP_MASK_DO)
4888 clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_REDUCTION]
4889 = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
4890 if (mask & GFC_OMP_MASK_SIMD)
4891 clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_REDUCTION]
4892 = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
4893 /* Linear clause is supported on do and simd,
4894 put it on the innermost one. */
4895 clausesa[innermost].lists[OMP_LIST_LINEAR]
4896 = code->ext.omp_clauses->lists[OMP_LIST_LINEAR];
4897 }
4898 if ((mask & (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
4899 == (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
4900 clausesa[GFC_OMP_SPLIT_DO].nowait = true;
4901 }
4902
4903 static tree
4904 gfc_trans_omp_do_simd (gfc_code *code, stmtblock_t *pblock,
4905 gfc_omp_clauses *clausesa, tree omp_clauses)
4906 {
4907 stmtblock_t block;
4908 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
4909 tree stmt, body, omp_do_clauses = NULL_TREE;
4910
4911 if (pblock == NULL)
4912 gfc_start_block (&block);
4913 else
4914 gfc_init_block (&block);
4915
4916 if (clausesa == NULL)
4917 {
4918 clausesa = clausesa_buf;
4919 gfc_split_omp_clauses (code, clausesa);
4920 }
4921 if (flag_openmp)
4922 omp_do_clauses
4923 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DO], code->loc);
4924 body = gfc_trans_omp_do (code, EXEC_OMP_SIMD, pblock ? pblock : &block,
4925 &clausesa[GFC_OMP_SPLIT_SIMD], omp_clauses);
4926 if (pblock == NULL)
4927 {
4928 if (TREE_CODE (body) != BIND_EXPR)
4929 body = build3_v (BIND_EXPR, NULL, body, poplevel (1, 0));
4930 else
4931 poplevel (0, 0);
4932 }
4933 else if (TREE_CODE (body) != BIND_EXPR)
4934 body = build3_v (BIND_EXPR, NULL, body, NULL_TREE);
4935 if (flag_openmp)
4936 {
4937 stmt = make_node (OMP_FOR);
4938 TREE_TYPE (stmt) = void_type_node;
4939 OMP_FOR_BODY (stmt) = body;
4940 OMP_FOR_CLAUSES (stmt) = omp_do_clauses;
4941 }
4942 else
4943 stmt = body;
4944 gfc_add_expr_to_block (&block, stmt);
4945 return gfc_finish_block (&block);
4946 }
4947
4948 static tree
4949 gfc_trans_omp_parallel_do (gfc_code *code, stmtblock_t *pblock,
4950 gfc_omp_clauses *clausesa)
4951 {
4952 stmtblock_t block, *new_pblock = pblock;
4953 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
4954 tree stmt, omp_clauses = NULL_TREE;
4955
4956 if (pblock == NULL)
4957 gfc_start_block (&block);
4958 else
4959 gfc_init_block (&block);
4960
4961 if (clausesa == NULL)
4962 {
4963 clausesa = clausesa_buf;
4964 gfc_split_omp_clauses (code, clausesa);
4965 }
4966 omp_clauses
4967 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
4968 code->loc);
4969 if (pblock == NULL)
4970 {
4971 if (!clausesa[GFC_OMP_SPLIT_DO].ordered
4972 && clausesa[GFC_OMP_SPLIT_DO].sched_kind != OMP_SCHED_STATIC)
4973 new_pblock = &block;
4974 else
4975 pushlevel ();
4976 }
4977 stmt = gfc_trans_omp_do (code, EXEC_OMP_DO, new_pblock,
4978 &clausesa[GFC_OMP_SPLIT_DO], omp_clauses);
4979 if (pblock == NULL)
4980 {
4981 if (TREE_CODE (stmt) != BIND_EXPR)
4982 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
4983 else
4984 poplevel (0, 0);
4985 }
4986 else if (TREE_CODE (stmt) != BIND_EXPR)
4987 stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
4988 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
4989 omp_clauses);
4990 OMP_PARALLEL_COMBINED (stmt) = 1;
4991 gfc_add_expr_to_block (&block, stmt);
4992 return gfc_finish_block (&block);
4993 }
4994
4995 static tree
4996 gfc_trans_omp_parallel_do_simd (gfc_code *code, stmtblock_t *pblock,
4997 gfc_omp_clauses *clausesa)
4998 {
4999 stmtblock_t block;
5000 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
5001 tree stmt, omp_clauses = NULL_TREE;
5002
5003 if (pblock == NULL)
5004 gfc_start_block (&block);
5005 else
5006 gfc_init_block (&block);
5007
5008 if (clausesa == NULL)
5009 {
5010 clausesa = clausesa_buf;
5011 gfc_split_omp_clauses (code, clausesa);
5012 }
5013 if (flag_openmp)
5014 omp_clauses
5015 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
5016 code->loc);
5017 if (pblock == NULL)
5018 pushlevel ();
5019 stmt = gfc_trans_omp_do_simd (code, pblock, clausesa, omp_clauses);
5020 if (pblock == NULL)
5021 {
5022 if (TREE_CODE (stmt) != BIND_EXPR)
5023 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5024 else
5025 poplevel (0, 0);
5026 }
5027 else if (TREE_CODE (stmt) != BIND_EXPR)
5028 stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
5029 if (flag_openmp)
5030 {
5031 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
5032 omp_clauses);
5033 OMP_PARALLEL_COMBINED (stmt) = 1;
5034 }
5035 gfc_add_expr_to_block (&block, stmt);
5036 return gfc_finish_block (&block);
5037 }
5038
5039 static tree
5040 gfc_trans_omp_parallel_sections (gfc_code *code)
5041 {
5042 stmtblock_t block;
5043 gfc_omp_clauses section_clauses;
5044 tree stmt, omp_clauses;
5045
5046 memset (&section_clauses, 0, sizeof (section_clauses));
5047 section_clauses.nowait = true;
5048
5049 gfc_start_block (&block);
5050 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
5051 code->loc);
5052 pushlevel ();
5053 stmt = gfc_trans_omp_sections (code, &section_clauses);
5054 if (TREE_CODE (stmt) != BIND_EXPR)
5055 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5056 else
5057 poplevel (0, 0);
5058 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
5059 omp_clauses);
5060 OMP_PARALLEL_COMBINED (stmt) = 1;
5061 gfc_add_expr_to_block (&block, stmt);
5062 return gfc_finish_block (&block);
5063 }
5064
5065 static tree
5066 gfc_trans_omp_parallel_workshare (gfc_code *code)
5067 {
5068 stmtblock_t block;
5069 gfc_omp_clauses workshare_clauses;
5070 tree stmt, omp_clauses;
5071
5072 memset (&workshare_clauses, 0, sizeof (workshare_clauses));
5073 workshare_clauses.nowait = true;
5074
5075 gfc_start_block (&block);
5076 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
5077 code->loc);
5078 pushlevel ();
5079 stmt = gfc_trans_omp_workshare (code, &workshare_clauses);
5080 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5081 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
5082 omp_clauses);
5083 OMP_PARALLEL_COMBINED (stmt) = 1;
5084 gfc_add_expr_to_block (&block, stmt);
5085 return gfc_finish_block (&block);
5086 }
5087
5088 static tree
5089 gfc_trans_omp_sections (gfc_code *code, gfc_omp_clauses *clauses)
5090 {
5091 stmtblock_t block, body;
5092 tree omp_clauses, stmt;
5093 bool has_lastprivate = clauses->lists[OMP_LIST_LASTPRIVATE] != NULL;
5094
5095 gfc_start_block (&block);
5096
5097 omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
5098
5099 gfc_init_block (&body);
5100 for (code = code->block; code; code = code->block)
5101 {
5102 /* Last section is special because of lastprivate, so even if it
5103 is empty, chain it in. */
5104 stmt = gfc_trans_omp_code (code->next,
5105 has_lastprivate && code->block == NULL);
5106 if (! IS_EMPTY_STMT (stmt))
5107 {
5108 stmt = build1_v (OMP_SECTION, stmt);
5109 gfc_add_expr_to_block (&body, stmt);
5110 }
5111 }
5112 stmt = gfc_finish_block (&body);
5113
5114 stmt = build2_loc (input_location, OMP_SECTIONS, void_type_node, stmt,
5115 omp_clauses);
5116 gfc_add_expr_to_block (&block, stmt);
5117
5118 return gfc_finish_block (&block);
5119 }
5120
5121 static tree
5122 gfc_trans_omp_single (gfc_code *code, gfc_omp_clauses *clauses)
5123 {
5124 tree omp_clauses = gfc_trans_omp_clauses (NULL, clauses, code->loc);
5125 tree stmt = gfc_trans_omp_code (code->block->next, true);
5126 stmt = build2_loc (input_location, OMP_SINGLE, void_type_node, stmt,
5127 omp_clauses);
5128 return stmt;
5129 }
5130
5131 static tree
5132 gfc_trans_omp_task (gfc_code *code)
5133 {
5134 stmtblock_t block;
5135 tree stmt, omp_clauses;
5136
5137 gfc_start_block (&block);
5138 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
5139 code->loc);
5140 pushlevel ();
5141 stmt = gfc_trans_omp_code (code->block->next, true);
5142 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5143 stmt = build2_loc (input_location, OMP_TASK, void_type_node, stmt,
5144 omp_clauses);
5145 gfc_add_expr_to_block (&block, stmt);
5146 return gfc_finish_block (&block);
5147 }
5148
5149 static tree
5150 gfc_trans_omp_taskgroup (gfc_code *code)
5151 {
5152 tree body = gfc_trans_code (code->block->next);
5153 tree stmt = make_node (OMP_TASKGROUP);
5154 TREE_TYPE (stmt) = void_type_node;
5155 OMP_TASKGROUP_BODY (stmt) = body;
5156 OMP_TASKGROUP_CLAUSES (stmt) = NULL_TREE;
5157 return stmt;
5158 }
5159
5160 static tree
5161 gfc_trans_omp_taskwait (void)
5162 {
5163 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
5164 return build_call_expr_loc (input_location, decl, 0);
5165 }
5166
5167 static tree
5168 gfc_trans_omp_taskyield (void)
5169 {
5170 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
5171 return build_call_expr_loc (input_location, decl, 0);
5172 }
5173
5174 static tree
5175 gfc_trans_omp_distribute (gfc_code *code, gfc_omp_clauses *clausesa)
5176 {
5177 stmtblock_t block;
5178 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
5179 tree stmt, omp_clauses = NULL_TREE;
5180
5181 gfc_start_block (&block);
5182 if (clausesa == NULL)
5183 {
5184 clausesa = clausesa_buf;
5185 gfc_split_omp_clauses (code, clausesa);
5186 }
5187 if (flag_openmp)
5188 omp_clauses
5189 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
5190 code->loc);
5191 switch (code->op)
5192 {
5193 case EXEC_OMP_DISTRIBUTE:
5194 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
5195 case EXEC_OMP_TEAMS_DISTRIBUTE:
5196 /* This is handled in gfc_trans_omp_do. */
5197 gcc_unreachable ();
5198 break;
5199 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
5200 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
5201 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
5202 stmt = gfc_trans_omp_parallel_do (code, &block, clausesa);
5203 if (TREE_CODE (stmt) != BIND_EXPR)
5204 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5205 else
5206 poplevel (0, 0);
5207 break;
5208 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
5209 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5210 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5211 stmt = gfc_trans_omp_parallel_do_simd (code, &block, clausesa);
5212 if (TREE_CODE (stmt) != BIND_EXPR)
5213 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5214 else
5215 poplevel (0, 0);
5216 break;
5217 case EXEC_OMP_DISTRIBUTE_SIMD:
5218 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
5219 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
5220 stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
5221 &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
5222 if (TREE_CODE (stmt) != BIND_EXPR)
5223 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5224 else
5225 poplevel (0, 0);
5226 break;
5227 default:
5228 gcc_unreachable ();
5229 }
5230 if (flag_openmp)
5231 {
5232 tree distribute = make_node (OMP_DISTRIBUTE);
5233 TREE_TYPE (distribute) = void_type_node;
5234 OMP_FOR_BODY (distribute) = stmt;
5235 OMP_FOR_CLAUSES (distribute) = omp_clauses;
5236 stmt = distribute;
5237 }
5238 gfc_add_expr_to_block (&block, stmt);
5239 return gfc_finish_block (&block);
5240 }
5241
5242 static tree
5243 gfc_trans_omp_teams (gfc_code *code, gfc_omp_clauses *clausesa,
5244 tree omp_clauses)
5245 {
5246 stmtblock_t block;
5247 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
5248 tree stmt;
5249 bool combined = true;
5250
5251 gfc_start_block (&block);
5252 if (clausesa == NULL)
5253 {
5254 clausesa = clausesa_buf;
5255 gfc_split_omp_clauses (code, clausesa);
5256 }
5257 if (flag_openmp)
5258 {
5259 omp_clauses
5260 = chainon (omp_clauses,
5261 gfc_trans_omp_clauses (&block,
5262 &clausesa[GFC_OMP_SPLIT_TEAMS],
5263 code->loc));
5264 pushlevel ();
5265 }
5266 switch (code->op)
5267 {
5268 case EXEC_OMP_TARGET_TEAMS:
5269 case EXEC_OMP_TEAMS:
5270 stmt = gfc_trans_omp_code (code->block->next, true);
5271 combined = false;
5272 break;
5273 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
5274 case EXEC_OMP_TEAMS_DISTRIBUTE:
5275 stmt = gfc_trans_omp_do (code, EXEC_OMP_DISTRIBUTE, NULL,
5276 &clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
5277 NULL);
5278 break;
5279 default:
5280 stmt = gfc_trans_omp_distribute (code, clausesa);
5281 break;
5282 }
5283 if (flag_openmp)
5284 {
5285 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5286 stmt = build2_loc (input_location, OMP_TEAMS, void_type_node, stmt,
5287 omp_clauses);
5288 if (combined)
5289 OMP_TEAMS_COMBINED (stmt) = 1;
5290 }
5291 gfc_add_expr_to_block (&block, stmt);
5292 return gfc_finish_block (&block);
5293 }
5294
5295 static tree
5296 gfc_trans_omp_target (gfc_code *code)
5297 {
5298 stmtblock_t block;
5299 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
5300 tree stmt, omp_clauses = NULL_TREE;
5301
5302 gfc_start_block (&block);
5303 gfc_split_omp_clauses (code, clausesa);
5304 if (flag_openmp)
5305 omp_clauses
5306 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TARGET],
5307 code->loc);
5308 switch (code->op)
5309 {
5310 case EXEC_OMP_TARGET:
5311 pushlevel ();
5312 stmt = gfc_trans_omp_code (code->block->next, true);
5313 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5314 break;
5315 case EXEC_OMP_TARGET_PARALLEL:
5316 {
5317 stmtblock_t iblock;
5318
5319 gfc_start_block (&iblock);
5320 tree inner_clauses
5321 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
5322 code->loc);
5323 stmt = gfc_trans_omp_code (code->block->next, true);
5324 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
5325 inner_clauses);
5326 gfc_add_expr_to_block (&iblock, stmt);
5327 stmt = gfc_finish_block (&iblock);
5328 if (TREE_CODE (stmt) != BIND_EXPR)
5329 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5330 else
5331 poplevel (0, 0);
5332 }
5333 break;
5334 case EXEC_OMP_TARGET_PARALLEL_DO:
5335 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
5336 stmt = gfc_trans_omp_parallel_do (code, &block, clausesa);
5337 if (TREE_CODE (stmt) != BIND_EXPR)
5338 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5339 else
5340 poplevel (0, 0);
5341 break;
5342 case EXEC_OMP_TARGET_SIMD:
5343 stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
5344 &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
5345 if (TREE_CODE (stmt) != BIND_EXPR)
5346 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5347 else
5348 poplevel (0, 0);
5349 break;
5350 default:
5351 if (flag_openmp
5352 && (clausesa[GFC_OMP_SPLIT_TEAMS].num_teams
5353 || clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit))
5354 {
5355 gfc_omp_clauses clausesb;
5356 tree teams_clauses;
5357 /* For combined !$omp target teams, the num_teams and
5358 thread_limit clauses are evaluated before entering the
5359 target construct. */
5360 memset (&clausesb, '\0', sizeof (clausesb));
5361 clausesb.num_teams = clausesa[GFC_OMP_SPLIT_TEAMS].num_teams;
5362 clausesb.thread_limit = clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit;
5363 clausesa[GFC_OMP_SPLIT_TEAMS].num_teams = NULL;
5364 clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit = NULL;
5365 teams_clauses
5366 = gfc_trans_omp_clauses (&block, &clausesb, code->loc);
5367 pushlevel ();
5368 stmt = gfc_trans_omp_teams (code, clausesa, teams_clauses);
5369 }
5370 else
5371 {
5372 pushlevel ();
5373 stmt = gfc_trans_omp_teams (code, clausesa, NULL_TREE);
5374 }
5375 if (TREE_CODE (stmt) != BIND_EXPR)
5376 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5377 else
5378 poplevel (0, 0);
5379 break;
5380 }
5381 if (flag_openmp)
5382 {
5383 stmt = build2_loc (input_location, OMP_TARGET, void_type_node, stmt,
5384 omp_clauses);
5385 if (code->op != EXEC_OMP_TARGET)
5386 OMP_TARGET_COMBINED (stmt) = 1;
5387 }
5388 gfc_add_expr_to_block (&block, stmt);
5389 return gfc_finish_block (&block);
5390 }
5391
5392 static tree
5393 gfc_trans_omp_taskloop (gfc_code *code)
5394 {
5395 stmtblock_t block;
5396 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
5397 tree stmt, omp_clauses = NULL_TREE;
5398
5399 gfc_start_block (&block);
5400 gfc_split_omp_clauses (code, clausesa);
5401 if (flag_openmp)
5402 omp_clauses
5403 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TASKLOOP],
5404 code->loc);
5405 switch (code->op)
5406 {
5407 case EXEC_OMP_TASKLOOP:
5408 /* This is handled in gfc_trans_omp_do. */
5409 gcc_unreachable ();
5410 break;
5411 case EXEC_OMP_TASKLOOP_SIMD:
5412 stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
5413 &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
5414 if (TREE_CODE (stmt) != BIND_EXPR)
5415 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5416 else
5417 poplevel (0, 0);
5418 break;
5419 default:
5420 gcc_unreachable ();
5421 }
5422 if (flag_openmp)
5423 {
5424 tree taskloop = make_node (OMP_TASKLOOP);
5425 TREE_TYPE (taskloop) = void_type_node;
5426 OMP_FOR_BODY (taskloop) = stmt;
5427 OMP_FOR_CLAUSES (taskloop) = omp_clauses;
5428 stmt = taskloop;
5429 }
5430 gfc_add_expr_to_block (&block, stmt);
5431 return gfc_finish_block (&block);
5432 }
5433
5434 static tree
5435 gfc_trans_omp_target_data (gfc_code *code)
5436 {
5437 stmtblock_t block;
5438 tree stmt, omp_clauses;
5439
5440 gfc_start_block (&block);
5441 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
5442 code->loc);
5443 stmt = gfc_trans_omp_code (code->block->next, true);
5444 stmt = build2_loc (input_location, OMP_TARGET_DATA, void_type_node, stmt,
5445 omp_clauses);
5446 gfc_add_expr_to_block (&block, stmt);
5447 return gfc_finish_block (&block);
5448 }
5449
5450 static tree
5451 gfc_trans_omp_target_enter_data (gfc_code *code)
5452 {
5453 stmtblock_t block;
5454 tree stmt, omp_clauses;
5455
5456 gfc_start_block (&block);
5457 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
5458 code->loc);
5459 stmt = build1_loc (input_location, OMP_TARGET_ENTER_DATA, void_type_node,
5460 omp_clauses);
5461 gfc_add_expr_to_block (&block, stmt);
5462 return gfc_finish_block (&block);
5463 }
5464
5465 static tree
5466 gfc_trans_omp_target_exit_data (gfc_code *code)
5467 {
5468 stmtblock_t block;
5469 tree stmt, omp_clauses;
5470
5471 gfc_start_block (&block);
5472 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
5473 code->loc);
5474 stmt = build1_loc (input_location, OMP_TARGET_EXIT_DATA, void_type_node,
5475 omp_clauses);
5476 gfc_add_expr_to_block (&block, stmt);
5477 return gfc_finish_block (&block);
5478 }
5479
5480 static tree
5481 gfc_trans_omp_target_update (gfc_code *code)
5482 {
5483 stmtblock_t block;
5484 tree stmt, omp_clauses;
5485
5486 gfc_start_block (&block);
5487 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
5488 code->loc);
5489 stmt = build1_loc (input_location, OMP_TARGET_UPDATE, void_type_node,
5490 omp_clauses);
5491 gfc_add_expr_to_block (&block, stmt);
5492 return gfc_finish_block (&block);
5493 }
5494
5495 static tree
5496 gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses)
5497 {
5498 tree res, tmp, stmt;
5499 stmtblock_t block, *pblock = NULL;
5500 stmtblock_t singleblock;
5501 int saved_ompws_flags;
5502 bool singleblock_in_progress = false;
5503 /* True if previous gfc_code in workshare construct is not workshared. */
5504 bool prev_singleunit;
5505
5506 code = code->block->next;
5507
5508 pushlevel ();
5509
5510 gfc_start_block (&block);
5511 pblock = &block;
5512
5513 ompws_flags = OMPWS_WORKSHARE_FLAG;
5514 prev_singleunit = false;
5515
5516 /* Translate statements one by one to trees until we reach
5517 the end of the workshare construct. Adjacent gfc_codes that
5518 are a single unit of work are clustered and encapsulated in a
5519 single OMP_SINGLE construct. */
5520 for (; code; code = code->next)
5521 {
5522 if (code->here != 0)
5523 {
5524 res = gfc_trans_label_here (code);
5525 gfc_add_expr_to_block (pblock, res);
5526 }
5527
5528 /* No dependence analysis, use for clauses with wait.
5529 If this is the last gfc_code, use default omp_clauses. */
5530 if (code->next == NULL && clauses->nowait)
5531 ompws_flags |= OMPWS_NOWAIT;
5532
5533 /* By default, every gfc_code is a single unit of work. */
5534 ompws_flags |= OMPWS_CURR_SINGLEUNIT;
5535 ompws_flags &= ~(OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY);
5536
5537 switch (code->op)
5538 {
5539 case EXEC_NOP:
5540 res = NULL_TREE;
5541 break;
5542
5543 case EXEC_ASSIGN:
5544 res = gfc_trans_assign (code);
5545 break;
5546
5547 case EXEC_POINTER_ASSIGN:
5548 res = gfc_trans_pointer_assign (code);
5549 break;
5550
5551 case EXEC_INIT_ASSIGN:
5552 res = gfc_trans_init_assign (code);
5553 break;
5554
5555 case EXEC_FORALL:
5556 res = gfc_trans_forall (code);
5557 break;
5558
5559 case EXEC_WHERE:
5560 res = gfc_trans_where (code);
5561 break;
5562
5563 case EXEC_OMP_ATOMIC:
5564 res = gfc_trans_omp_directive (code);
5565 break;
5566
5567 case EXEC_OMP_PARALLEL:
5568 case EXEC_OMP_PARALLEL_DO:
5569 case EXEC_OMP_PARALLEL_SECTIONS:
5570 case EXEC_OMP_PARALLEL_WORKSHARE:
5571 case EXEC_OMP_CRITICAL:
5572 saved_ompws_flags = ompws_flags;
5573 ompws_flags = 0;
5574 res = gfc_trans_omp_directive (code);
5575 ompws_flags = saved_ompws_flags;
5576 break;
5577
5578 default:
5579 gfc_internal_error ("gfc_trans_omp_workshare(): Bad statement code");
5580 }
5581
5582 gfc_set_backend_locus (&code->loc);
5583
5584 if (res != NULL_TREE && ! IS_EMPTY_STMT (res))
5585 {
5586 if (prev_singleunit)
5587 {
5588 if (ompws_flags & OMPWS_CURR_SINGLEUNIT)
5589 /* Add current gfc_code to single block. */
5590 gfc_add_expr_to_block (&singleblock, res);
5591 else
5592 {
5593 /* Finish single block and add it to pblock. */
5594 tmp = gfc_finish_block (&singleblock);
5595 tmp = build2_loc (input_location, OMP_SINGLE,
5596 void_type_node, tmp, NULL_TREE);
5597 gfc_add_expr_to_block (pblock, tmp);
5598 /* Add current gfc_code to pblock. */
5599 gfc_add_expr_to_block (pblock, res);
5600 singleblock_in_progress = false;
5601 }
5602 }
5603 else
5604 {
5605 if (ompws_flags & OMPWS_CURR_SINGLEUNIT)
5606 {
5607 /* Start single block. */
5608 gfc_init_block (&singleblock);
5609 gfc_add_expr_to_block (&singleblock, res);
5610 singleblock_in_progress = true;
5611 }
5612 else
5613 /* Add the new statement to the block. */
5614 gfc_add_expr_to_block (pblock, res);
5615 }
5616 prev_singleunit = (ompws_flags & OMPWS_CURR_SINGLEUNIT) != 0;
5617 }
5618 }
5619
5620 /* Finish remaining SINGLE block, if we were in the middle of one. */
5621 if (singleblock_in_progress)
5622 {
5623 /* Finish single block and add it to pblock. */
5624 tmp = gfc_finish_block (&singleblock);
5625 tmp = build2_loc (input_location, OMP_SINGLE, void_type_node, tmp,
5626 clauses->nowait
5627 ? build_omp_clause (input_location, OMP_CLAUSE_NOWAIT)
5628 : NULL_TREE);
5629 gfc_add_expr_to_block (pblock, tmp);
5630 }
5631
5632 stmt = gfc_finish_block (pblock);
5633 if (TREE_CODE (stmt) != BIND_EXPR)
5634 {
5635 if (!IS_EMPTY_STMT (stmt))
5636 {
5637 tree bindblock = poplevel (1, 0);
5638 stmt = build3_v (BIND_EXPR, NULL, stmt, bindblock);
5639 }
5640 else
5641 poplevel (0, 0);
5642 }
5643 else
5644 poplevel (0, 0);
5645
5646 if (IS_EMPTY_STMT (stmt) && !clauses->nowait)
5647 stmt = gfc_trans_omp_barrier ();
5648
5649 ompws_flags = 0;
5650 return stmt;
5651 }
5652
5653 tree
5654 gfc_trans_oacc_declare (gfc_code *code)
5655 {
5656 stmtblock_t block;
5657 tree stmt, oacc_clauses;
5658 enum tree_code construct_code;
5659
5660 construct_code = OACC_DATA;
5661
5662 gfc_start_block (&block);
5663
5664 oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.oacc_declare->clauses,
5665 code->loc);
5666 stmt = gfc_trans_omp_code (code->block->next, true);
5667 stmt = build2_loc (input_location, construct_code, void_type_node, stmt,
5668 oacc_clauses);
5669 gfc_add_expr_to_block (&block, stmt);
5670
5671 return gfc_finish_block (&block);
5672 }
5673
5674 tree
5675 gfc_trans_oacc_directive (gfc_code *code)
5676 {
5677 switch (code->op)
5678 {
5679 case EXEC_OACC_PARALLEL_LOOP:
5680 case EXEC_OACC_KERNELS_LOOP:
5681 case EXEC_OACC_SERIAL_LOOP:
5682 return gfc_trans_oacc_combined_directive (code);
5683 case EXEC_OACC_PARALLEL:
5684 case EXEC_OACC_KERNELS:
5685 case EXEC_OACC_SERIAL:
5686 case EXEC_OACC_DATA:
5687 case EXEC_OACC_HOST_DATA:
5688 return gfc_trans_oacc_construct (code);
5689 case EXEC_OACC_LOOP:
5690 return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses,
5691 NULL);
5692 case EXEC_OACC_UPDATE:
5693 case EXEC_OACC_CACHE:
5694 case EXEC_OACC_ENTER_DATA:
5695 case EXEC_OACC_EXIT_DATA:
5696 return gfc_trans_oacc_executable_directive (code);
5697 case EXEC_OACC_WAIT:
5698 return gfc_trans_oacc_wait_directive (code);
5699 case EXEC_OACC_ATOMIC:
5700 return gfc_trans_omp_atomic (code);
5701 case EXEC_OACC_DECLARE:
5702 return gfc_trans_oacc_declare (code);
5703 default:
5704 gcc_unreachable ();
5705 }
5706 }
5707
5708 tree
5709 gfc_trans_omp_directive (gfc_code *code)
5710 {
5711 switch (code->op)
5712 {
5713 case EXEC_OMP_ATOMIC:
5714 return gfc_trans_omp_atomic (code);
5715 case EXEC_OMP_BARRIER:
5716 return gfc_trans_omp_barrier ();
5717 case EXEC_OMP_CANCEL:
5718 return gfc_trans_omp_cancel (code);
5719 case EXEC_OMP_CANCELLATION_POINT:
5720 return gfc_trans_omp_cancellation_point (code);
5721 case EXEC_OMP_CRITICAL:
5722 return gfc_trans_omp_critical (code);
5723 case EXEC_OMP_DISTRIBUTE:
5724 case EXEC_OMP_DO:
5725 case EXEC_OMP_SIMD:
5726 case EXEC_OMP_TASKLOOP:
5727 return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses,
5728 NULL);
5729 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
5730 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
5731 case EXEC_OMP_DISTRIBUTE_SIMD:
5732 return gfc_trans_omp_distribute (code, NULL);
5733 case EXEC_OMP_DO_SIMD:
5734 return gfc_trans_omp_do_simd (code, NULL, NULL, NULL_TREE);
5735 case EXEC_OMP_FLUSH:
5736 return gfc_trans_omp_flush ();
5737 case EXEC_OMP_MASTER:
5738 return gfc_trans_omp_master (code);
5739 case EXEC_OMP_ORDERED:
5740 return gfc_trans_omp_ordered (code);
5741 case EXEC_OMP_PARALLEL:
5742 return gfc_trans_omp_parallel (code);
5743 case EXEC_OMP_PARALLEL_DO:
5744 return gfc_trans_omp_parallel_do (code, NULL, NULL);
5745 case EXEC_OMP_PARALLEL_DO_SIMD:
5746 return gfc_trans_omp_parallel_do_simd (code, NULL, NULL);
5747 case EXEC_OMP_PARALLEL_SECTIONS:
5748 return gfc_trans_omp_parallel_sections (code);
5749 case EXEC_OMP_PARALLEL_WORKSHARE:
5750 return gfc_trans_omp_parallel_workshare (code);
5751 case EXEC_OMP_SECTIONS:
5752 return gfc_trans_omp_sections (code, code->ext.omp_clauses);
5753 case EXEC_OMP_SINGLE:
5754 return gfc_trans_omp_single (code, code->ext.omp_clauses);
5755 case EXEC_OMP_TARGET:
5756 case EXEC_OMP_TARGET_PARALLEL:
5757 case EXEC_OMP_TARGET_PARALLEL_DO:
5758 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
5759 case EXEC_OMP_TARGET_SIMD:
5760 case EXEC_OMP_TARGET_TEAMS:
5761 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
5762 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
5763 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5764 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
5765 return gfc_trans_omp_target (code);
5766 case EXEC_OMP_TARGET_DATA:
5767 return gfc_trans_omp_target_data (code);
5768 case EXEC_OMP_TARGET_ENTER_DATA:
5769 return gfc_trans_omp_target_enter_data (code);
5770 case EXEC_OMP_TARGET_EXIT_DATA:
5771 return gfc_trans_omp_target_exit_data (code);
5772 case EXEC_OMP_TARGET_UPDATE:
5773 return gfc_trans_omp_target_update (code);
5774 case EXEC_OMP_TASK:
5775 return gfc_trans_omp_task (code);
5776 case EXEC_OMP_TASKGROUP:
5777 return gfc_trans_omp_taskgroup (code);
5778 case EXEC_OMP_TASKLOOP_SIMD:
5779 return gfc_trans_omp_taskloop (code);
5780 case EXEC_OMP_TASKWAIT:
5781 return gfc_trans_omp_taskwait ();
5782 case EXEC_OMP_TASKYIELD:
5783 return gfc_trans_omp_taskyield ();
5784 case EXEC_OMP_TEAMS:
5785 case EXEC_OMP_TEAMS_DISTRIBUTE:
5786 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
5787 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5788 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
5789 return gfc_trans_omp_teams (code, NULL, NULL_TREE);
5790 case EXEC_OMP_WORKSHARE:
5791 return gfc_trans_omp_workshare (code, code->ext.omp_clauses);
5792 default:
5793 gcc_unreachable ();
5794 }
5795 }
5796
5797 void
5798 gfc_trans_omp_declare_simd (gfc_namespace *ns)
5799 {
5800 if (ns->entries)
5801 return;
5802
5803 gfc_omp_declare_simd *ods;
5804 for (ods = ns->omp_declare_simd; ods; ods = ods->next)
5805 {
5806 tree c = gfc_trans_omp_clauses (NULL, ods->clauses, ods->where, true);
5807 tree fndecl = ns->proc_name->backend_decl;
5808 if (c != NULL_TREE)
5809 c = tree_cons (NULL_TREE, c, NULL_TREE);
5810 c = build_tree_list (get_identifier ("omp declare simd"), c);
5811 TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
5812 DECL_ATTRIBUTES (fndecl) = c;
5813 }
5814 }