]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/fortran/trans-openmp.c
[multiple changes]
[thirdparty/gcc.git] / gcc / fortran / trans-openmp.c
CommitLineData
6c7a4dfd 1/* OpenMP directive translation -- generate GCC trees from gfc_code.
23a5b65a 2 Copyright (C) 2005-2014 Free Software Foundation, Inc.
6c7a4dfd
JJ
3 Contributed by Jakub Jelinek <jakub@redhat.com>
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
d234d788 9Software Foundation; either version 3, or (at your option) any later
6c7a4dfd
JJ
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
d234d788
NC
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
6c7a4dfd
JJ
20
21
22#include "config.h"
23#include "system.h"
24#include "coretypes.h"
25#include "tree.h"
2fb9a547 26#include "gimple-expr.h"
45b0be94 27#include "gimplify.h" /* For create_tmp_var_raw. */
d8a2d370 28#include "stringpool.h"
c829d016 29#include "diagnostic-core.h" /* For internal_error. */
6c7a4dfd
JJ
30#include "gfortran.h"
31#include "trans.h"
32#include "trans-stmt.h"
33#include "trans-types.h"
34#include "trans-array.h"
35#include "trans-const.h"
36#include "arith.h"
0645c1a2 37#include "omp-low.h"
6c7a4dfd 38
34d01e1d 39int ompws_flags;
6c7a4dfd
JJ
40
41/* True if OpenMP should privatize what this DECL points to rather
42 than the DECL itself. */
43
44bool
58f9752a 45gfc_omp_privatize_by_reference (const_tree decl)
6c7a4dfd
JJ
46{
47 tree type = TREE_TYPE (decl);
48
36cefd39
JJ
49 if (TREE_CODE (type) == REFERENCE_TYPE
50 && (!DECL_ARTIFICIAL (decl) || TREE_CODE (decl) == PARM_DECL))
6c7a4dfd
JJ
51 return true;
52
53 if (TREE_CODE (type) == POINTER_TYPE)
54 {
e1c82219
JJ
55 /* Array POINTER/ALLOCATABLE have aggregate types, all user variables
56 that have POINTER_TYPE type and don't have GFC_POINTER_TYPE_P
57 set are supposed to be privatized by reference. */
92d28cbb
JJ
58 if (GFC_DECL_GET_SCALAR_POINTER (decl)
59 || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
60 || GFC_DECL_CRAY_POINTEE (decl))
e1c82219
JJ
61 return false;
62
2b45bf21
JJ
63 if (!DECL_ARTIFICIAL (decl)
64 && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
6c7a4dfd
JJ
65 return true;
66
67 /* Some arrays are expanded as DECL_ARTIFICIAL pointers
68 by the frontend. */
69 if (DECL_LANG_SPECIFIC (decl)
70 && GFC_DECL_SAVED_DESCRIPTOR (decl))
71 return true;
72 }
73
74 return false;
75}
76
77/* True if OpenMP sharing attribute of DECL is predetermined. */
78
79enum omp_clause_default_kind
80gfc_omp_predetermined_sharing (tree decl)
81{
92d28cbb
JJ
82 /* Associate names preserve the association established during ASSOCIATE.
83 As they are implemented either as pointers to the selector or array
84 descriptor and shouldn't really change in the ASSOCIATE region,
85 this decl can be either shared or firstprivate. If it is a pointer,
86 use firstprivate, as it is cheaper that way, otherwise make it shared. */
87 if (GFC_DECL_ASSOCIATE_VAR_P (decl))
88 {
89 if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
90 return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
91 else
92 return OMP_CLAUSE_DEFAULT_SHARED;
93 }
94
79943d19
JJ
95 if (DECL_ARTIFICIAL (decl)
96 && ! GFC_DECL_RESULT (decl)
97 && ! (DECL_LANG_SPECIFIC (decl)
98 && GFC_DECL_SAVED_DESCRIPTOR (decl)))
6c7a4dfd
JJ
99 return OMP_CLAUSE_DEFAULT_SHARED;
100
101 /* Cray pointees shouldn't be listed in any clauses and should be
102 gimplified to dereference of the corresponding Cray pointer.
103 Make them all private, so that they are emitted in the debug
104 information. */
105 if (GFC_DECL_CRAY_POINTEE (decl))
106 return OMP_CLAUSE_DEFAULT_PRIVATE;
107
20906c66 108 /* Assumed-size arrays are predetermined shared. */
a68ab351
JJ
109 if (TREE_CODE (decl) == PARM_DECL
110 && GFC_ARRAY_TYPE_P (TREE_TYPE (decl))
111 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN
112 && GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (decl),
113 GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)) - 1)
114 == NULL)
115 return OMP_CLAUSE_DEFAULT_SHARED;
116
2b45bf21
JJ
117 /* Dummy procedures aren't considered variables by OpenMP, thus are
118 disallowed in OpenMP clauses. They are represented as PARM_DECLs
119 in the middle-end, so return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE here
120 to avoid complaining about their uses with default(none). */
121 if (TREE_CODE (decl) == PARM_DECL
122 && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
123 && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == FUNCTION_TYPE)
124 return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
125
6c7a4dfd
JJ
126 /* COMMON and EQUIVALENCE decls are shared. They
127 are only referenced through DECL_VALUE_EXPR of the variables
128 contained in them. If those are privatized, they will not be
129 gimplified to the COMMON or EQUIVALENCE decls. */
130 if (GFC_DECL_COMMON_OR_EQUIV (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
131 return OMP_CLAUSE_DEFAULT_SHARED;
132
133 if (GFC_DECL_RESULT (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
134 return OMP_CLAUSE_DEFAULT_SHARED;
135
136 return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
137}
138
79943d19
JJ
139/* Return decl that should be used when reporting DEFAULT(NONE)
140 diagnostics. */
141
142tree
143gfc_omp_report_decl (tree decl)
144{
145 if (DECL_ARTIFICIAL (decl)
146 && DECL_LANG_SPECIFIC (decl)
147 && GFC_DECL_SAVED_DESCRIPTOR (decl))
148 return GFC_DECL_SAVED_DESCRIPTOR (decl);
149
150 return decl;
151}
cd75853e 152
92d28cbb
JJ
153/* Return true if TYPE has any allocatable components. */
154
155static bool
156gfc_has_alloc_comps (tree type, tree decl)
157{
158 tree field, ftype;
159
160 if (POINTER_TYPE_P (type))
161 {
162 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
163 type = TREE_TYPE (type);
164 else if (GFC_DECL_GET_SCALAR_POINTER (decl))
165 return false;
166 }
167
168 while (GFC_DESCRIPTOR_TYPE_P (type) || GFC_ARRAY_TYPE_P (type))
169 type = gfc_get_element_type (type);
170
171 if (TREE_CODE (type) != RECORD_TYPE)
172 return false;
173
174 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
175 {
176 ftype = TREE_TYPE (field);
177 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
178 return true;
179 if (GFC_DESCRIPTOR_TYPE_P (ftype)
180 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
181 return true;
182 if (gfc_has_alloc_comps (ftype, field))
183 return true;
184 }
185 return false;
186}
187
a68ab351
JJ
188/* Return true if DECL in private clause needs
189 OMP_CLAUSE_PRIVATE_OUTER_REF on the private clause. */
190bool
191gfc_omp_private_outer_ref (tree decl)
192{
193 tree type = TREE_TYPE (decl);
194
195 if (GFC_DESCRIPTOR_TYPE_P (type)
196 && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
197 return true;
198
92d28cbb
JJ
199 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
200 return true;
201
202 if (gfc_omp_privatize_by_reference (decl))
203 type = TREE_TYPE (type);
204
205 if (gfc_has_alloc_comps (type, decl))
206 return true;
207
a68ab351
JJ
208 return false;
209}
210
92d28cbb
JJ
211/* Callback for gfc_omp_unshare_expr. */
212
213static tree
214gfc_omp_unshare_expr_r (tree *tp, int *walk_subtrees, void *)
215{
216 tree t = *tp;
217 enum tree_code code = TREE_CODE (t);
218
219 /* Stop at types, decls, constants like copy_tree_r. */
220 if (TREE_CODE_CLASS (code) == tcc_type
221 || TREE_CODE_CLASS (code) == tcc_declaration
222 || TREE_CODE_CLASS (code) == tcc_constant
223 || code == BLOCK)
224 *walk_subtrees = 0;
225 else if (handled_component_p (t)
226 || TREE_CODE (t) == MEM_REF)
227 {
228 *tp = unshare_expr (t);
229 *walk_subtrees = 0;
230 }
231
232 return NULL_TREE;
233}
234
235/* Unshare in expr anything that the FE which normally doesn't
236 care much about tree sharing (because during gimplification
237 everything is unshared) could cause problems with tree sharing
238 at omp-low.c time. */
239
240static tree
241gfc_omp_unshare_expr (tree expr)
242{
243 walk_tree (&expr, gfc_omp_unshare_expr_r, NULL, NULL);
244 return expr;
245}
246
247enum walk_alloc_comps
248{
249 WALK_ALLOC_COMPS_DTOR,
250 WALK_ALLOC_COMPS_DEFAULT_CTOR,
251 WALK_ALLOC_COMPS_COPY_CTOR
252};
253
254/* Handle allocatable components in OpenMP clauses. */
255
256static tree
257gfc_walk_alloc_comps (tree decl, tree dest, tree var,
258 enum walk_alloc_comps kind)
259{
260 stmtblock_t block, tmpblock;
261 tree type = TREE_TYPE (decl), then_b, tem, field;
262 gfc_init_block (&block);
263
264 if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
265 {
266 if (GFC_DESCRIPTOR_TYPE_P (type))
267 {
268 gfc_init_block (&tmpblock);
269 tem = gfc_full_array_size (&tmpblock, decl,
270 GFC_TYPE_ARRAY_RANK (type));
271 then_b = gfc_finish_block (&tmpblock);
272 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (then_b));
273 tem = gfc_omp_unshare_expr (tem);
274 tem = fold_build2_loc (input_location, MINUS_EXPR,
275 gfc_array_index_type, tem,
276 gfc_index_one_node);
277 }
278 else
279 {
280 if (!TYPE_DOMAIN (type)
281 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE
282 || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node
283 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node)
284 {
285 tem = fold_build2 (EXACT_DIV_EXPR, sizetype,
286 TYPE_SIZE_UNIT (type),
287 TYPE_SIZE_UNIT (TREE_TYPE (type)));
288 tem = size_binop (MINUS_EXPR, tem, size_one_node);
289 }
290 else
291 tem = array_type_nelts (type);
292 tem = fold_convert (gfc_array_index_type, tem);
293 }
294
295 tree nelems = gfc_evaluate_now (tem, &block);
296 tree index = gfc_create_var (gfc_array_index_type, "S");
297
298 gfc_init_block (&tmpblock);
299 tem = gfc_conv_array_data (decl);
300 tree declvar = build_fold_indirect_ref_loc (input_location, tem);
301 tree declvref = gfc_build_array_ref (declvar, index, NULL);
302 tree destvar, destvref = NULL_TREE;
303 if (dest)
304 {
305 tem = gfc_conv_array_data (dest);
306 destvar = build_fold_indirect_ref_loc (input_location, tem);
307 destvref = gfc_build_array_ref (destvar, index, NULL);
308 }
309 gfc_add_expr_to_block (&tmpblock,
310 gfc_walk_alloc_comps (declvref, destvref,
311 var, kind));
312
313 gfc_loopinfo loop;
314 gfc_init_loopinfo (&loop);
315 loop.dimen = 1;
316 loop.from[0] = gfc_index_zero_node;
317 loop.loopvar[0] = index;
318 loop.to[0] = nelems;
319 gfc_trans_scalarizing_loops (&loop, &tmpblock);
320 gfc_add_block_to_block (&block, &loop.pre);
321 return gfc_finish_block (&block);
322 }
323 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (var))
324 {
325 decl = build_fold_indirect_ref_loc (input_location, decl);
326 if (dest)
327 dest = build_fold_indirect_ref_loc (input_location, dest);
328 type = TREE_TYPE (decl);
329 }
330
331 gcc_assert (TREE_CODE (type) == RECORD_TYPE);
332 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
333 {
334 tree ftype = TREE_TYPE (field);
335 tree declf, destf = NULL_TREE;
336 bool has_alloc_comps = gfc_has_alloc_comps (ftype, field);
337 if ((!GFC_DESCRIPTOR_TYPE_P (ftype)
338 || GFC_TYPE_ARRAY_AKIND (ftype) != GFC_ARRAY_ALLOCATABLE)
339 && !GFC_DECL_GET_SCALAR_ALLOCATABLE (field)
340 && !has_alloc_comps)
341 continue;
342 declf = fold_build3_loc (input_location, COMPONENT_REF, ftype,
343 decl, field, NULL_TREE);
344 if (dest)
345 destf = fold_build3_loc (input_location, COMPONENT_REF, ftype,
346 dest, field, NULL_TREE);
347
348 tem = NULL_TREE;
349 switch (kind)
350 {
351 case WALK_ALLOC_COMPS_DTOR:
352 break;
353 case WALK_ALLOC_COMPS_DEFAULT_CTOR:
354 if (GFC_DESCRIPTOR_TYPE_P (ftype)
355 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
356 {
357 gfc_add_modify (&block, unshare_expr (destf),
358 unshare_expr (declf));
359 tem = gfc_duplicate_allocatable_nocopy
360 (destf, declf, ftype,
361 GFC_TYPE_ARRAY_RANK (ftype));
362 }
363 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
364 tem = gfc_duplicate_allocatable_nocopy (destf, declf, ftype, 0);
365 break;
366 case WALK_ALLOC_COMPS_COPY_CTOR:
367 if (GFC_DESCRIPTOR_TYPE_P (ftype)
368 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
369 tem = gfc_duplicate_allocatable (destf, declf, ftype,
370 GFC_TYPE_ARRAY_RANK (ftype));
371 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
372 tem = gfc_duplicate_allocatable (destf, declf, ftype, 0);
373 break;
374 }
375 if (tem)
376 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
377 if (has_alloc_comps)
378 {
379 gfc_init_block (&tmpblock);
380 gfc_add_expr_to_block (&tmpblock,
381 gfc_walk_alloc_comps (declf, destf,
382 field, kind));
383 then_b = gfc_finish_block (&tmpblock);
384 if (GFC_DESCRIPTOR_TYPE_P (ftype)
385 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
386 tem = gfc_conv_descriptor_data_get (unshare_expr (declf));
387 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
388 tem = unshare_expr (declf);
389 else
390 tem = NULL_TREE;
391 if (tem)
392 {
393 tem = fold_convert (pvoid_type_node, tem);
394 tem = fold_build2_loc (input_location, NE_EXPR,
395 boolean_type_node, tem,
396 null_pointer_node);
397 then_b = build3_loc (input_location, COND_EXPR, void_type_node,
398 tem, then_b,
399 build_empty_stmt (input_location));
400 }
401 gfc_add_expr_to_block (&block, then_b);
402 }
403 if (kind == WALK_ALLOC_COMPS_DTOR)
404 {
405 if (GFC_DESCRIPTOR_TYPE_P (ftype)
406 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
407 {
408 tem = gfc_trans_dealloc_allocated (unshare_expr (declf),
409 false, NULL);
410 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
411 }
412 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
413 {
414 tem = gfc_call_free (unshare_expr (declf));
415 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
416 }
417 }
418 }
419
420 return gfc_finish_block (&block);
421}
422
cd75853e
JJ
423/* Return code to initialize DECL with its default constructor, or
424 NULL if there's nothing to do. */
425
426tree
a68ab351 427gfc_omp_clause_default_ctor (tree clause, tree decl, tree outer)
cd75853e 428{
92d28cbb 429 tree type = TREE_TYPE (decl), size, ptr, cond, then_b, else_b;
a68ab351 430 stmtblock_t block, cond_block;
cd75853e 431
92d28cbb
JJ
432 gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_PRIVATE
433 || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LASTPRIVATE
434 || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR
435 || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_REDUCTION);
cd75853e 436
92d28cbb
JJ
437 if ((! GFC_DESCRIPTOR_TYPE_P (type)
438 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
439 && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)))
440 {
441 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
442 {
443 gcc_assert (outer);
444 gfc_start_block (&block);
445 tree tem = gfc_walk_alloc_comps (outer, decl,
446 OMP_CLAUSE_DECL (clause),
447 WALK_ALLOC_COMPS_DEFAULT_CTOR);
448 gfc_add_expr_to_block (&block, tem);
449 return gfc_finish_block (&block);
450 }
451 return NULL_TREE;
452 }
acf0174b 453
92d28cbb 454 gcc_assert (outer != NULL_TREE);
a68ab351 455
92d28cbb 456 /* Allocatable arrays and scalars in PRIVATE clauses need to be set to
a68ab351
JJ
457 "not currently allocated" allocation status if outer
458 array is "not currently allocated", otherwise should be allocated. */
459 gfc_start_block (&block);
460
461 gfc_init_block (&cond_block);
462
92d28cbb
JJ
463 if (GFC_DESCRIPTOR_TYPE_P (type))
464 {
465 gfc_add_modify (&cond_block, decl, outer);
466 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
467 size = gfc_conv_descriptor_ubound_get (decl, rank);
468 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
469 size,
470 gfc_conv_descriptor_lbound_get (decl, rank));
471 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
472 size, gfc_index_one_node);
473 if (GFC_TYPE_ARRAY_RANK (type) > 1)
474 size = fold_build2_loc (input_location, MULT_EXPR,
475 gfc_array_index_type, size,
476 gfc_conv_descriptor_stride_get (decl, rank));
477 tree esize = fold_convert (gfc_array_index_type,
478 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
479 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
480 size, esize);
481 size = unshare_expr (size);
482 size = gfc_evaluate_now (fold_convert (size_type_node, size),
483 &cond_block);
484 }
485 else
486 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
4f13e17f
DC
487 ptr = gfc_create_var (pvoid_type_node, NULL);
488 gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
92d28cbb
JJ
489 if (GFC_DESCRIPTOR_TYPE_P (type))
490 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl), ptr);
491 else
492 gfc_add_modify (&cond_block, unshare_expr (decl),
493 fold_convert (TREE_TYPE (decl), ptr));
494 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
495 {
496 tree tem = gfc_walk_alloc_comps (outer, decl,
497 OMP_CLAUSE_DECL (clause),
498 WALK_ALLOC_COMPS_DEFAULT_CTOR);
499 gfc_add_expr_to_block (&cond_block, tem);
500 }
a68ab351
JJ
501 then_b = gfc_finish_block (&cond_block);
502
92d28cbb
JJ
503 /* Reduction clause requires allocated ALLOCATABLE. */
504 if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_REDUCTION)
505 {
506 gfc_init_block (&cond_block);
507 if (GFC_DESCRIPTOR_TYPE_P (type))
508 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl),
509 null_pointer_node);
510 else
511 gfc_add_modify (&cond_block, unshare_expr (decl),
512 build_zero_cst (TREE_TYPE (decl)));
513 else_b = gfc_finish_block (&cond_block);
514
515 tree tem = fold_convert (pvoid_type_node,
516 GFC_DESCRIPTOR_TYPE_P (type)
517 ? gfc_conv_descriptor_data_get (outer) : outer);
518 tem = unshare_expr (tem);
519 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
520 tem, null_pointer_node);
521 gfc_add_expr_to_block (&block,
522 build3_loc (input_location, COND_EXPR,
523 void_type_node, cond, then_b,
524 else_b));
525 }
526 else
527 gfc_add_expr_to_block (&block, then_b);
cd75853e 528
a68ab351
JJ
529 return gfc_finish_block (&block);
530}
531
532/* Build and return code for a copy constructor from SRC to DEST. */
533
534tree
535gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
536{
92d28cbb 537 tree type = TREE_TYPE (dest), ptr, size, call;
20906c66
JJ
538 tree cond, then_b, else_b;
539 stmtblock_t block, cond_block;
a68ab351 540
92d28cbb
JJ
541 gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE
542 || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
a68ab351 543
92d28cbb
JJ
544 if ((! GFC_DESCRIPTOR_TYPE_P (type)
545 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
546 && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)))
547 {
548 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
549 {
550 gfc_start_block (&block);
551 gfc_add_modify (&block, dest, src);
552 tree tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause),
553 WALK_ALLOC_COMPS_COPY_CTOR);
554 gfc_add_expr_to_block (&block, tem);
555 return gfc_finish_block (&block);
556 }
557 else
558 return build2_v (MODIFY_EXPR, dest, src);
559 }
a68ab351
JJ
560
561 /* Allocatable arrays in FIRSTPRIVATE clauses need to be allocated
562 and copied from SRC. */
563 gfc_start_block (&block);
564
20906c66
JJ
565 gfc_init_block (&cond_block);
566
567 gfc_add_modify (&cond_block, dest, src);
92d28cbb
JJ
568 if (GFC_DESCRIPTOR_TYPE_P (type))
569 {
570 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
571 size = gfc_conv_descriptor_ubound_get (dest, rank);
572 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
573 size,
574 gfc_conv_descriptor_lbound_get (dest, rank));
575 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
576 size, gfc_index_one_node);
577 if (GFC_TYPE_ARRAY_RANK (type) > 1)
578 size = fold_build2_loc (input_location, MULT_EXPR,
579 gfc_array_index_type, size,
580 gfc_conv_descriptor_stride_get (dest, rank));
581 tree esize = fold_convert (gfc_array_index_type,
582 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
583 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
584 size, esize);
585 size = unshare_expr (size);
586 size = gfc_evaluate_now (fold_convert (size_type_node, size),
587 &cond_block);
588 }
589 else
590 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
4f13e17f 591 ptr = gfc_create_var (pvoid_type_node, NULL);
20906c66 592 gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
92d28cbb
JJ
593 if (GFC_DESCRIPTOR_TYPE_P (type))
594 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest), ptr);
595 else
596 gfc_add_modify (&cond_block, unshare_expr (dest),
597 fold_convert (TREE_TYPE (dest), ptr));
4f13e17f 598
92d28cbb
JJ
599 tree srcptr = GFC_DESCRIPTOR_TYPE_P (type)
600 ? gfc_conv_descriptor_data_get (src) : src;
601 srcptr = unshare_expr (srcptr);
602 srcptr = fold_convert (pvoid_type_node, srcptr);
db3927fb 603 call = build_call_expr_loc (input_location,
92d28cbb
JJ
604 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr,
605 srcptr, size);
20906c66 606 gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
92d28cbb
JJ
607 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
608 {
609 tree tem = gfc_walk_alloc_comps (src, dest,
610 OMP_CLAUSE_DECL (clause),
611 WALK_ALLOC_COMPS_COPY_CTOR);
612 gfc_add_expr_to_block (&cond_block, tem);
613 }
20906c66
JJ
614 then_b = gfc_finish_block (&cond_block);
615
616 gfc_init_block (&cond_block);
92d28cbb
JJ
617 if (GFC_DESCRIPTOR_TYPE_P (type))
618 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest),
619 null_pointer_node);
620 else
621 gfc_add_modify (&cond_block, unshare_expr (dest),
622 build_zero_cst (TREE_TYPE (dest)));
20906c66
JJ
623 else_b = gfc_finish_block (&cond_block);
624
625 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
92d28cbb
JJ
626 unshare_expr (srcptr), null_pointer_node);
627 gfc_add_expr_to_block (&block,
628 build3_loc (input_location, COND_EXPR,
629 void_type_node, cond, then_b, else_b));
cd75853e
JJ
630
631 return gfc_finish_block (&block);
632}
633
92d28cbb
JJ
634/* Similarly, except use an intrinsic or pointer assignment operator
635 instead. */
a68ab351
JJ
636
637tree
92d28cbb 638gfc_omp_clause_assign_op (tree clause, tree dest, tree src)
a68ab351 639{
92d28cbb
JJ
640 tree type = TREE_TYPE (dest), ptr, size, call, nonalloc;
641 tree cond, then_b, else_b;
642 stmtblock_t block, cond_block, cond_block2, inner_block;
a68ab351 643
92d28cbb
JJ
644 if ((! GFC_DESCRIPTOR_TYPE_P (type)
645 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
646 && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)))
647 {
648 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
649 {
650 gfc_start_block (&block);
651 /* First dealloc any allocatable components in DEST. */
652 tree tem = gfc_walk_alloc_comps (dest, NULL_TREE,
653 OMP_CLAUSE_DECL (clause),
654 WALK_ALLOC_COMPS_DTOR);
655 gfc_add_expr_to_block (&block, tem);
656 /* Then copy over toplevel data. */
657 gfc_add_modify (&block, dest, src);
658 /* Finally allocate any allocatable components and copy. */
659 tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause),
660 WALK_ALLOC_COMPS_COPY_CTOR);
661 gfc_add_expr_to_block (&block, tem);
662 return gfc_finish_block (&block);
663 }
664 else
665 return build2_v (MODIFY_EXPR, dest, src);
666 }
a68ab351 667
a68ab351
JJ
668 gfc_start_block (&block);
669
92d28cbb
JJ
670 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
671 {
672 then_b = gfc_walk_alloc_comps (dest, NULL_TREE, OMP_CLAUSE_DECL (clause),
673 WALK_ALLOC_COMPS_DTOR);
674 tree tem = fold_convert (pvoid_type_node,
675 GFC_DESCRIPTOR_TYPE_P (type)
676 ? gfc_conv_descriptor_data_get (dest) : dest);
677 tem = unshare_expr (tem);
678 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
679 tem, null_pointer_node);
680 tem = build3_loc (input_location, COND_EXPR, void_type_node, cond,
681 then_b, build_empty_stmt (input_location));
682 gfc_add_expr_to_block (&block, tem);
683 }
684
685 gfc_init_block (&cond_block);
686
687 if (GFC_DESCRIPTOR_TYPE_P (type))
688 {
689 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
690 size = gfc_conv_descriptor_ubound_get (src, rank);
691 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
692 size,
693 gfc_conv_descriptor_lbound_get (src, rank));
694 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
695 size, gfc_index_one_node);
696 if (GFC_TYPE_ARRAY_RANK (type) > 1)
697 size = fold_build2_loc (input_location, MULT_EXPR,
698 gfc_array_index_type, size,
699 gfc_conv_descriptor_stride_get (src, rank));
700 tree esize = fold_convert (gfc_array_index_type,
701 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
702 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
703 size, esize);
704 size = unshare_expr (size);
705 size = gfc_evaluate_now (fold_convert (size_type_node, size),
706 &cond_block);
707 }
708 else
709 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
710 ptr = gfc_create_var (pvoid_type_node, NULL);
711
712 tree destptr = GFC_DESCRIPTOR_TYPE_P (type)
713 ? gfc_conv_descriptor_data_get (dest) : dest;
714 destptr = unshare_expr (destptr);
715 destptr = fold_convert (pvoid_type_node, destptr);
716 gfc_add_modify (&cond_block, ptr, destptr);
717
718 nonalloc = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
719 destptr, null_pointer_node);
720 cond = nonalloc;
721 if (GFC_DESCRIPTOR_TYPE_P (type))
722 {
723 int i;
724 for (i = 0; i < GFC_TYPE_ARRAY_RANK (type); i++)
725 {
726 tree rank = gfc_rank_cst[i];
727 tree tem = gfc_conv_descriptor_ubound_get (src, rank);
728 tem = fold_build2_loc (input_location, MINUS_EXPR,
729 gfc_array_index_type, tem,
730 gfc_conv_descriptor_lbound_get (src, rank));
731 tem = fold_build2_loc (input_location, PLUS_EXPR,
732 gfc_array_index_type, tem,
733 gfc_conv_descriptor_lbound_get (dest, rank));
734 tem = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
735 tem, gfc_conv_descriptor_ubound_get (dest,
736 rank));
737 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
738 boolean_type_node, cond, tem);
739 }
740 }
741
742 gfc_init_block (&cond_block2);
743
744 if (GFC_DESCRIPTOR_TYPE_P (type))
745 {
746 gfc_init_block (&inner_block);
747 gfc_allocate_using_malloc (&inner_block, ptr, size, NULL_TREE);
748 then_b = gfc_finish_block (&inner_block);
749
750 gfc_init_block (&inner_block);
751 gfc_add_modify (&inner_block, ptr,
752 gfc_call_realloc (&inner_block, ptr, size));
753 else_b = gfc_finish_block (&inner_block);
754
755 gfc_add_expr_to_block (&cond_block2,
756 build3_loc (input_location, COND_EXPR,
757 void_type_node,
758 unshare_expr (nonalloc),
759 then_b, else_b));
760 gfc_add_modify (&cond_block2, dest, src);
761 gfc_conv_descriptor_data_set (&cond_block2, unshare_expr (dest), ptr);
762 }
763 else
764 {
765 gfc_allocate_using_malloc (&cond_block2, ptr, size, NULL_TREE);
766 gfc_add_modify (&cond_block2, unshare_expr (dest),
767 fold_convert (type, ptr));
768 }
769 then_b = gfc_finish_block (&cond_block2);
770 else_b = build_empty_stmt (input_location);
771
772 gfc_add_expr_to_block (&cond_block,
773 build3_loc (input_location, COND_EXPR,
774 void_type_node, unshare_expr (cond),
775 then_b, else_b));
776
777 tree srcptr = GFC_DESCRIPTOR_TYPE_P (type)
778 ? gfc_conv_descriptor_data_get (src) : src;
779 srcptr = unshare_expr (srcptr);
780 srcptr = fold_convert (pvoid_type_node, srcptr);
db3927fb 781 call = build_call_expr_loc (input_location,
92d28cbb
JJ
782 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr,
783 srcptr, size);
784 gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
785 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
786 {
787 tree tem = gfc_walk_alloc_comps (src, dest,
788 OMP_CLAUSE_DECL (clause),
789 WALK_ALLOC_COMPS_COPY_CTOR);
790 gfc_add_expr_to_block (&cond_block, tem);
791 }
792 then_b = gfc_finish_block (&cond_block);
793
794 if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_COPYIN)
795 {
796 gfc_init_block (&cond_block);
797 if (GFC_DESCRIPTOR_TYPE_P (type))
798 gfc_add_expr_to_block (&cond_block,
799 gfc_trans_dealloc_allocated (unshare_expr (dest),
800 false, NULL));
801 else
802 {
803 destptr = gfc_evaluate_now (destptr, &cond_block);
804 gfc_add_expr_to_block (&cond_block, gfc_call_free (destptr));
805 gfc_add_modify (&cond_block, unshare_expr (dest),
806 build_zero_cst (TREE_TYPE (dest)));
807 }
808 else_b = gfc_finish_block (&cond_block);
809
810 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
811 unshare_expr (srcptr), null_pointer_node);
812 gfc_add_expr_to_block (&block,
813 build3_loc (input_location, COND_EXPR,
814 void_type_node, cond,
815 then_b, else_b));
816 }
817 else
818 gfc_add_expr_to_block (&block, then_b);
a68ab351
JJ
819
820 return gfc_finish_block (&block);
821}
822
823/* Build and return code destructing DECL. Return NULL if nothing
824 to be done. */
825
826tree
92d28cbb 827gfc_omp_clause_dtor (tree clause, tree decl)
a68ab351 828{
92d28cbb 829 tree type = TREE_TYPE (decl), tem;
a68ab351 830
92d28cbb
JJ
831 if ((! GFC_DESCRIPTOR_TYPE_P (type)
832 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
833 && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)))
834 {
835 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
836 return gfc_walk_alloc_comps (decl, NULL_TREE,
837 OMP_CLAUSE_DECL (clause),
838 WALK_ALLOC_COMPS_DTOR);
839 return NULL_TREE;
840 }
a68ab351 841
92d28cbb
JJ
842 if (GFC_DESCRIPTOR_TYPE_P (type))
843 /* Allocatable arrays in FIRSTPRIVATE/LASTPRIVATE etc. clauses need
844 to be deallocated if they were allocated. */
845 tem = gfc_trans_dealloc_allocated (decl, false, NULL);
846 else
847 tem = gfc_call_free (decl);
848 tem = gfc_omp_unshare_expr (tem);
acf0174b 849
92d28cbb
JJ
850 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
851 {
852 stmtblock_t block;
853 tree then_b;
854
855 gfc_init_block (&block);
856 gfc_add_expr_to_block (&block,
857 gfc_walk_alloc_comps (decl, NULL_TREE,
858 OMP_CLAUSE_DECL (clause),
859 WALK_ALLOC_COMPS_DTOR));
860 gfc_add_expr_to_block (&block, tem);
861 then_b = gfc_finish_block (&block);
862
863 tem = fold_convert (pvoid_type_node,
864 GFC_DESCRIPTOR_TYPE_P (type)
865 ? gfc_conv_descriptor_data_get (decl) : decl);
866 tem = unshare_expr (tem);
867 tree cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
868 tem, null_pointer_node);
869 tem = build3_loc (input_location, COND_EXPR, void_type_node, cond,
870 then_b, build_empty_stmt (input_location));
871 }
872 return tem;
a68ab351
JJ
873}
874
cd75853e 875
f014c653
JJ
876void
877gfc_omp_finish_clause (tree c, gimple_seq *pre_p)
878{
879 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
880 return;
881
882 tree decl = OMP_CLAUSE_DECL (c);
883 tree c2 = NULL_TREE, c3 = NULL_TREE, c4 = NULL_TREE;
884 if (POINTER_TYPE_P (TREE_TYPE (decl)))
885 {
886 if (!gfc_omp_privatize_by_reference (decl)
887 && !GFC_DECL_GET_SCALAR_POINTER (decl)
888 && !GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
889 && !GFC_DECL_CRAY_POINTEE (decl)
890 && !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
891 return;
892 c4 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
893 OMP_CLAUSE_MAP_KIND (c4) = OMP_CLAUSE_MAP_POINTER;
894 OMP_CLAUSE_DECL (c4) = decl;
895 OMP_CLAUSE_SIZE (c4) = size_int (0);
896 decl = build_fold_indirect_ref (decl);
897 OMP_CLAUSE_DECL (c) = decl;
898 }
899 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
900 {
901 stmtblock_t block;
902 gfc_start_block (&block);
903 tree type = TREE_TYPE (decl);
904 tree ptr = gfc_conv_descriptor_data_get (decl);
905 ptr = fold_convert (build_pointer_type (char_type_node), ptr);
906 ptr = build_fold_indirect_ref (ptr);
907 OMP_CLAUSE_DECL (c) = ptr;
908 c2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
909 OMP_CLAUSE_MAP_KIND (c2) = OMP_CLAUSE_MAP_TO_PSET;
910 OMP_CLAUSE_DECL (c2) = decl;
911 OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (type);
912 c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
913 OMP_CLAUSE_MAP_KIND (c3) = OMP_CLAUSE_MAP_POINTER;
914 OMP_CLAUSE_DECL (c3) = gfc_conv_descriptor_data_get (decl);
915 OMP_CLAUSE_SIZE (c3) = size_int (0);
916 tree size = create_tmp_var (gfc_array_index_type, NULL);
917 tree elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
918 elemsz = fold_convert (gfc_array_index_type, elemsz);
919 if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER
920 || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT)
921 {
922 stmtblock_t cond_block;
923 tree tem, then_b, else_b, zero, cond;
924
925 gfc_init_block (&cond_block);
926 tem = gfc_full_array_size (&cond_block, decl,
927 GFC_TYPE_ARRAY_RANK (type));
928 gfc_add_modify (&cond_block, size, tem);
929 gfc_add_modify (&cond_block, size,
930 fold_build2 (MULT_EXPR, gfc_array_index_type,
931 size, elemsz));
932 then_b = gfc_finish_block (&cond_block);
933 gfc_init_block (&cond_block);
934 zero = build_int_cst (gfc_array_index_type, 0);
935 gfc_add_modify (&cond_block, size, zero);
936 else_b = gfc_finish_block (&cond_block);
937 tem = gfc_conv_descriptor_data_get (decl);
938 tem = fold_convert (pvoid_type_node, tem);
939 cond = fold_build2_loc (input_location, NE_EXPR,
940 boolean_type_node, tem, null_pointer_node);
941 gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR,
942 void_type_node, cond,
943 then_b, else_b));
944 }
945 else
946 {
947 gfc_add_modify (&block, size,
948 gfc_full_array_size (&block, decl,
949 GFC_TYPE_ARRAY_RANK (type)));
950 gfc_add_modify (&block, size,
951 fold_build2 (MULT_EXPR, gfc_array_index_type,
952 size, elemsz));
953 }
954 OMP_CLAUSE_SIZE (c) = size;
955 tree stmt = gfc_finish_block (&block);
956 gimplify_and_add (stmt, pre_p);
957 }
958 tree last = c;
959 if (c2)
960 {
961 OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (last);
962 OMP_CLAUSE_CHAIN (last) = c2;
963 last = c2;
964 }
965 if (c3)
966 {
967 OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (last);
968 OMP_CLAUSE_CHAIN (last) = c3;
969 last = c3;
970 }
971 if (c4)
972 {
973 OMP_CLAUSE_CHAIN (c4) = OMP_CLAUSE_CHAIN (last);
974 OMP_CLAUSE_CHAIN (last) = c4;
975 last = c4;
976 }
977}
978
979
6c7a4dfd
JJ
980/* Return true if DECL's DECL_VALUE_EXPR (if any) should be
981 disregarded in OpenMP construct, because it is going to be
982 remapped during OpenMP lowering. SHARED is true if DECL
983 is going to be shared, false if it is going to be privatized. */
984
985bool
986gfc_omp_disregard_value_expr (tree decl, bool shared)
987{
988 if (GFC_DECL_COMMON_OR_EQUIV (decl)
989 && DECL_HAS_VALUE_EXPR_P (decl))
990 {
991 tree value = DECL_VALUE_EXPR (decl);
992
993 if (TREE_CODE (value) == COMPONENT_REF
994 && TREE_CODE (TREE_OPERAND (value, 0)) == VAR_DECL
995 && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
996 {
997 /* If variable in COMMON or EQUIVALENCE is privatized, return
998 true, as just that variable is supposed to be privatized,
999 not the whole COMMON or whole EQUIVALENCE.
1000 For shared variables in COMMON or EQUIVALENCE, let them be
1001 gimplified to DECL_VALUE_EXPR, so that for multiple shared vars
1002 from the same COMMON or EQUIVALENCE just one sharing of the
1003 whole COMMON or EQUIVALENCE is enough. */
1004 return ! shared;
1005 }
1006 }
1007
1008 if (GFC_DECL_RESULT (decl) && DECL_HAS_VALUE_EXPR_P (decl))
1009 return ! shared;
1010
1011 return false;
1012}
1013
1014/* Return true if DECL that is shared iff SHARED is true should
1015 be put into OMP_CLAUSE_PRIVATE with OMP_CLAUSE_PRIVATE_DEBUG
1016 flag set. */
1017
1018bool
1019gfc_omp_private_debug_clause (tree decl, bool shared)
1020{
1021 if (GFC_DECL_CRAY_POINTEE (decl))
1022 return true;
1023
1024 if (GFC_DECL_COMMON_OR_EQUIV (decl)
1025 && DECL_HAS_VALUE_EXPR_P (decl))
1026 {
1027 tree value = DECL_VALUE_EXPR (decl);
1028
1029 if (TREE_CODE (value) == COMPONENT_REF
1030 && TREE_CODE (TREE_OPERAND (value, 0)) == VAR_DECL
1031 && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
1032 return shared;
1033 }
1034
1035 return false;
1036}
1037
1038/* Register language specific type size variables as potentially OpenMP
1039 firstprivate variables. */
1040
1041void
1042gfc_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
1043{
1044 if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
1045 {
1046 int r;
1047
1048 gcc_assert (TYPE_LANG_SPECIFIC (type) != NULL);
1049 for (r = 0; r < GFC_TYPE_ARRAY_RANK (type); r++)
1050 {
1051 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_LBOUND (type, r));
1052 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_UBOUND (type, r));
1053 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_STRIDE (type, r));
1054 }
1055 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_SIZE (type));
1056 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_OFFSET (type));
1057 }
1058}
1059
1060
1061static inline tree
1062gfc_trans_add_clause (tree node, tree tail)
1063{
1064 OMP_CLAUSE_CHAIN (node) = tail;
1065 return node;
1066}
1067
1068static tree
dd2fc525 1069gfc_trans_omp_variable (gfc_symbol *sym, bool declare_simd)
6c7a4dfd 1070{
dd2fc525
JJ
1071 if (declare_simd)
1072 {
1073 int cnt = 0;
1074 gfc_symbol *proc_sym;
1075 gfc_formal_arglist *f;
1076
1077 gcc_assert (sym->attr.dummy);
1078 proc_sym = sym->ns->proc_name;
1079 if (proc_sym->attr.entry_master)
1080 ++cnt;
1081 if (gfc_return_by_reference (proc_sym))
1082 {
1083 ++cnt;
1084 if (proc_sym->ts.type == BT_CHARACTER)
1085 ++cnt;
1086 }
1087 for (f = gfc_sym_get_dummy_args (proc_sym); f; f = f->next)
1088 if (f->sym == sym)
1089 break;
1090 else if (f->sym)
1091 ++cnt;
1092 gcc_assert (f);
1093 return build_int_cst (integer_type_node, cnt);
1094 }
1095
6c7a4dfd 1096 tree t = gfc_get_symbol_decl (sym);
11a5f608
JJ
1097 tree parent_decl;
1098 int parent_flag;
1099 bool return_value;
1100 bool alternate_entry;
1101 bool entry_master;
1102
1103 return_value = sym->attr.function && sym->result == sym;
1104 alternate_entry = sym->attr.function && sym->attr.entry
1105 && sym->result == sym;
1106 entry_master = sym->attr.result
1107 && sym->ns->proc_name->attr.entry_master
1108 && !gfc_return_by_reference (sym->ns->proc_name);
dd2fc525
JJ
1109 parent_decl = current_function_decl
1110 ? DECL_CONTEXT (current_function_decl) : NULL_TREE;
11a5f608
JJ
1111
1112 if ((t == parent_decl && return_value)
1113 || (sym->ns && sym->ns->proc_name
1114 && sym->ns->proc_name->backend_decl == parent_decl
1115 && (alternate_entry || entry_master)))
1116 parent_flag = 1;
1117 else
1118 parent_flag = 0;
6c7a4dfd
JJ
1119
1120 /* Special case for assigning the return value of a function.
1121 Self recursive functions must have an explicit return value. */
11a5f608
JJ
1122 if (return_value && (t == current_function_decl || parent_flag))
1123 t = gfc_get_fake_result_decl (sym, parent_flag);
6c7a4dfd
JJ
1124
1125 /* Similarly for alternate entry points. */
11a5f608
JJ
1126 else if (alternate_entry
1127 && (sym->ns->proc_name->backend_decl == current_function_decl
1128 || parent_flag))
6c7a4dfd
JJ
1129 {
1130 gfc_entry_list *el = NULL;
1131
1132 for (el = sym->ns->entries; el; el = el->next)
1133 if (sym == el->sym)
1134 {
11a5f608 1135 t = gfc_get_fake_result_decl (sym, parent_flag);
6c7a4dfd
JJ
1136 break;
1137 }
1138 }
1139
11a5f608
JJ
1140 else if (entry_master
1141 && (sym->ns->proc_name->backend_decl == current_function_decl
1142 || parent_flag))
1143 t = gfc_get_fake_result_decl (sym, parent_flag);
6c7a4dfd
JJ
1144
1145 return t;
1146}
1147
1148static tree
dd2fc525
JJ
1149gfc_trans_omp_variable_list (enum omp_clause_code code,
1150 gfc_omp_namelist *namelist, tree list,
1151 bool declare_simd)
6c7a4dfd
JJ
1152{
1153 for (; namelist != NULL; namelist = namelist->next)
dd2fc525 1154 if (namelist->sym->attr.referenced || declare_simd)
6c7a4dfd 1155 {
dd2fc525 1156 tree t = gfc_trans_omp_variable (namelist->sym, declare_simd);
6c7a4dfd
JJ
1157 if (t != error_mark_node)
1158 {
c2255bc4 1159 tree node = build_omp_clause (input_location, code);
6c7a4dfd
JJ
1160 OMP_CLAUSE_DECL (node) = t;
1161 list = gfc_trans_add_clause (node, list);
1162 }
1163 }
1164 return list;
1165}
1166
5f23671d
JJ
1167struct omp_udr_find_orig_data
1168{
1169 gfc_omp_udr *omp_udr;
1170 bool omp_orig_seen;
1171};
1172
1173static int
1174omp_udr_find_orig (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
1175 void *data)
1176{
1177 struct omp_udr_find_orig_data *cd = (struct omp_udr_find_orig_data *) data;
1178 if ((*e)->expr_type == EXPR_VARIABLE
1179 && (*e)->symtree->n.sym == cd->omp_udr->omp_orig)
1180 cd->omp_orig_seen = true;
1181
1182 return 0;
1183}
1184
1185static tree
1186gfc_trans_omp_udr_expr (gfc_omp_namelist *n, bool is_initializer,
1187 gfc_expr *syme, gfc_expr *outere)
1188{
1189 gfc_se symse, outerse;
1190 gfc_ss *symss, *outerss;
1191 gfc_loopinfo loop;
1192 stmtblock_t block, body;
1193 tree tem;
1194 int i;
1195 gfc_namespace *ns = (is_initializer
1196 ? n->udr->initializer_ns : n->udr->combiner_ns);
1197
1198 syme = gfc_copy_expr (syme);
1199 outere = gfc_copy_expr (outere);
1200 gfc_init_se (&symse, NULL);
1201 gfc_init_se (&outerse, NULL);
1202 gfc_start_block (&block);
1203 gfc_init_loopinfo (&loop);
1204 symss = gfc_walk_expr (syme);
1205 outerss = gfc_walk_expr (outere);
1206 gfc_add_ss_to_loop (&loop, symss);
1207 gfc_add_ss_to_loop (&loop, outerss);
1208 gfc_conv_ss_startstride (&loop);
1209 /* Enable loop reversal. */
1210 for (i = 0; i < GFC_MAX_DIMENSIONS; i++)
1211 loop.reverse[i] = GFC_ENABLE_REVERSE;
1212 gfc_conv_loop_setup (&loop, &ns->code->loc);
1213 gfc_copy_loopinfo_to_se (&symse, &loop);
1214 gfc_copy_loopinfo_to_se (&outerse, &loop);
1215 symse.ss = symss;
1216 outerse.ss = outerss;
1217 gfc_mark_ss_chain_used (symss, 1);
1218 gfc_mark_ss_chain_used (outerss, 1);
1219 gfc_start_scalarized_body (&loop, &body);
1220 gfc_conv_expr (&symse, syme);
1221 gfc_conv_expr (&outerse, outere);
1222
1223 if (is_initializer)
1224 {
1225 n->udr->omp_priv->backend_decl = symse.expr;
1226 n->udr->omp_orig->backend_decl = outerse.expr;
1227 }
1228 else
1229 {
1230 n->udr->omp_out->backend_decl = outerse.expr;
1231 n->udr->omp_in->backend_decl = symse.expr;
1232 }
1233
1234 if (ns->code->op == EXEC_ASSIGN)
1235 tem = gfc_trans_assignment (ns->code->expr1, ns->code->expr2,
1236 false, false);
1237 else
1238 tem = gfc_trans_call (ns->code, false, NULL_TREE, NULL_TREE, false);
1239 gfc_add_expr_to_block (&body, tem);
1240
1241 gcc_assert (symse.ss == gfc_ss_terminator
1242 && outerse.ss == gfc_ss_terminator);
1243 /* Generate the copying loops. */
1244 gfc_trans_scalarizing_loops (&loop, &body);
1245
1246 /* Wrap the whole thing up. */
1247 gfc_add_block_to_block (&block, &loop.pre);
1248 gfc_add_block_to_block (&block, &loop.post);
1249
1250 gfc_cleanup_loop (&loop);
1251 gfc_free_expr (syme);
1252 gfc_free_expr (outere);
1253
1254 return gfc_finish_block (&block);
1255}
1256
6c7a4dfd 1257static void
5f23671d 1258gfc_trans_omp_array_reduction_or_udr (tree c, gfc_omp_namelist *n, locus where)
6c7a4dfd 1259{
5f23671d 1260 gfc_symbol *sym = n->sym;
6c7a4dfd
JJ
1261 gfc_symtree *root1 = NULL, *root2 = NULL, *root3 = NULL, *root4 = NULL;
1262 gfc_symtree *symtree1, *symtree2, *symtree3, *symtree4 = NULL;
1263 gfc_symbol init_val_sym, outer_sym, intrinsic_sym;
5f23671d 1264 gfc_symbol omp_var_copy[4];
6c7a4dfd
JJ
1265 gfc_expr *e1, *e2, *e3, *e4;
1266 gfc_ref *ref;
af3fcdb4 1267 tree decl, backend_decl, stmt, type, outer_decl;
6c7a4dfd
JJ
1268 locus old_loc = gfc_current_locus;
1269 const char *iname;
524af0d6 1270 bool t;
6c7a4dfd
JJ
1271
1272 decl = OMP_CLAUSE_DECL (c);
1273 gfc_current_locus = where;
af3fcdb4
JJ
1274 type = TREE_TYPE (decl);
1275 outer_decl = create_tmp_var_raw (type, NULL);
1276 if (TREE_CODE (decl) == PARM_DECL
1277 && TREE_CODE (type) == REFERENCE_TYPE
1278 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type))
1279 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (type)) == GFC_ARRAY_ALLOCATABLE)
1280 {
1281 decl = build_fold_indirect_ref (decl);
1282 type = TREE_TYPE (type);
1283 }
6c7a4dfd
JJ
1284
1285 /* Create a fake symbol for init value. */
1286 memset (&init_val_sym, 0, sizeof (init_val_sym));
1287 init_val_sym.ns = sym->ns;
1288 init_val_sym.name = sym->name;
1289 init_val_sym.ts = sym->ts;
1290 init_val_sym.attr.referenced = 1;
1291 init_val_sym.declared_at = where;
a7a53ca5 1292 init_val_sym.attr.flavor = FL_VARIABLE;
5f23671d
JJ
1293 if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK)
1294 backend_decl = omp_reduction_init (c, gfc_sym_type (&init_val_sym));
1295 else if (n->udr->initializer_ns)
1296 backend_decl = NULL;
1297 else
1298 switch (sym->ts.type)
1299 {
1300 case BT_LOGICAL:
1301 case BT_INTEGER:
1302 case BT_REAL:
1303 case BT_COMPLEX:
1304 backend_decl = build_zero_cst (gfc_sym_type (&init_val_sym));
1305 break;
1306 default:
1307 backend_decl = NULL_TREE;
1308 break;
1309 }
6c7a4dfd
JJ
1310 init_val_sym.backend_decl = backend_decl;
1311
1312 /* Create a fake symbol for the outer array reference. */
1313 outer_sym = *sym;
5f23671d
JJ
1314 if (sym->as)
1315 outer_sym.as = gfc_copy_array_spec (sym->as);
6c7a4dfd
JJ
1316 outer_sym.attr.dummy = 0;
1317 outer_sym.attr.result = 0;
a7a53ca5 1318 outer_sym.attr.flavor = FL_VARIABLE;
af3fcdb4
JJ
1319 outer_sym.backend_decl = outer_decl;
1320 if (decl != OMP_CLAUSE_DECL (c))
1321 outer_sym.backend_decl = build_fold_indirect_ref (outer_decl);
6c7a4dfd
JJ
1322
1323 /* Create fake symtrees for it. */
1324 symtree1 = gfc_new_symtree (&root1, sym->name);
1325 symtree1->n.sym = sym;
1326 gcc_assert (symtree1 == root1);
1327
1328 symtree2 = gfc_new_symtree (&root2, sym->name);
1329 symtree2->n.sym = &init_val_sym;
1330 gcc_assert (symtree2 == root2);
1331
1332 symtree3 = gfc_new_symtree (&root3, sym->name);
1333 symtree3->n.sym = &outer_sym;
1334 gcc_assert (symtree3 == root3);
1335
5f23671d
JJ
1336 memset (omp_var_copy, 0, sizeof omp_var_copy);
1337 if (n->udr)
1338 {
1339 omp_var_copy[0] = *n->udr->omp_out;
1340 omp_var_copy[1] = *n->udr->omp_in;
1341 if (sym->attr.dimension)
1342 {
1343 n->udr->omp_out->ts = sym->ts;
1344 n->udr->omp_in->ts = sym->ts;
1345 }
1346 else
1347 {
1348 *n->udr->omp_out = outer_sym;
1349 *n->udr->omp_in = *sym;
1350 }
1351 if (n->udr->initializer_ns)
1352 {
1353 omp_var_copy[2] = *n->udr->omp_priv;
1354 omp_var_copy[3] = *n->udr->omp_orig;
1355 if (sym->attr.dimension)
1356 {
1357 n->udr->omp_priv->ts = sym->ts;
1358 n->udr->omp_orig->ts = sym->ts;
1359 }
1360 else
1361 {
1362 *n->udr->omp_priv = *sym;
1363 *n->udr->omp_orig = outer_sym;
1364 }
1365 }
1366 }
1367
6c7a4dfd
JJ
1368 /* Create expressions. */
1369 e1 = gfc_get_expr ();
1370 e1->expr_type = EXPR_VARIABLE;
1371 e1->where = where;
1372 e1->symtree = symtree1;
1373 e1->ts = sym->ts;
5f23671d
JJ
1374 if (sym->attr.dimension)
1375 {
1376 e1->ref = ref = gfc_get_ref ();
1377 ref->type = REF_ARRAY;
1378 ref->u.ar.where = where;
1379 ref->u.ar.as = sym->as;
1380 ref->u.ar.type = AR_FULL;
1381 ref->u.ar.dimen = 0;
1382 }
6c7a4dfd 1383 t = gfc_resolve_expr (e1);
524af0d6 1384 gcc_assert (t);
6c7a4dfd 1385
5f23671d
JJ
1386 e2 = NULL;
1387 if (backend_decl != NULL_TREE)
1388 {
1389 e2 = gfc_get_expr ();
1390 e2->expr_type = EXPR_VARIABLE;
1391 e2->where = where;
1392 e2->symtree = symtree2;
1393 e2->ts = sym->ts;
1394 t = gfc_resolve_expr (e2);
1395 gcc_assert (t);
1396 }
1397 else if (n->udr->initializer_ns == NULL)
1398 {
1399 gcc_assert (sym->ts.type == BT_DERIVED);
1400 e2 = gfc_default_initializer (&sym->ts);
1401 gcc_assert (e2);
1402 t = gfc_resolve_expr (e2);
1403 gcc_assert (t);
1404 }
1405 else if (n->udr->initializer_ns->code->op == EXEC_ASSIGN)
1406 {
1407 if (!sym->attr.dimension)
1408 {
1409 e2 = gfc_copy_expr (n->udr->initializer_ns->code->expr2);
1410 t = gfc_resolve_expr (e2);
1411 gcc_assert (t);
1412 }
1413 }
1414 if (n->udr && n->udr->initializer_ns)
1415 {
1416 struct omp_udr_find_orig_data cd;
1417 cd.omp_udr = n->udr;
1418 cd.omp_orig_seen = false;
1419 gfc_code_walker (&n->udr->initializer_ns->code,
1420 gfc_dummy_code_callback, omp_udr_find_orig, &cd);
1421 if (cd.omp_orig_seen)
1422 OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c) = 1;
1423 }
6c7a4dfd
JJ
1424
1425 e3 = gfc_copy_expr (e1);
1426 e3->symtree = symtree3;
1427 t = gfc_resolve_expr (e3);
524af0d6 1428 gcc_assert (t);
6c7a4dfd
JJ
1429
1430 iname = NULL;
5f23671d 1431 e4 = NULL;
6c7a4dfd
JJ
1432 switch (OMP_CLAUSE_REDUCTION_CODE (c))
1433 {
1434 case PLUS_EXPR:
1435 case MINUS_EXPR:
1436 e4 = gfc_add (e3, e1);
1437 break;
1438 case MULT_EXPR:
1439 e4 = gfc_multiply (e3, e1);
1440 break;
1441 case TRUTH_ANDIF_EXPR:
1442 e4 = gfc_and (e3, e1);
1443 break;
1444 case TRUTH_ORIF_EXPR:
1445 e4 = gfc_or (e3, e1);
1446 break;
1447 case EQ_EXPR:
1448 e4 = gfc_eqv (e3, e1);
1449 break;
1450 case NE_EXPR:
1451 e4 = gfc_neqv (e3, e1);
1452 break;
1453 case MIN_EXPR:
1454 iname = "min";
1455 break;
1456 case MAX_EXPR:
1457 iname = "max";
1458 break;
1459 case BIT_AND_EXPR:
1460 iname = "iand";
1461 break;
1462 case BIT_IOR_EXPR:
1463 iname = "ior";
1464 break;
1465 case BIT_XOR_EXPR:
1466 iname = "ieor";
1467 break;
5f23671d
JJ
1468 case ERROR_MARK:
1469 if (n->udr->combiner_ns->code->op == EXEC_ASSIGN)
1470 {
1471 if (!sym->attr.dimension)
1472 {
1473 gfc_free_expr (e3);
1474 e3 = gfc_copy_expr (n->udr->combiner_ns->code->expr1);
1475 e4 = gfc_copy_expr (n->udr->combiner_ns->code->expr2);
1476 t = gfc_resolve_expr (e3);
1477 gcc_assert (t);
1478 t = gfc_resolve_expr (e4);
1479 gcc_assert (t);
1480 }
1481 }
1482 break;
6c7a4dfd
JJ
1483 default:
1484 gcc_unreachable ();
1485 }
1486 if (iname != NULL)
1487 {
1488 memset (&intrinsic_sym, 0, sizeof (intrinsic_sym));
1489 intrinsic_sym.ns = sym->ns;
1490 intrinsic_sym.name = iname;
1491 intrinsic_sym.ts = sym->ts;
1492 intrinsic_sym.attr.referenced = 1;
1493 intrinsic_sym.attr.intrinsic = 1;
1494 intrinsic_sym.attr.function = 1;
1495 intrinsic_sym.result = &intrinsic_sym;
1496 intrinsic_sym.declared_at = where;
1497
1498 symtree4 = gfc_new_symtree (&root4, iname);
1499 symtree4->n.sym = &intrinsic_sym;
1500 gcc_assert (symtree4 == root4);
1501
1502 e4 = gfc_get_expr ();
1503 e4->expr_type = EXPR_FUNCTION;
1504 e4->where = where;
1505 e4->symtree = symtree4;
1506 e4->value.function.isym = gfc_find_function (iname);
1507 e4->value.function.actual = gfc_get_actual_arglist ();
1508 e4->value.function.actual->expr = e3;
1509 e4->value.function.actual->next = gfc_get_actual_arglist ();
1510 e4->value.function.actual->next->expr = e1;
1511 }
5f23671d
JJ
1512 if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK)
1513 {
1514 /* e1 and e3 have been stored as arguments of e4, avoid sharing. */
1515 e1 = gfc_copy_expr (e1);
1516 e3 = gfc_copy_expr (e3);
1517 t = gfc_resolve_expr (e4);
1518 gcc_assert (t);
1519 }
6c7a4dfd
JJ
1520
1521 /* Create the init statement list. */
87a60f68 1522 pushlevel ();
92d28cbb 1523 if (e2)
2b56d6a4 1524 stmt = gfc_trans_assignment (e1, e2, false, false);
5f23671d
JJ
1525 else if (sym->attr.dimension)
1526 stmt = gfc_trans_omp_udr_expr (n, true, e1, e3);
1527 else
1528 stmt = gfc_trans_call (n->udr->initializer_ns->code, false,
1529 NULL_TREE, NULL_TREE, false);
5b8fdd1f 1530 if (TREE_CODE (stmt) != BIND_EXPR)
87a60f68 1531 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5b8fdd1f 1532 else
87a60f68 1533 poplevel (0, 0);
5b8fdd1f 1534 OMP_CLAUSE_REDUCTION_INIT (c) = stmt;
6c7a4dfd
JJ
1535
1536 /* Create the merge statement list. */
87a60f68 1537 pushlevel ();
92d28cbb 1538 if (e4)
2b56d6a4 1539 stmt = gfc_trans_assignment (e3, e4, false, true);
5f23671d
JJ
1540 else if (sym->attr.dimension)
1541 stmt = gfc_trans_omp_udr_expr (n, false, e1, e3);
1542 else
1543 stmt = gfc_trans_call (n->udr->combiner_ns->code, false,
1544 NULL_TREE, NULL_TREE, false);
5b8fdd1f 1545 if (TREE_CODE (stmt) != BIND_EXPR)
87a60f68 1546 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5b8fdd1f 1547 else
87a60f68 1548 poplevel (0, 0);
5b8fdd1f 1549 OMP_CLAUSE_REDUCTION_MERGE (c) = stmt;
6c7a4dfd
JJ
1550
1551 /* And stick the placeholder VAR_DECL into the clause as well. */
af3fcdb4 1552 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = outer_decl;
6c7a4dfd
JJ
1553
1554 gfc_current_locus = old_loc;
1555
1556 gfc_free_expr (e1);
5f23671d
JJ
1557 if (e2)
1558 gfc_free_expr (e2);
6c7a4dfd 1559 gfc_free_expr (e3);
5f23671d
JJ
1560 if (e4)
1561 gfc_free_expr (e4);
cede9502
JM
1562 free (symtree1);
1563 free (symtree2);
1564 free (symtree3);
04695783 1565 free (symtree4);
5f23671d
JJ
1566 if (outer_sym.as)
1567 gfc_free_array_spec (outer_sym.as);
1568
1569 if (n->udr)
1570 {
1571 *n->udr->omp_out = omp_var_copy[0];
1572 *n->udr->omp_in = omp_var_copy[1];
1573 if (n->udr->initializer_ns)
1574 {
1575 *n->udr->omp_priv = omp_var_copy[2];
1576 *n->udr->omp_orig = omp_var_copy[3];
1577 }
1578 }
6c7a4dfd
JJ
1579}
1580
1581static tree
dd2fc525 1582gfc_trans_omp_reduction_list (gfc_omp_namelist *namelist, tree list,
5f23671d 1583 locus where)
6c7a4dfd
JJ
1584{
1585 for (; namelist != NULL; namelist = namelist->next)
1586 if (namelist->sym->attr.referenced)
1587 {
dd2fc525 1588 tree t = gfc_trans_omp_variable (namelist->sym, false);
6c7a4dfd
JJ
1589 if (t != error_mark_node)
1590 {
c2255bc4
AH
1591 tree node = build_omp_clause (where.lb->location,
1592 OMP_CLAUSE_REDUCTION);
6c7a4dfd 1593 OMP_CLAUSE_DECL (node) = t;
f014c653 1594 switch (namelist->u.reduction_op)
5f23671d
JJ
1595 {
1596 case OMP_REDUCTION_PLUS:
1597 OMP_CLAUSE_REDUCTION_CODE (node) = PLUS_EXPR;
1598 break;
1599 case OMP_REDUCTION_MINUS:
1600 OMP_CLAUSE_REDUCTION_CODE (node) = MINUS_EXPR;
1601 break;
1602 case OMP_REDUCTION_TIMES:
1603 OMP_CLAUSE_REDUCTION_CODE (node) = MULT_EXPR;
1604 break;
1605 case OMP_REDUCTION_AND:
1606 OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ANDIF_EXPR;
1607 break;
1608 case OMP_REDUCTION_OR:
1609 OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ORIF_EXPR;
1610 break;
1611 case OMP_REDUCTION_EQV:
1612 OMP_CLAUSE_REDUCTION_CODE (node) = EQ_EXPR;
1613 break;
1614 case OMP_REDUCTION_NEQV:
1615 OMP_CLAUSE_REDUCTION_CODE (node) = NE_EXPR;
1616 break;
1617 case OMP_REDUCTION_MAX:
1618 OMP_CLAUSE_REDUCTION_CODE (node) = MAX_EXPR;
1619 break;
1620 case OMP_REDUCTION_MIN:
1621 OMP_CLAUSE_REDUCTION_CODE (node) = MIN_EXPR;
1622 break;
1623 case OMP_REDUCTION_IAND:
1624 OMP_CLAUSE_REDUCTION_CODE (node) = BIT_AND_EXPR;
1625 break;
1626 case OMP_REDUCTION_IOR:
1627 OMP_CLAUSE_REDUCTION_CODE (node) = BIT_IOR_EXPR;
1628 break;
1629 case OMP_REDUCTION_IEOR:
1630 OMP_CLAUSE_REDUCTION_CODE (node) = BIT_XOR_EXPR;
1631 break;
1632 case OMP_REDUCTION_USER:
1633 OMP_CLAUSE_REDUCTION_CODE (node) = ERROR_MARK;
1634 break;
1635 default:
1636 gcc_unreachable ();
1637 }
1638 if (namelist->sym->attr.dimension
f014c653 1639 || namelist->u.reduction_op == OMP_REDUCTION_USER
92d28cbb 1640 || namelist->sym->attr.allocatable)
5f23671d 1641 gfc_trans_omp_array_reduction_or_udr (node, namelist, where);
6c7a4dfd
JJ
1642 list = gfc_trans_add_clause (node, list);
1643 }
1644 }
1645 return list;
1646}
1647
1648static tree
1649gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
dd2fc525 1650 locus where, bool declare_simd = false)
6c7a4dfd 1651{
c4fae39e 1652 tree omp_clauses = NULL_TREE, chunk_size, c;
6c7a4dfd
JJ
1653 int list;
1654 enum omp_clause_code clause_code;
1655 gfc_se se;
1656
1657 if (clauses == NULL)
1658 return NULL_TREE;
1659
1660 for (list = 0; list < OMP_LIST_NUM; list++)
1661 {
dd2fc525 1662 gfc_omp_namelist *n = clauses->lists[list];
6c7a4dfd
JJ
1663
1664 if (n == NULL)
1665 continue;
6c7a4dfd
JJ
1666 switch (list)
1667 {
5f23671d
JJ
1668 case OMP_LIST_REDUCTION:
1669 omp_clauses = gfc_trans_omp_reduction_list (n, omp_clauses, where);
1670 break;
6c7a4dfd
JJ
1671 case OMP_LIST_PRIVATE:
1672 clause_code = OMP_CLAUSE_PRIVATE;
1673 goto add_clause;
1674 case OMP_LIST_SHARED:
1675 clause_code = OMP_CLAUSE_SHARED;
1676 goto add_clause;
1677 case OMP_LIST_FIRSTPRIVATE:
1678 clause_code = OMP_CLAUSE_FIRSTPRIVATE;
1679 goto add_clause;
1680 case OMP_LIST_LASTPRIVATE:
1681 clause_code = OMP_CLAUSE_LASTPRIVATE;
1682 goto add_clause;
1683 case OMP_LIST_COPYIN:
1684 clause_code = OMP_CLAUSE_COPYIN;
1685 goto add_clause;
1686 case OMP_LIST_COPYPRIVATE:
1687 clause_code = OMP_CLAUSE_COPYPRIVATE;
dd2fc525
JJ
1688 goto add_clause;
1689 case OMP_LIST_UNIFORM:
1690 clause_code = OMP_CLAUSE_UNIFORM;
6c7a4dfd
JJ
1691 /* FALLTHROUGH */
1692 add_clause:
1693 omp_clauses
dd2fc525
JJ
1694 = gfc_trans_omp_variable_list (clause_code, n, omp_clauses,
1695 declare_simd);
1696 break;
1697 case OMP_LIST_ALIGNED:
1698 for (; n != NULL; n = n->next)
1699 if (n->sym->attr.referenced || declare_simd)
1700 {
1701 tree t = gfc_trans_omp_variable (n->sym, declare_simd);
1702 if (t != error_mark_node)
1703 {
1704 tree node = build_omp_clause (input_location,
1705 OMP_CLAUSE_ALIGNED);
1706 OMP_CLAUSE_DECL (node) = t;
1707 if (n->expr)
1708 {
1709 tree alignment_var;
1710
1711 if (block == NULL)
1712 alignment_var = gfc_conv_constant_to_tree (n->expr);
1713 else
1714 {
1715 gfc_init_se (&se, NULL);
1716 gfc_conv_expr (&se, n->expr);
1717 gfc_add_block_to_block (block, &se.pre);
1718 alignment_var = gfc_evaluate_now (se.expr, block);
1719 gfc_add_block_to_block (block, &se.post);
1720 }
1721 OMP_CLAUSE_ALIGNED_ALIGNMENT (node) = alignment_var;
1722 }
1723 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
1724 }
1725 }
1726 break;
1727 case OMP_LIST_LINEAR:
1728 {
1729 gfc_expr *last_step_expr = NULL;
1730 tree last_step = NULL_TREE;
1731
1732 for (; n != NULL; n = n->next)
1733 {
1734 if (n->expr)
1735 {
1736 last_step_expr = n->expr;
1737 last_step = NULL_TREE;
1738 }
1739 if (n->sym->attr.referenced || declare_simd)
1740 {
1741 tree t = gfc_trans_omp_variable (n->sym, declare_simd);
1742 if (t != error_mark_node)
1743 {
1744 tree node = build_omp_clause (input_location,
1745 OMP_CLAUSE_LINEAR);
1746 OMP_CLAUSE_DECL (node) = t;
1747 if (last_step_expr && last_step == NULL_TREE)
1748 {
1749 if (block == NULL)
1750 last_step
1751 = gfc_conv_constant_to_tree (last_step_expr);
1752 else
1753 {
1754 gfc_init_se (&se, NULL);
1755 gfc_conv_expr (&se, last_step_expr);
1756 gfc_add_block_to_block (block, &se.pre);
1757 last_step = gfc_evaluate_now (se.expr, block);
1758 gfc_add_block_to_block (block, &se.post);
1759 }
1760 }
1761 OMP_CLAUSE_LINEAR_STEP (node) = last_step;
1762 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
1763 }
1764 }
1765 }
1766 }
1767 break;
f014c653 1768 case OMP_LIST_DEPEND:
dd2fc525
JJ
1769 for (; n != NULL; n = n->next)
1770 {
1771 if (!n->sym->attr.referenced)
1772 continue;
1773
1774 tree node = build_omp_clause (input_location, OMP_CLAUSE_DEPEND);
1775 if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
1776 {
f014c653
JJ
1777 tree decl = gfc_get_symbol_decl (n->sym);
1778 if (gfc_omp_privatize_by_reference (decl))
1779 decl = build_fold_indirect_ref (decl);
1780 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
1781 {
1782 decl = gfc_conv_descriptor_data_get (decl);
1783 decl = fold_convert (build_pointer_type (char_type_node),
1784 decl);
1785 decl = build_fold_indirect_ref (decl);
1786 }
1787 else if (DECL_P (decl))
1788 TREE_ADDRESSABLE (decl) = 1;
1789 OMP_CLAUSE_DECL (node) = decl;
dd2fc525
JJ
1790 }
1791 else
1792 {
1793 tree ptr;
1794 gfc_init_se (&se, NULL);
1795 if (n->expr->ref->u.ar.type == AR_ELEMENT)
1796 {
1797 gfc_conv_expr_reference (&se, n->expr);
1798 ptr = se.expr;
1799 }
1800 else
1801 {
1802 gfc_conv_expr_descriptor (&se, n->expr);
1803 ptr = gfc_conv_array_data (se.expr);
1804 }
1805 gfc_add_block_to_block (block, &se.pre);
1806 gfc_add_block_to_block (block, &se.post);
f014c653
JJ
1807 ptr = fold_convert (build_pointer_type (char_type_node),
1808 ptr);
1809 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
1810 }
1811 switch (n->u.depend_op)
1812 {
1813 case OMP_DEPEND_IN:
1814 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_IN;
1815 break;
1816 case OMP_DEPEND_OUT:
1817 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_OUT;
1818 break;
1819 case OMP_DEPEND_INOUT:
1820 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_INOUT;
1821 break;
1822 default:
1823 gcc_unreachable ();
1824 }
1825 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
1826 }
1827 break;
1828 case OMP_LIST_MAP:
1829 for (; n != NULL; n = n->next)
1830 {
1831 if (!n->sym->attr.referenced)
1832 continue;
1833
1834 tree node = build_omp_clause (input_location, OMP_CLAUSE_MAP);
1835 tree node2 = NULL_TREE;
1836 tree node3 = NULL_TREE;
1837 tree node4 = NULL_TREE;
1838 tree decl = gfc_get_symbol_decl (n->sym);
1839 if (DECL_P (decl))
1840 TREE_ADDRESSABLE (decl) = 1;
1841 if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
1842 {
1843 if (POINTER_TYPE_P (TREE_TYPE (decl)))
1844 {
1845 node4 = build_omp_clause (input_location,
1846 OMP_CLAUSE_MAP);
1847 OMP_CLAUSE_MAP_KIND (node4) = OMP_CLAUSE_MAP_POINTER;
1848 OMP_CLAUSE_DECL (node4) = decl;
1849 OMP_CLAUSE_SIZE (node4) = size_int (0);
1850 decl = build_fold_indirect_ref (decl);
1851 }
1852 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
1853 {
1854 tree type = TREE_TYPE (decl);
1855 tree ptr = gfc_conv_descriptor_data_get (decl);
1856 ptr = fold_convert (build_pointer_type (char_type_node),
1857 ptr);
1858 ptr = build_fold_indirect_ref (ptr);
1859 OMP_CLAUSE_DECL (node) = ptr;
1860 node2 = build_omp_clause (input_location,
1861 OMP_CLAUSE_MAP);
1862 OMP_CLAUSE_MAP_KIND (node2) = OMP_CLAUSE_MAP_TO_PSET;
1863 OMP_CLAUSE_DECL (node2) = decl;
1864 OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
1865 node3 = build_omp_clause (input_location,
1866 OMP_CLAUSE_MAP);
1867 OMP_CLAUSE_MAP_KIND (node3) = OMP_CLAUSE_MAP_POINTER;
1868 OMP_CLAUSE_DECL (node3)
1869 = gfc_conv_descriptor_data_get (decl);
1870 OMP_CLAUSE_SIZE (node3) = size_int (0);
1871 if (n->sym->attr.pointer)
1872 {
1873 stmtblock_t cond_block;
1874 tree size
1875 = gfc_create_var (gfc_array_index_type, NULL);
1876 tree tem, then_b, else_b, zero, cond;
1877
1878 gfc_init_block (&cond_block);
1879 tem
1880 = gfc_full_array_size (&cond_block, decl,
1881 GFC_TYPE_ARRAY_RANK (type));
1882 gfc_add_modify (&cond_block, size, tem);
1883 then_b = gfc_finish_block (&cond_block);
1884 gfc_init_block (&cond_block);
1885 zero = build_int_cst (gfc_array_index_type, 0);
1886 gfc_add_modify (&cond_block, size, zero);
1887 else_b = gfc_finish_block (&cond_block);
1888 tem = gfc_conv_descriptor_data_get (decl);
1889 tem = fold_convert (pvoid_type_node, tem);
1890 cond = fold_build2_loc (input_location, NE_EXPR,
1891 boolean_type_node,
1892 tem, null_pointer_node);
1893 gfc_add_expr_to_block (block,
1894 build3_loc (input_location,
1895 COND_EXPR,
1896 void_type_node,
1897 cond, then_b,
1898 else_b));
1899 OMP_CLAUSE_SIZE (node) = size;
1900 }
1901 else
1902 OMP_CLAUSE_SIZE (node)
1903 = gfc_full_array_size (block, decl,
1904 GFC_TYPE_ARRAY_RANK (type));
1905 tree elemsz
1906 = TYPE_SIZE_UNIT (gfc_get_element_type (type));
1907 elemsz = fold_convert (gfc_array_index_type, elemsz);
1908 OMP_CLAUSE_SIZE (node)
1909 = fold_build2 (MULT_EXPR, gfc_array_index_type,
1910 OMP_CLAUSE_SIZE (node), elemsz);
1911 }
1912 else
1913 OMP_CLAUSE_DECL (node) = decl;
1914 }
1915 else
1916 {
1917 tree ptr, ptr2;
1918 gfc_init_se (&se, NULL);
1919 if (n->expr->ref->u.ar.type == AR_ELEMENT)
1920 {
1921 gfc_conv_expr_reference (&se, n->expr);
1922 gfc_add_block_to_block (block, &se.pre);
1923 ptr = se.expr;
1924 OMP_CLAUSE_SIZE (node)
1925 = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
1926 }
1927 else
1928 {
1929 gfc_conv_expr_descriptor (&se, n->expr);
1930 ptr = gfc_conv_array_data (se.expr);
1931 tree type = TREE_TYPE (se.expr);
1932 gfc_add_block_to_block (block, &se.pre);
1933 OMP_CLAUSE_SIZE (node)
1934 = gfc_full_array_size (block, se.expr,
1935 GFC_TYPE_ARRAY_RANK (type));
1936 tree elemsz
1937 = TYPE_SIZE_UNIT (gfc_get_element_type (type));
1938 elemsz = fold_convert (gfc_array_index_type, elemsz);
1939 OMP_CLAUSE_SIZE (node)
1940 = fold_build2 (MULT_EXPR, gfc_array_index_type,
1941 OMP_CLAUSE_SIZE (node), elemsz);
1942 }
1943 gfc_add_block_to_block (block, &se.post);
1944 ptr = fold_convert (build_pointer_type (char_type_node),
1945 ptr);
1946 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
1947
1948 if (POINTER_TYPE_P (TREE_TYPE (decl))
1949 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
1950 {
1951 node4 = build_omp_clause (input_location,
1952 OMP_CLAUSE_MAP);
1953 OMP_CLAUSE_MAP_KIND (node4) = OMP_CLAUSE_MAP_POINTER;
1954 OMP_CLAUSE_DECL (node4) = decl;
1955 OMP_CLAUSE_SIZE (node4) = size_int (0);
1956 decl = build_fold_indirect_ref (decl);
1957 }
1958 ptr = fold_convert (sizetype, ptr);
1959 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
1960 {
1961 tree type = TREE_TYPE (decl);
1962 ptr2 = gfc_conv_descriptor_data_get (decl);
1963 node2 = build_omp_clause (input_location,
1964 OMP_CLAUSE_MAP);
1965 OMP_CLAUSE_MAP_KIND (node2) = OMP_CLAUSE_MAP_TO_PSET;
1966 OMP_CLAUSE_DECL (node2) = decl;
1967 OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
1968 node3 = build_omp_clause (input_location,
1969 OMP_CLAUSE_MAP);
1970 OMP_CLAUSE_MAP_KIND (node3) = OMP_CLAUSE_MAP_POINTER;
1971 OMP_CLAUSE_DECL (node3)
1972 = gfc_conv_descriptor_data_get (decl);
1973 }
1974 else
1975 {
1976 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1977 ptr2 = build_fold_addr_expr (decl);
1978 else
1979 {
1980 gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl)));
1981 ptr2 = decl;
1982 }
1983 node3 = build_omp_clause (input_location,
1984 OMP_CLAUSE_MAP);
1985 OMP_CLAUSE_MAP_KIND (node3) = OMP_CLAUSE_MAP_POINTER;
1986 OMP_CLAUSE_DECL (node3) = decl;
1987 }
1988 ptr2 = fold_convert (sizetype, ptr2);
1989 OMP_CLAUSE_SIZE (node3)
1990 = fold_build2 (MINUS_EXPR, sizetype, ptr, ptr2);
1991 }
1992 switch (n->u.map_op)
1993 {
1994 case OMP_MAP_ALLOC:
1995 OMP_CLAUSE_MAP_KIND (node) = OMP_CLAUSE_MAP_ALLOC;
1996 break;
1997 case OMP_MAP_TO:
1998 OMP_CLAUSE_MAP_KIND (node) = OMP_CLAUSE_MAP_TO;
1999 break;
2000 case OMP_MAP_FROM:
2001 OMP_CLAUSE_MAP_KIND (node) = OMP_CLAUSE_MAP_FROM;
2002 break;
2003 case OMP_MAP_TOFROM:
2004 OMP_CLAUSE_MAP_KIND (node) = OMP_CLAUSE_MAP_TOFROM;
2005 break;
2006 default:
2007 gcc_unreachable ();
2008 }
2009 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2010 if (node2)
2011 omp_clauses = gfc_trans_add_clause (node2, omp_clauses);
2012 if (node3)
2013 omp_clauses = gfc_trans_add_clause (node3, omp_clauses);
2014 if (node4)
2015 omp_clauses = gfc_trans_add_clause (node4, omp_clauses);
2016 }
2017 break;
2018 case OMP_LIST_TO:
2019 case OMP_LIST_FROM:
2020 for (; n != NULL; n = n->next)
2021 {
2022 if (!n->sym->attr.referenced)
2023 continue;
2024
2025 tree node = build_omp_clause (input_location,
2026 list == OMP_LIST_TO
2027 ? OMP_CLAUSE_TO : OMP_CLAUSE_FROM);
2028 if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
2029 {
2030 tree decl = gfc_get_symbol_decl (n->sym);
2031 if (gfc_omp_privatize_by_reference (decl))
2032 decl = build_fold_indirect_ref (decl);
2033 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
2034 {
2035 tree type = TREE_TYPE (decl);
2036 tree ptr = gfc_conv_descriptor_data_get (decl);
2037 ptr = fold_convert (build_pointer_type (char_type_node),
2038 ptr);
2039 ptr = build_fold_indirect_ref (ptr);
2040 OMP_CLAUSE_DECL (node) = ptr;
2041 OMP_CLAUSE_SIZE (node)
2042 = gfc_full_array_size (block, decl,
2043 GFC_TYPE_ARRAY_RANK (type));
2044 tree elemsz
2045 = TYPE_SIZE_UNIT (gfc_get_element_type (type));
2046 elemsz = fold_convert (gfc_array_index_type, elemsz);
2047 OMP_CLAUSE_SIZE (node)
2048 = fold_build2 (MULT_EXPR, gfc_array_index_type,
2049 OMP_CLAUSE_SIZE (node), elemsz);
2050 }
2051 else
2052 OMP_CLAUSE_DECL (node) = decl;
2053 }
2054 else
2055 {
2056 tree ptr;
2057 gfc_init_se (&se, NULL);
2058 if (n->expr->ref->u.ar.type == AR_ELEMENT)
2059 {
2060 gfc_conv_expr_reference (&se, n->expr);
2061 ptr = se.expr;
2062 gfc_add_block_to_block (block, &se.pre);
2063 OMP_CLAUSE_SIZE (node)
2064 = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
2065 }
2066 else
2067 {
2068 gfc_conv_expr_descriptor (&se, n->expr);
2069 ptr = gfc_conv_array_data (se.expr);
2070 tree type = TREE_TYPE (se.expr);
2071 gfc_add_block_to_block (block, &se.pre);
2072 OMP_CLAUSE_SIZE (node)
2073 = gfc_full_array_size (block, se.expr,
2074 GFC_TYPE_ARRAY_RANK (type));
2075 tree elemsz
2076 = TYPE_SIZE_UNIT (gfc_get_element_type (type));
2077 elemsz = fold_convert (gfc_array_index_type, elemsz);
2078 OMP_CLAUSE_SIZE (node)
2079 = fold_build2 (MULT_EXPR, gfc_array_index_type,
2080 OMP_CLAUSE_SIZE (node), elemsz);
2081 }
2082 gfc_add_block_to_block (block, &se.post);
2083 ptr = fold_convert (build_pointer_type (char_type_node),
2084 ptr);
2085 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
dd2fc525 2086 }
dd2fc525
JJ
2087 omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2088 }
6c7a4dfd
JJ
2089 break;
2090 default:
2091 break;
2092 }
2093 }
2094
2095 if (clauses->if_expr)
2096 {
2097 tree if_var;
2098
2099 gfc_init_se (&se, NULL);
2100 gfc_conv_expr (&se, clauses->if_expr);
2101 gfc_add_block_to_block (block, &se.pre);
2102 if_var = gfc_evaluate_now (se.expr, block);
2103 gfc_add_block_to_block (block, &se.post);
2104
c2255bc4 2105 c = build_omp_clause (where.lb->location, OMP_CLAUSE_IF);
6c7a4dfd
JJ
2106 OMP_CLAUSE_IF_EXPR (c) = if_var;
2107 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2108 }
2109
20906c66
JJ
2110 if (clauses->final_expr)
2111 {
2112 tree final_var;
2113
2114 gfc_init_se (&se, NULL);
2115 gfc_conv_expr (&se, clauses->final_expr);
2116 gfc_add_block_to_block (block, &se.pre);
2117 final_var = gfc_evaluate_now (se.expr, block);
2118 gfc_add_block_to_block (block, &se.post);
2119
2120 c = build_omp_clause (where.lb->location, OMP_CLAUSE_FINAL);
2121 OMP_CLAUSE_FINAL_EXPR (c) = final_var;
2122 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2123 }
2124
6c7a4dfd
JJ
2125 if (clauses->num_threads)
2126 {
2127 tree num_threads;
2128
2129 gfc_init_se (&se, NULL);
2130 gfc_conv_expr (&se, clauses->num_threads);
2131 gfc_add_block_to_block (block, &se.pre);
2132 num_threads = gfc_evaluate_now (se.expr, block);
2133 gfc_add_block_to_block (block, &se.post);
2134
c2255bc4 2135 c = build_omp_clause (where.lb->location, OMP_CLAUSE_NUM_THREADS);
6c7a4dfd
JJ
2136 OMP_CLAUSE_NUM_THREADS_EXPR (c) = num_threads;
2137 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2138 }
2139
2140 chunk_size = NULL_TREE;
2141 if (clauses->chunk_size)
2142 {
2143 gfc_init_se (&se, NULL);
2144 gfc_conv_expr (&se, clauses->chunk_size);
2145 gfc_add_block_to_block (block, &se.pre);
2146 chunk_size = gfc_evaluate_now (se.expr, block);
2147 gfc_add_block_to_block (block, &se.post);
2148 }
2149
2150 if (clauses->sched_kind != OMP_SCHED_NONE)
2151 {
c2255bc4 2152 c = build_omp_clause (where.lb->location, OMP_CLAUSE_SCHEDULE);
6c7a4dfd
JJ
2153 OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
2154 switch (clauses->sched_kind)
2155 {
2156 case OMP_SCHED_STATIC:
2157 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
2158 break;
2159 case OMP_SCHED_DYNAMIC:
2160 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
2161 break;
2162 case OMP_SCHED_GUIDED:
2163 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
2164 break;
2165 case OMP_SCHED_RUNTIME:
2166 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
2167 break;
a68ab351
JJ
2168 case OMP_SCHED_AUTO:
2169 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
2170 break;
6c7a4dfd
JJ
2171 default:
2172 gcc_unreachable ();
2173 }
2174 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2175 }
2176
2177 if (clauses->default_sharing != OMP_DEFAULT_UNKNOWN)
2178 {
c2255bc4 2179 c = build_omp_clause (where.lb->location, OMP_CLAUSE_DEFAULT);
6c7a4dfd
JJ
2180 switch (clauses->default_sharing)
2181 {
2182 case OMP_DEFAULT_NONE:
2183 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_NONE;
2184 break;
2185 case OMP_DEFAULT_SHARED:
2186 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_SHARED;
2187 break;
2188 case OMP_DEFAULT_PRIVATE:
2189 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRIVATE;
2190 break;
a68ab351
JJ
2191 case OMP_DEFAULT_FIRSTPRIVATE:
2192 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
2193 break;
6c7a4dfd
JJ
2194 default:
2195 gcc_unreachable ();
2196 }
2197 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2198 }
2199
2200 if (clauses->nowait)
2201 {
c2255bc4 2202 c = build_omp_clause (where.lb->location, OMP_CLAUSE_NOWAIT);
6c7a4dfd
JJ
2203 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2204 }
2205
2206 if (clauses->ordered)
2207 {
c2255bc4 2208 c = build_omp_clause (where.lb->location, OMP_CLAUSE_ORDERED);
6c7a4dfd
JJ
2209 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2210 }
2211
a68ab351
JJ
2212 if (clauses->untied)
2213 {
c2255bc4 2214 c = build_omp_clause (where.lb->location, OMP_CLAUSE_UNTIED);
a68ab351
JJ
2215 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2216 }
2217
20906c66
JJ
2218 if (clauses->mergeable)
2219 {
2220 c = build_omp_clause (where.lb->location, OMP_CLAUSE_MERGEABLE);
2221 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2222 }
2223
a68ab351
JJ
2224 if (clauses->collapse)
2225 {
c2255bc4 2226 c = build_omp_clause (where.lb->location, OMP_CLAUSE_COLLAPSE);
df09d1d5
RG
2227 OMP_CLAUSE_COLLAPSE_EXPR (c)
2228 = build_int_cst (integer_type_node, clauses->collapse);
a68ab351
JJ
2229 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2230 }
2231
dd2fc525
JJ
2232 if (clauses->inbranch)
2233 {
2234 c = build_omp_clause (where.lb->location, OMP_CLAUSE_INBRANCH);
2235 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2236 }
2237
2238 if (clauses->notinbranch)
2239 {
2240 c = build_omp_clause (where.lb->location, OMP_CLAUSE_NOTINBRANCH);
2241 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2242 }
2243
2244 switch (clauses->cancel)
2245 {
2246 case OMP_CANCEL_UNKNOWN:
2247 break;
2248 case OMP_CANCEL_PARALLEL:
2249 c = build_omp_clause (where.lb->location, OMP_CLAUSE_PARALLEL);
2250 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2251 break;
2252 case OMP_CANCEL_SECTIONS:
2253 c = build_omp_clause (where.lb->location, OMP_CLAUSE_SECTIONS);
2254 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2255 break;
2256 case OMP_CANCEL_DO:
2257 c = build_omp_clause (where.lb->location, OMP_CLAUSE_FOR);
2258 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2259 break;
2260 case OMP_CANCEL_TASKGROUP:
2261 c = build_omp_clause (where.lb->location, OMP_CLAUSE_TASKGROUP);
2262 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2263 break;
2264 }
2265
2266 if (clauses->proc_bind != OMP_PROC_BIND_UNKNOWN)
2267 {
2268 c = build_omp_clause (where.lb->location, OMP_CLAUSE_PROC_BIND);
2269 switch (clauses->proc_bind)
2270 {
2271 case OMP_PROC_BIND_MASTER:
2272 OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_MASTER;
2273 break;
2274 case OMP_PROC_BIND_SPREAD:
2275 OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_SPREAD;
2276 break;
2277 case OMP_PROC_BIND_CLOSE:
2278 OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_CLOSE;
2279 break;
2280 default:
2281 gcc_unreachable ();
2282 }
2283 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2284 }
2285
2286 if (clauses->safelen_expr)
2287 {
2288 tree safelen_var;
2289
2290 gfc_init_se (&se, NULL);
2291 gfc_conv_expr (&se, clauses->safelen_expr);
2292 gfc_add_block_to_block (block, &se.pre);
2293 safelen_var = gfc_evaluate_now (se.expr, block);
2294 gfc_add_block_to_block (block, &se.post);
2295
2296 c = build_omp_clause (where.lb->location, OMP_CLAUSE_SAFELEN);
2297 OMP_CLAUSE_SAFELEN_EXPR (c) = safelen_var;
2298 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2299 }
2300
2301 if (clauses->simdlen_expr)
2302 {
2303 c = build_omp_clause (where.lb->location, OMP_CLAUSE_SIMDLEN);
2304 OMP_CLAUSE_SIMDLEN_EXPR (c)
2305 = gfc_conv_constant_to_tree (clauses->simdlen_expr);
2306 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2307 }
2308
f014c653
JJ
2309 if (clauses->num_teams)
2310 {
2311 tree num_teams;
2312
2313 gfc_init_se (&se, NULL);
2314 gfc_conv_expr (&se, clauses->num_teams);
2315 gfc_add_block_to_block (block, &se.pre);
2316 num_teams = gfc_evaluate_now (se.expr, block);
2317 gfc_add_block_to_block (block, &se.post);
2318
2319 c = build_omp_clause (where.lb->location, OMP_CLAUSE_NUM_TEAMS);
2320 OMP_CLAUSE_NUM_TEAMS_EXPR (c) = num_teams;
2321 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2322 }
2323
2324 if (clauses->device)
2325 {
2326 tree device;
2327
2328 gfc_init_se (&se, NULL);
2329 gfc_conv_expr (&se, clauses->device);
2330 gfc_add_block_to_block (block, &se.pre);
2331 device = gfc_evaluate_now (se.expr, block);
2332 gfc_add_block_to_block (block, &se.post);
2333
2334 c = build_omp_clause (where.lb->location, OMP_CLAUSE_DEVICE);
2335 OMP_CLAUSE_DEVICE_ID (c) = device;
2336 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2337 }
2338
2339 if (clauses->thread_limit)
2340 {
2341 tree thread_limit;
2342
2343 gfc_init_se (&se, NULL);
2344 gfc_conv_expr (&se, clauses->thread_limit);
2345 gfc_add_block_to_block (block, &se.pre);
2346 thread_limit = gfc_evaluate_now (se.expr, block);
2347 gfc_add_block_to_block (block, &se.post);
2348
2349 c = build_omp_clause (where.lb->location, OMP_CLAUSE_THREAD_LIMIT);
2350 OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = thread_limit;
2351 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2352 }
2353
2354 chunk_size = NULL_TREE;
2355 if (clauses->dist_chunk_size)
2356 {
2357 gfc_init_se (&se, NULL);
2358 gfc_conv_expr (&se, clauses->dist_chunk_size);
2359 gfc_add_block_to_block (block, &se.pre);
2360 chunk_size = gfc_evaluate_now (se.expr, block);
2361 gfc_add_block_to_block (block, &se.post);
2362 }
2363
2364 if (clauses->dist_sched_kind != OMP_SCHED_NONE)
2365 {
2366 c = build_omp_clause (where.lb->location, OMP_CLAUSE_DIST_SCHEDULE);
2367 OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
2368 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
2369 }
2370
2371 return nreverse (omp_clauses);
6c7a4dfd
JJ
2372}
2373
2374/* Like gfc_trans_code, but force creation of a BIND_EXPR around it. */
2375
2376static tree
2377gfc_trans_omp_code (gfc_code *code, bool force_empty)
2378{
2379 tree stmt;
2380
87a60f68 2381 pushlevel ();
6c7a4dfd
JJ
2382 stmt = gfc_trans_code (code);
2383 if (TREE_CODE (stmt) != BIND_EXPR)
2384 {
2385 if (!IS_EMPTY_STMT (stmt) || force_empty)
2386 {
87a60f68 2387 tree block = poplevel (1, 0);
6c7a4dfd
JJ
2388 stmt = build3_v (BIND_EXPR, NULL, stmt, block);
2389 }
2390 else
87a60f68 2391 poplevel (0, 0);
6c7a4dfd
JJ
2392 }
2393 else
87a60f68 2394 poplevel (0, 0);
6c7a4dfd
JJ
2395 return stmt;
2396}
2397
2398
2399static tree gfc_trans_omp_sections (gfc_code *, gfc_omp_clauses *);
2400static tree gfc_trans_omp_workshare (gfc_code *, gfc_omp_clauses *);
2401
2402static tree
2403gfc_trans_omp_atomic (gfc_code *code)
2404{
20906c66 2405 gfc_code *atomic_code = code;
6c7a4dfd
JJ
2406 gfc_se lse;
2407 gfc_se rse;
20906c66 2408 gfc_se vse;
6c7a4dfd
JJ
2409 gfc_expr *expr2, *e;
2410 gfc_symbol *var;
2411 stmtblock_t block;
2412 tree lhsaddr, type, rhs, x;
2413 enum tree_code op = ERROR_MARK;
20906c66 2414 enum tree_code aop = OMP_ATOMIC;
6c7a4dfd 2415 bool var_on_left = false;
dd2fc525 2416 bool seq_cst = (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SEQ_CST) != 0;
6c7a4dfd
JJ
2417
2418 code = code->block->next;
2419 gcc_assert (code->op == EXEC_ASSIGN);
a513927a 2420 var = code->expr1->symtree->n.sym;
6c7a4dfd
JJ
2421
2422 gfc_init_se (&lse, NULL);
2423 gfc_init_se (&rse, NULL);
20906c66 2424 gfc_init_se (&vse, NULL);
6c7a4dfd
JJ
2425 gfc_start_block (&block);
2426
6c7a4dfd
JJ
2427 expr2 = code->expr2;
2428 if (expr2->expr_type == EXPR_FUNCTION
cd5ecab6 2429 && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
6c7a4dfd
JJ
2430 expr2 = expr2->value.function.actual->expr;
2431
dd2fc525 2432 switch (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
20906c66
JJ
2433 {
2434 case GFC_OMP_ATOMIC_READ:
2435 gfc_conv_expr (&vse, code->expr1);
2436 gfc_add_block_to_block (&block, &vse.pre);
2437
2438 gfc_conv_expr (&lse, expr2);
2439 gfc_add_block_to_block (&block, &lse.pre);
2440 type = TREE_TYPE (lse.expr);
2441 lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
2442
2443 x = build1 (OMP_ATOMIC_READ, type, lhsaddr);
dd2fc525 2444 OMP_ATOMIC_SEQ_CST (x) = seq_cst;
20906c66
JJ
2445 x = convert (TREE_TYPE (vse.expr), x);
2446 gfc_add_modify (&block, vse.expr, x);
2447
2448 gfc_add_block_to_block (&block, &lse.pre);
2449 gfc_add_block_to_block (&block, &rse.pre);
2450
2451 return gfc_finish_block (&block);
2452 case GFC_OMP_ATOMIC_CAPTURE:
2453 aop = OMP_ATOMIC_CAPTURE_NEW;
2454 if (expr2->expr_type == EXPR_VARIABLE)
2455 {
2456 aop = OMP_ATOMIC_CAPTURE_OLD;
2457 gfc_conv_expr (&vse, code->expr1);
2458 gfc_add_block_to_block (&block, &vse.pre);
2459
2460 gfc_conv_expr (&lse, expr2);
2461 gfc_add_block_to_block (&block, &lse.pre);
2462 gfc_init_se (&lse, NULL);
2463 code = code->next;
2464 var = code->expr1->symtree->n.sym;
2465 expr2 = code->expr2;
2466 if (expr2->expr_type == EXPR_FUNCTION
2467 && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
2468 expr2 = expr2->value.function.actual->expr;
2469 }
2470 break;
2471 default:
2472 break;
2473 }
2474
2475 gfc_conv_expr (&lse, code->expr1);
2476 gfc_add_block_to_block (&block, &lse.pre);
2477 type = TREE_TYPE (lse.expr);
2478 lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
2479
dd2fc525
JJ
2480 if (((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
2481 == GFC_OMP_ATOMIC_WRITE)
2482 || (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SWAP))
20906c66
JJ
2483 {
2484 gfc_conv_expr (&rse, expr2);
2485 gfc_add_block_to_block (&block, &rse.pre);
2486 }
2487 else if (expr2->expr_type == EXPR_OP)
6c7a4dfd
JJ
2488 {
2489 gfc_expr *e;
a1ee985f 2490 switch (expr2->value.op.op)
6c7a4dfd
JJ
2491 {
2492 case INTRINSIC_PLUS:
2493 op = PLUS_EXPR;
2494 break;
2495 case INTRINSIC_TIMES:
2496 op = MULT_EXPR;
2497 break;
2498 case INTRINSIC_MINUS:
2499 op = MINUS_EXPR;
2500 break;
2501 case INTRINSIC_DIVIDE:
2502 if (expr2->ts.type == BT_INTEGER)
2503 op = TRUNC_DIV_EXPR;
2504 else
2505 op = RDIV_EXPR;
2506 break;
2507 case INTRINSIC_AND:
2508 op = TRUTH_ANDIF_EXPR;
2509 break;
2510 case INTRINSIC_OR:
2511 op = TRUTH_ORIF_EXPR;
2512 break;
2513 case INTRINSIC_EQV:
2514 op = EQ_EXPR;
2515 break;
2516 case INTRINSIC_NEQV:
2517 op = NE_EXPR;
2518 break;
2519 default:
2520 gcc_unreachable ();
2521 }
2522 e = expr2->value.op.op1;
2523 if (e->expr_type == EXPR_FUNCTION
cd5ecab6 2524 && e->value.function.isym->id == GFC_ISYM_CONVERSION)
6c7a4dfd
JJ
2525 e = e->value.function.actual->expr;
2526 if (e->expr_type == EXPR_VARIABLE
2527 && e->symtree != NULL
2528 && e->symtree->n.sym == var)
2529 {
2530 expr2 = expr2->value.op.op2;
2531 var_on_left = true;
2532 }
2533 else
2534 {
2535 e = expr2->value.op.op2;
2536 if (e->expr_type == EXPR_FUNCTION
cd5ecab6 2537 && e->value.function.isym->id == GFC_ISYM_CONVERSION)
6c7a4dfd
JJ
2538 e = e->value.function.actual->expr;
2539 gcc_assert (e->expr_type == EXPR_VARIABLE
2540 && e->symtree != NULL
2541 && e->symtree->n.sym == var);
2542 expr2 = expr2->value.op.op1;
2543 var_on_left = false;
2544 }
2545 gfc_conv_expr (&rse, expr2);
2546 gfc_add_block_to_block (&block, &rse.pre);
2547 }
2548 else
2549 {
2550 gcc_assert (expr2->expr_type == EXPR_FUNCTION);
cd5ecab6 2551 switch (expr2->value.function.isym->id)
6c7a4dfd
JJ
2552 {
2553 case GFC_ISYM_MIN:
2554 op = MIN_EXPR;
2555 break;
2556 case GFC_ISYM_MAX:
2557 op = MAX_EXPR;
2558 break;
2559 case GFC_ISYM_IAND:
2560 op = BIT_AND_EXPR;
2561 break;
2562 case GFC_ISYM_IOR:
2563 op = BIT_IOR_EXPR;
2564 break;
2565 case GFC_ISYM_IEOR:
2566 op = BIT_XOR_EXPR;
2567 break;
2568 default:
2569 gcc_unreachable ();
2570 }
2571 e = expr2->value.function.actual->expr;
2572 gcc_assert (e->expr_type == EXPR_VARIABLE
2573 && e->symtree != NULL
2574 && e->symtree->n.sym == var);
2575
2576 gfc_conv_expr (&rse, expr2->value.function.actual->next->expr);
2577 gfc_add_block_to_block (&block, &rse.pre);
2578 if (expr2->value.function.actual->next->next != NULL)
2579 {
2580 tree accum = gfc_create_var (TREE_TYPE (rse.expr), NULL);
2581 gfc_actual_arglist *arg;
2582
726a989a 2583 gfc_add_modify (&block, accum, rse.expr);
6c7a4dfd
JJ
2584 for (arg = expr2->value.function.actual->next->next; arg;
2585 arg = arg->next)
2586 {
2587 gfc_init_block (&rse.pre);
2588 gfc_conv_expr (&rse, arg->expr);
2589 gfc_add_block_to_block (&block, &rse.pre);
65a9ca82
TB
2590 x = fold_build2_loc (input_location, op, TREE_TYPE (accum),
2591 accum, rse.expr);
726a989a 2592 gfc_add_modify (&block, accum, x);
6c7a4dfd
JJ
2593 }
2594
2595 rse.expr = accum;
2596 }
2597
2598 expr2 = expr2->value.function.actual->next->expr;
2599 }
2600
2601 lhsaddr = save_expr (lhsaddr);
2602 rhs = gfc_evaluate_now (rse.expr, &block);
6c7a4dfd 2603
dd2fc525
JJ
2604 if (((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
2605 == GFC_OMP_ATOMIC_WRITE)
2606 || (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SWAP))
20906c66 2607 x = rhs;
6c7a4dfd 2608 else
20906c66
JJ
2609 {
2610 x = convert (TREE_TYPE (rhs),
2611 build_fold_indirect_ref_loc (input_location, lhsaddr));
2612 if (var_on_left)
2613 x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), x, rhs);
2614 else
2615 x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), rhs, x);
2616 }
6c7a4dfd
JJ
2617
2618 if (TREE_CODE (TREE_TYPE (rhs)) == COMPLEX_TYPE
2619 && TREE_CODE (type) != COMPLEX_TYPE)
65a9ca82
TB
2620 x = fold_build1_loc (input_location, REALPART_EXPR,
2621 TREE_TYPE (TREE_TYPE (rhs)), x);
6c7a4dfd 2622
6c7a4dfd
JJ
2623 gfc_add_block_to_block (&block, &lse.pre);
2624 gfc_add_block_to_block (&block, &rse.pre);
2625
20906c66
JJ
2626 if (aop == OMP_ATOMIC)
2627 {
2628 x = build2_v (OMP_ATOMIC, lhsaddr, convert (type, x));
dd2fc525 2629 OMP_ATOMIC_SEQ_CST (x) = seq_cst;
20906c66
JJ
2630 gfc_add_expr_to_block (&block, x);
2631 }
2632 else
2633 {
2634 if (aop == OMP_ATOMIC_CAPTURE_NEW)
2635 {
2636 code = code->next;
2637 expr2 = code->expr2;
2638 if (expr2->expr_type == EXPR_FUNCTION
2639 && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
2640 expr2 = expr2->value.function.actual->expr;
2641
2642 gcc_assert (expr2->expr_type == EXPR_VARIABLE);
2643 gfc_conv_expr (&vse, code->expr1);
2644 gfc_add_block_to_block (&block, &vse.pre);
2645
2646 gfc_init_se (&lse, NULL);
2647 gfc_conv_expr (&lse, expr2);
2648 gfc_add_block_to_block (&block, &lse.pre);
2649 }
2650 x = build2 (aop, type, lhsaddr, convert (type, x));
dd2fc525 2651 OMP_ATOMIC_SEQ_CST (x) = seq_cst;
20906c66
JJ
2652 x = convert (TREE_TYPE (vse.expr), x);
2653 gfc_add_modify (&block, vse.expr, x);
2654 }
2655
6c7a4dfd
JJ
2656 return gfc_finish_block (&block);
2657}
2658
2659static tree
2660gfc_trans_omp_barrier (void)
2661{
e79983f4 2662 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
db3927fb 2663 return build_call_expr_loc (input_location, decl, 0);
6c7a4dfd
JJ
2664}
2665
dd2fc525
JJ
2666static tree
2667gfc_trans_omp_cancel (gfc_code *code)
2668{
2669 int mask = 0;
2670 tree ifc = boolean_true_node;
2671 stmtblock_t block;
2672 switch (code->ext.omp_clauses->cancel)
2673 {
2674 case OMP_CANCEL_PARALLEL: mask = 1; break;
2675 case OMP_CANCEL_DO: mask = 2; break;
2676 case OMP_CANCEL_SECTIONS: mask = 4; break;
2677 case OMP_CANCEL_TASKGROUP: mask = 8; break;
2678 default: gcc_unreachable ();
2679 }
2680 gfc_start_block (&block);
2681 if (code->ext.omp_clauses->if_expr)
2682 {
2683 gfc_se se;
2684 tree if_var;
2685
2686 gfc_init_se (&se, NULL);
2687 gfc_conv_expr (&se, code->ext.omp_clauses->if_expr);
2688 gfc_add_block_to_block (&block, &se.pre);
2689 if_var = gfc_evaluate_now (se.expr, &block);
2690 gfc_add_block_to_block (&block, &se.post);
2691 tree type = TREE_TYPE (if_var);
2692 ifc = fold_build2_loc (input_location, NE_EXPR,
2693 boolean_type_node, if_var,
2694 build_zero_cst (type));
2695 }
2696 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
2697 tree c_bool_type = TREE_TYPE (TREE_TYPE (decl));
2698 ifc = fold_convert (c_bool_type, ifc);
2699 gfc_add_expr_to_block (&block,
2700 build_call_expr_loc (input_location, decl, 2,
2701 build_int_cst (integer_type_node,
2702 mask), ifc));
2703 return gfc_finish_block (&block);
2704}
2705
2706static tree
2707gfc_trans_omp_cancellation_point (gfc_code *code)
2708{
2709 int mask = 0;
2710 switch (code->ext.omp_clauses->cancel)
2711 {
2712 case OMP_CANCEL_PARALLEL: mask = 1; break;
2713 case OMP_CANCEL_DO: mask = 2; break;
2714 case OMP_CANCEL_SECTIONS: mask = 4; break;
2715 case OMP_CANCEL_TASKGROUP: mask = 8; break;
2716 default: gcc_unreachable ();
2717 }
2718 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCELLATION_POINT);
2719 return build_call_expr_loc (input_location, decl, 1,
2720 build_int_cst (integer_type_node, mask));
2721}
2722
6c7a4dfd
JJ
2723static tree
2724gfc_trans_omp_critical (gfc_code *code)
2725{
2726 tree name = NULL_TREE, stmt;
2727 if (code->ext.omp_name != NULL)
2728 name = get_identifier (code->ext.omp_name);
2729 stmt = gfc_trans_code (code->block->next);
5d44e5c8 2730 return build2_loc (input_location, OMP_CRITICAL, void_type_node, stmt, name);
6c7a4dfd
JJ
2731}
2732
04924d6a
NF
2733typedef struct dovar_init_d {
2734 tree var;
2735 tree init;
2736} dovar_init;
2737
04924d6a 2738
6c7a4dfd 2739static tree
dd2fc525 2740gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
a68ab351 2741 gfc_omp_clauses *do_clauses, tree par_clauses)
6c7a4dfd
JJ
2742{
2743 gfc_se se;
2744 tree dovar, stmt, from, to, step, type, init, cond, incr;
2745 tree count = NULL_TREE, cycle_label, tmp, omp_clauses;
2746 stmtblock_t block;
2747 stmtblock_t body;
742fae05 2748 gfc_omp_clauses *clauses = code->ext.omp_clauses;
a68ab351 2749 int i, collapse = clauses->collapse;
6e1aa848 2750 vec<dovar_init> inits = vNULL;
04924d6a
NF
2751 dovar_init *di;
2752 unsigned ix;
6c7a4dfd 2753
a68ab351
JJ
2754 if (collapse <= 0)
2755 collapse = 1;
2756
c4fae39e 2757 code = code->block->next;
6c7a4dfd
JJ
2758 gcc_assert (code->op == EXEC_DO);
2759
a68ab351
JJ
2760 init = make_tree_vec (collapse);
2761 cond = make_tree_vec (collapse);
2762 incr = make_tree_vec (collapse);
2763
6c7a4dfd
JJ
2764 if (pblock == NULL)
2765 {
2766 gfc_start_block (&block);
2767 pblock = &block;
2768 }
2769
742fae05 2770 omp_clauses = gfc_trans_omp_clauses (pblock, do_clauses, code->loc);
6c7a4dfd 2771
a68ab351 2772 for (i = 0; i < collapse; i++)
6c7a4dfd 2773 {
a68ab351
JJ
2774 int simple = 0;
2775 int dovar_found = 0;
281e33e1 2776 tree dovar_decl;
a68ab351
JJ
2777
2778 if (clauses)
6c7a4dfd 2779 {
f014c653
JJ
2780 gfc_omp_namelist *n = NULL;
2781 if (op != EXEC_OMP_DISTRIBUTE)
2782 for (n = clauses->lists[(op == EXEC_OMP_SIMD && collapse == 1)
2783 ? OMP_LIST_LINEAR : OMP_LIST_LASTPRIVATE];
2784 n != NULL; n = n->next)
2785 if (code->ext.iterator->var->symtree->n.sym == n->sym)
2786 break;
a68ab351
JJ
2787 if (n != NULL)
2788 dovar_found = 1;
dd2fc525 2789 else if (n == NULL && op != EXEC_OMP_SIMD)
a68ab351
JJ
2790 for (n = clauses->lists[OMP_LIST_PRIVATE]; n != NULL; n = n->next)
2791 if (code->ext.iterator->var->symtree->n.sym == n->sym)
2792 break;
2793 if (n != NULL)
2794 dovar_found++;
6c7a4dfd 2795 }
a68ab351
JJ
2796
2797 /* Evaluate all the expressions in the iterator. */
2798 gfc_init_se (&se, NULL);
2799 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
2800 gfc_add_block_to_block (pblock, &se.pre);
2801 dovar = se.expr;
2802 type = TREE_TYPE (dovar);
2803 gcc_assert (TREE_CODE (type) == INTEGER_TYPE);
2804
2805 gfc_init_se (&se, NULL);
2806 gfc_conv_expr_val (&se, code->ext.iterator->start);
2807 gfc_add_block_to_block (pblock, &se.pre);
2808 from = gfc_evaluate_now (se.expr, pblock);
2809
2810 gfc_init_se (&se, NULL);
2811 gfc_conv_expr_val (&se, code->ext.iterator->end);
2812 gfc_add_block_to_block (pblock, &se.pre);
2813 to = gfc_evaluate_now (se.expr, pblock);
2814
2815 gfc_init_se (&se, NULL);
2816 gfc_conv_expr_val (&se, code->ext.iterator->step);
2817 gfc_add_block_to_block (pblock, &se.pre);
2818 step = gfc_evaluate_now (se.expr, pblock);
281e33e1 2819 dovar_decl = dovar;
a68ab351
JJ
2820
2821 /* Special case simple loops. */
281e33e1
JJ
2822 if (TREE_CODE (dovar) == VAR_DECL)
2823 {
2824 if (integer_onep (step))
2825 simple = 1;
2826 else if (tree_int_cst_equal (step, integer_minus_one_node))
2827 simple = -1;
2828 }
2829 else
2830 dovar_decl
dd2fc525
JJ
2831 = gfc_trans_omp_variable (code->ext.iterator->var->symtree->n.sym,
2832 false);
a68ab351
JJ
2833
2834 /* Loop body. */
2835 if (simple)
6c7a4dfd 2836 {
726a989a 2837 TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, dovar, from);
edaadf74
JJ
2838 /* The condition should not be folded. */
2839 TREE_VEC_ELT (cond, i) = build2_loc (input_location, simple > 0
2840 ? LE_EXPR : GE_EXPR,
2841 boolean_type_node, dovar, to);
65a9ca82
TB
2842 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR,
2843 type, dovar, step);
2844 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location,
2845 MODIFY_EXPR,
2846 type, dovar,
2847 TREE_VEC_ELT (incr, i));
a68ab351
JJ
2848 }
2849 else
2850 {
2851 /* STEP is not 1 or -1. Use:
2852 for (count = 0; count < (to + step - from) / step; count++)
2853 {
2854 dovar = from + count * step;
2855 body;
2856 cycle_label:;
2857 } */
65a9ca82
TB
2858 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, step, from);
2859 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, to, tmp);
2860 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, type, tmp,
2861 step);
a68ab351
JJ
2862 tmp = gfc_evaluate_now (tmp, pblock);
2863 count = gfc_create_var (type, "count");
726a989a 2864 TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, count,
a68ab351 2865 build_int_cst (type, 0));
edaadf74
JJ
2866 /* The condition should not be folded. */
2867 TREE_VEC_ELT (cond, i) = build2_loc (input_location, LT_EXPR,
2868 boolean_type_node,
2869 count, tmp);
65a9ca82
TB
2870 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR,
2871 type, count,
2872 build_int_cst (type, 1));
2873 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location,
2874 MODIFY_EXPR, type, count,
2875 TREE_VEC_ELT (incr, i));
a68ab351
JJ
2876
2877 /* Initialize DOVAR. */
65a9ca82
TB
2878 tmp = fold_build2_loc (input_location, MULT_EXPR, type, count, step);
2879 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, from, tmp);
f32682ca 2880 dovar_init e = {dovar, tmp};
9771b263 2881 inits.safe_push (e);
6c7a4dfd 2882 }
6c7a4dfd 2883
a68ab351
JJ
2884 if (!dovar_found)
2885 {
dd2fc525
JJ
2886 if (op == EXEC_OMP_SIMD)
2887 {
2888 if (collapse == 1)
2889 {
2890 tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
2891 OMP_CLAUSE_LINEAR_STEP (tmp) = step;
2892 }
2893 else
2894 tmp = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
2895 if (!simple)
2896 dovar_found = 2;
2897 }
2898 else
2899 tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
281e33e1 2900 OMP_CLAUSE_DECL (tmp) = dovar_decl;
a68ab351
JJ
2901 omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
2902 }
dd2fc525 2903 if (dovar_found == 2)
a68ab351
JJ
2904 {
2905 tree c = NULL;
2906
2907 tmp = NULL;
2908 if (!simple)
2909 {
2910 /* If dovar is lastprivate, but different counter is used,
2911 dovar += step needs to be added to
2912 OMP_CLAUSE_LASTPRIVATE_STMT, otherwise the copied dovar
2913 will have the value on entry of the last loop, rather
2914 than value after iterator increment. */
2915 tmp = gfc_evaluate_now (step, pblock);
65a9ca82
TB
2916 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, dovar,
2917 tmp);
2918 tmp = fold_build2_loc (input_location, MODIFY_EXPR, type,
2919 dovar, tmp);
a68ab351
JJ
2920 for (c = omp_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2921 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
281e33e1 2922 && OMP_CLAUSE_DECL (c) == dovar_decl)
a68ab351
JJ
2923 {
2924 OMP_CLAUSE_LASTPRIVATE_STMT (c) = tmp;
2925 break;
2926 }
dd2fc525
JJ
2927 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2928 && OMP_CLAUSE_DECL (c) == dovar_decl)
2929 {
2930 OMP_CLAUSE_LINEAR_STMT (c) = tmp;
2931 break;
2932 }
a68ab351 2933 }
dd2fc525 2934 if (c == NULL && op == EXEC_OMP_DO && par_clauses != NULL)
a68ab351
JJ
2935 {
2936 for (c = par_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2937 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
281e33e1 2938 && OMP_CLAUSE_DECL (c) == dovar_decl)
a68ab351 2939 {
c2255bc4
AH
2940 tree l = build_omp_clause (input_location,
2941 OMP_CLAUSE_LASTPRIVATE);
281e33e1 2942 OMP_CLAUSE_DECL (l) = dovar_decl;
a68ab351
JJ
2943 OMP_CLAUSE_CHAIN (l) = omp_clauses;
2944 OMP_CLAUSE_LASTPRIVATE_STMT (l) = tmp;
2945 omp_clauses = l;
2946 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_SHARED);
2947 break;
2948 }
2949 }
2950 gcc_assert (simple || c != NULL);
2951 }
2952 if (!simple)
2953 {
dd2fc525
JJ
2954 if (op != EXEC_OMP_SIMD)
2955 tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
2956 else if (collapse == 1)
2957 {
2958 tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
2959 OMP_CLAUSE_LINEAR_STEP (tmp) = step;
2960 OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
2961 OMP_CLAUSE_LINEAR_NO_COPYOUT (tmp) = 1;
2962 }
2963 else
2964 tmp = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
a68ab351
JJ
2965 OMP_CLAUSE_DECL (tmp) = count;
2966 omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
2967 }
2968
2969 if (i + 1 < collapse)
2970 code = code->block->next;
6c7a4dfd
JJ
2971 }
2972
a68ab351 2973 if (pblock != &block)
6c7a4dfd 2974 {
87a60f68 2975 pushlevel ();
a68ab351 2976 gfc_start_block (&block);
6c7a4dfd 2977 }
a68ab351
JJ
2978
2979 gfc_start_block (&body);
2980
9771b263 2981 FOR_EACH_VEC_ELT (inits, ix, di)
04924d6a 2982 gfc_add_modify (&body, di->var, di->init);
9771b263 2983 inits.release ();
6c7a4dfd
JJ
2984
2985 /* Cycle statement is implemented with a goto. Exit statement must not be
2986 present for this loop. */
2987 cycle_label = gfc_build_label_decl (NULL_TREE);
2988
e7041633 2989 /* Put these labels where they can be found later. */
6c7a4dfd 2990
7602cb87
JJ
2991 code->cycle_label = cycle_label;
2992 code->exit_label = NULL_TREE;
6c7a4dfd
JJ
2993
2994 /* Main loop body. */
2995 tmp = gfc_trans_omp_code (code->block->next, true);
2996 gfc_add_expr_to_block (&body, tmp);
2997
2998 /* Label for cycle statements (if needed). */
2999 if (TREE_USED (cycle_label))
3000 {
3001 tmp = build1_v (LABEL_EXPR, cycle_label);
3002 gfc_add_expr_to_block (&body, tmp);
3003 }
3004
3005 /* End of loop body. */
f014c653
JJ
3006 switch (op)
3007 {
3008 case EXEC_OMP_SIMD: stmt = make_node (OMP_SIMD); break;
3009 case EXEC_OMP_DO: stmt = make_node (OMP_FOR); break;
3010 case EXEC_OMP_DISTRIBUTE: stmt = make_node (OMP_DISTRIBUTE); break;
3011 default: gcc_unreachable ();
3012 }
6c7a4dfd
JJ
3013
3014 TREE_TYPE (stmt) = void_type_node;
3015 OMP_FOR_BODY (stmt) = gfc_finish_block (&body);
3016 OMP_FOR_CLAUSES (stmt) = omp_clauses;
3017 OMP_FOR_INIT (stmt) = init;
3018 OMP_FOR_COND (stmt) = cond;
3019 OMP_FOR_INCR (stmt) = incr;
3020 gfc_add_expr_to_block (&block, stmt);
3021
3022 return gfc_finish_block (&block);
3023}
3024
3025static tree
3026gfc_trans_omp_flush (void)
3027{
e79983f4 3028 tree decl = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
db3927fb 3029 return build_call_expr_loc (input_location, decl, 0);
6c7a4dfd
JJ
3030}
3031
3032static tree
3033gfc_trans_omp_master (gfc_code *code)
3034{
3035 tree stmt = gfc_trans_code (code->block->next);
3036 if (IS_EMPTY_STMT (stmt))
3037 return stmt;
3038 return build1_v (OMP_MASTER, stmt);
3039}
3040
3041static tree
3042gfc_trans_omp_ordered (gfc_code *code)
3043{
3044 return build1_v (OMP_ORDERED, gfc_trans_code (code->block->next));
3045}
3046
3047static tree
3048gfc_trans_omp_parallel (gfc_code *code)
3049{
3050 stmtblock_t block;
3051 tree stmt, omp_clauses;
3052
3053 gfc_start_block (&block);
3054 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
3055 code->loc);
3056 stmt = gfc_trans_omp_code (code->block->next, true);
5d44e5c8
TB
3057 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
3058 omp_clauses);
6c7a4dfd
JJ
3059 gfc_add_expr_to_block (&block, stmt);
3060 return gfc_finish_block (&block);
3061}
3062
dd2fc525
JJ
3063enum
3064{
3065 GFC_OMP_SPLIT_SIMD,
3066 GFC_OMP_SPLIT_DO,
3067 GFC_OMP_SPLIT_PARALLEL,
f014c653
JJ
3068 GFC_OMP_SPLIT_DISTRIBUTE,
3069 GFC_OMP_SPLIT_TEAMS,
3070 GFC_OMP_SPLIT_TARGET,
dd2fc525
JJ
3071 GFC_OMP_SPLIT_NUM
3072};
3073
3074enum
3075{
3076 GFC_OMP_MASK_SIMD = (1 << GFC_OMP_SPLIT_SIMD),
3077 GFC_OMP_MASK_DO = (1 << GFC_OMP_SPLIT_DO),
f014c653
JJ
3078 GFC_OMP_MASK_PARALLEL = (1 << GFC_OMP_SPLIT_PARALLEL),
3079 GFC_OMP_MASK_DISTRIBUTE = (1 << GFC_OMP_SPLIT_DISTRIBUTE),
3080 GFC_OMP_MASK_TEAMS = (1 << GFC_OMP_SPLIT_TEAMS),
3081 GFC_OMP_MASK_TARGET = (1 << GFC_OMP_SPLIT_TARGET)
dd2fc525
JJ
3082};
3083
3084static void
3085gfc_split_omp_clauses (gfc_code *code,
3086 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM])
3087{
5f23671d 3088 int mask = 0, innermost = 0;
dd2fc525
JJ
3089 memset (clausesa, 0, GFC_OMP_SPLIT_NUM * sizeof (gfc_omp_clauses));
3090 switch (code->op)
3091 {
f014c653
JJ
3092 case EXEC_OMP_DISTRIBUTE:
3093 innermost = GFC_OMP_SPLIT_DISTRIBUTE;
3094 break;
3095 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
3096 mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
3097 innermost = GFC_OMP_SPLIT_DO;
3098 break;
3099 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
3100 mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL
3101 | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
3102 innermost = GFC_OMP_SPLIT_SIMD;
3103 break;
3104 case EXEC_OMP_DISTRIBUTE_SIMD:
3105 mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
3106 innermost = GFC_OMP_SPLIT_SIMD;
3107 break;
3108 case EXEC_OMP_DO:
3109 innermost = GFC_OMP_SPLIT_DO;
3110 break;
dd2fc525
JJ
3111 case EXEC_OMP_DO_SIMD:
3112 mask = GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
3113 innermost = GFC_OMP_SPLIT_SIMD;
3114 break;
f014c653
JJ
3115 case EXEC_OMP_PARALLEL:
3116 innermost = GFC_OMP_SPLIT_PARALLEL;
3117 break;
dd2fc525
JJ
3118 case EXEC_OMP_PARALLEL_DO:
3119 mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
3120 innermost = GFC_OMP_SPLIT_DO;
3121 break;
3122 case EXEC_OMP_PARALLEL_DO_SIMD:
3123 mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
3124 innermost = GFC_OMP_SPLIT_SIMD;
3125 break;
f014c653
JJ
3126 case EXEC_OMP_SIMD:
3127 innermost = GFC_OMP_SPLIT_SIMD;
3128 break;
3129 case EXEC_OMP_TARGET:
3130 innermost = GFC_OMP_SPLIT_TARGET;
3131 break;
3132 case EXEC_OMP_TARGET_TEAMS:
3133 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS;
3134 innermost = GFC_OMP_SPLIT_TEAMS;
3135 break;
3136 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
3137 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS
3138 | GFC_OMP_MASK_DISTRIBUTE;
3139 innermost = GFC_OMP_SPLIT_DISTRIBUTE;
3140 break;
3141 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
3142 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
3143 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
3144 innermost = GFC_OMP_SPLIT_DO;
3145 break;
3146 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
3147 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
3148 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
3149 innermost = GFC_OMP_SPLIT_SIMD;
3150 break;
3151 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
3152 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS
3153 | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
3154 innermost = GFC_OMP_SPLIT_SIMD;
3155 break;
3156 case EXEC_OMP_TEAMS:
3157 innermost = GFC_OMP_SPLIT_TEAMS;
3158 break;
3159 case EXEC_OMP_TEAMS_DISTRIBUTE:
3160 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE;
3161 innermost = GFC_OMP_SPLIT_DISTRIBUTE;
3162 break;
3163 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
3164 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
3165 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
3166 innermost = GFC_OMP_SPLIT_DO;
3167 break;
3168 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
3169 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
3170 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
3171 innermost = GFC_OMP_SPLIT_SIMD;
3172 break;
3173 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
3174 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
3175 innermost = GFC_OMP_SPLIT_SIMD;
3176 break;
dd2fc525
JJ
3177 default:
3178 gcc_unreachable ();
3179 }
f014c653
JJ
3180 if (mask == 0)
3181 {
3182 clausesa[innermost] = *code->ext.omp_clauses;
3183 return;
3184 }
dd2fc525
JJ
3185 if (code->ext.omp_clauses != NULL)
3186 {
f014c653
JJ
3187 if (mask & GFC_OMP_MASK_TARGET)
3188 {
3189 /* First the clauses that are unique to some constructs. */
3190 clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_MAP]
3191 = code->ext.omp_clauses->lists[OMP_LIST_MAP];
3192 clausesa[GFC_OMP_SPLIT_TARGET].device
3193 = code->ext.omp_clauses->device;
3194 }
3195 if (mask & GFC_OMP_MASK_TEAMS)
3196 {
3197 /* First the clauses that are unique to some constructs. */
3198 clausesa[GFC_OMP_SPLIT_TEAMS].num_teams
3199 = code->ext.omp_clauses->num_teams;
3200 clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit
3201 = code->ext.omp_clauses->thread_limit;
3202 /* Shared and default clauses are allowed on parallel and teams. */
3203 clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_SHARED]
3204 = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
3205 clausesa[GFC_OMP_SPLIT_TEAMS].default_sharing
3206 = code->ext.omp_clauses->default_sharing;
3207 }
3208 if (mask & GFC_OMP_MASK_DISTRIBUTE)
3209 {
3210 /* First the clauses that are unique to some constructs. */
3211 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_sched_kind
3212 = code->ext.omp_clauses->dist_sched_kind;
3213 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_chunk_size
3214 = code->ext.omp_clauses->dist_chunk_size;
3215 /* Duplicate collapse. */
3216 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].collapse
3217 = code->ext.omp_clauses->collapse;
3218 }
dd2fc525
JJ
3219 if (mask & GFC_OMP_MASK_PARALLEL)
3220 {
3221 /* First the clauses that are unique to some constructs. */
3222 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_COPYIN]
3223 = code->ext.omp_clauses->lists[OMP_LIST_COPYIN];
3224 clausesa[GFC_OMP_SPLIT_PARALLEL].num_threads
3225 = code->ext.omp_clauses->num_threads;
3226 clausesa[GFC_OMP_SPLIT_PARALLEL].proc_bind
3227 = code->ext.omp_clauses->proc_bind;
3228 /* Shared and default clauses are allowed on parallel and teams. */
3229 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_SHARED]
3230 = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
3231 clausesa[GFC_OMP_SPLIT_PARALLEL].default_sharing
3232 = code->ext.omp_clauses->default_sharing;
dd2fc525
JJ
3233 }
3234 if (mask & GFC_OMP_MASK_DO)
3235 {
3236 /* First the clauses that are unique to some constructs. */
3237 clausesa[GFC_OMP_SPLIT_DO].ordered
3238 = code->ext.omp_clauses->ordered;
3239 clausesa[GFC_OMP_SPLIT_DO].sched_kind
3240 = code->ext.omp_clauses->sched_kind;
3241 clausesa[GFC_OMP_SPLIT_DO].chunk_size
3242 = code->ext.omp_clauses->chunk_size;
3243 clausesa[GFC_OMP_SPLIT_DO].nowait
3244 = code->ext.omp_clauses->nowait;
3245 /* Duplicate collapse. */
3246 clausesa[GFC_OMP_SPLIT_DO].collapse
3247 = code->ext.omp_clauses->collapse;
3248 }
3249 if (mask & GFC_OMP_MASK_SIMD)
3250 {
3251 clausesa[GFC_OMP_SPLIT_SIMD].safelen_expr
3252 = code->ext.omp_clauses->safelen_expr;
3253 clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_LINEAR]
3254 = code->ext.omp_clauses->lists[OMP_LIST_LINEAR];
3255 clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_ALIGNED]
3256 = code->ext.omp_clauses->lists[OMP_LIST_ALIGNED];
3257 /* Duplicate collapse. */
3258 clausesa[GFC_OMP_SPLIT_SIMD].collapse
3259 = code->ext.omp_clauses->collapse;
3260 }
3261 /* Private clause is supported on all constructs but target,
3262 it is enough to put it on the innermost one. For
3263 !$ omp do put it on parallel though,
3264 as that's what we did for OpenMP 3.1. */
3265 clausesa[innermost == GFC_OMP_SPLIT_DO
3266 ? (int) GFC_OMP_SPLIT_PARALLEL
3267 : innermost].lists[OMP_LIST_PRIVATE]
3268 = code->ext.omp_clauses->lists[OMP_LIST_PRIVATE];
3269 /* Firstprivate clause is supported on all constructs but
3270 target and simd. Put it on the outermost of those and
3271 duplicate on parallel. */
f014c653
JJ
3272 if (mask & GFC_OMP_MASK_TEAMS)
3273 clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_FIRSTPRIVATE]
3274 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
3275 else if (mask & GFC_OMP_MASK_DISTRIBUTE)
3276 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_FIRSTPRIVATE]
3277 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
dd2fc525
JJ
3278 if (mask & GFC_OMP_MASK_PARALLEL)
3279 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_FIRSTPRIVATE]
3280 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
3281 else if (mask & GFC_OMP_MASK_DO)
3282 clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_FIRSTPRIVATE]
3283 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
3284 /* Lastprivate is allowed on do and simd. In
3285 parallel do{, simd} we actually want to put it on
3286 parallel rather than do. */
3287 if (mask & GFC_OMP_MASK_PARALLEL)
3288 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_LASTPRIVATE]
3289 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
3290 else if (mask & GFC_OMP_MASK_DO)
3291 clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_LASTPRIVATE]
3292 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
3293 if (mask & GFC_OMP_MASK_SIMD)
3294 clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_LASTPRIVATE]
3295 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
3296 /* Reduction is allowed on simd, do, parallel and teams.
3297 Duplicate it on all of them, but omit on do if
3298 parallel is present. */
f014c653
JJ
3299 if (mask & GFC_OMP_MASK_TEAMS)
3300 clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_REDUCTION]
3301 = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
5f23671d
JJ
3302 if (mask & GFC_OMP_MASK_PARALLEL)
3303 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_REDUCTION]
3304 = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
3305 else if (mask & GFC_OMP_MASK_DO)
3306 clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_REDUCTION]
3307 = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
3308 if (mask & GFC_OMP_MASK_SIMD)
3309 clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_REDUCTION]
3310 = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
f014c653
JJ
3311 /* FIXME: This is currently being discussed. */
3312 if (mask & GFC_OMP_MASK_PARALLEL)
3313 clausesa[GFC_OMP_SPLIT_PARALLEL].if_expr
3314 = code->ext.omp_clauses->if_expr;
3315 else
3316 clausesa[GFC_OMP_SPLIT_TARGET].if_expr
3317 = code->ext.omp_clauses->if_expr;
dd2fc525
JJ
3318 }
3319 if ((mask & (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
3320 == (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
3321 clausesa[GFC_OMP_SPLIT_DO].nowait = true;
3322}
3323
6c7a4dfd 3324static tree
f014c653
JJ
3325gfc_trans_omp_do_simd (gfc_code *code, stmtblock_t *pblock,
3326 gfc_omp_clauses *clausesa, tree omp_clauses)
6c7a4dfd 3327{
f014c653 3328 stmtblock_t block;
dd2fc525
JJ
3329 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
3330 tree stmt, body, omp_do_clauses = NULL_TREE;
6c7a4dfd 3331
f014c653
JJ
3332 if (pblock == NULL)
3333 gfc_start_block (&block);
3334 else
3335 gfc_init_block (&block);
6c7a4dfd 3336
dd2fc525 3337 if (clausesa == NULL)
6c7a4dfd 3338 {
dd2fc525
JJ
3339 clausesa = clausesa_buf;
3340 gfc_split_omp_clauses (code, clausesa);
6c7a4dfd 3341 }
92d28cbb
JJ
3342 if (gfc_option.gfc_flag_openmp)
3343 omp_do_clauses
3344 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DO], code->loc);
f014c653 3345 body = gfc_trans_omp_do (code, EXEC_OMP_SIMD, pblock ? pblock : &block,
dd2fc525 3346 &clausesa[GFC_OMP_SPLIT_SIMD], omp_clauses);
f014c653
JJ
3347 if (pblock == NULL)
3348 {
3349 if (TREE_CODE (body) != BIND_EXPR)
3350 body = build3_v (BIND_EXPR, NULL, body, poplevel (1, 0));
3351 else
3352 poplevel (0, 0);
3353 }
3354 else if (TREE_CODE (body) != BIND_EXPR)
3355 body = build3_v (BIND_EXPR, NULL, body, NULL_TREE);
92d28cbb
JJ
3356 if (gfc_option.gfc_flag_openmp)
3357 {
3358 stmt = make_node (OMP_FOR);
3359 TREE_TYPE (stmt) = void_type_node;
3360 OMP_FOR_BODY (stmt) = body;
3361 OMP_FOR_CLAUSES (stmt) = omp_do_clauses;
3362 }
3363 else
3364 stmt = body;
dd2fc525
JJ
3365 gfc_add_expr_to_block (&block, stmt);
3366 return gfc_finish_block (&block);
3367}
3368
3369static tree
f014c653
JJ
3370gfc_trans_omp_parallel_do (gfc_code *code, stmtblock_t *pblock,
3371 gfc_omp_clauses *clausesa)
dd2fc525 3372{
f014c653
JJ
3373 stmtblock_t block, *new_pblock = pblock;
3374 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
dd2fc525
JJ
3375 tree stmt, omp_clauses = NULL_TREE;
3376
f014c653
JJ
3377 if (pblock == NULL)
3378 gfc_start_block (&block);
3379 else
3380 gfc_init_block (&block);
dd2fc525 3381
f014c653
JJ
3382 if (clausesa == NULL)
3383 {
3384 clausesa = clausesa_buf;
3385 gfc_split_omp_clauses (code, clausesa);
3386 }
dd2fc525
JJ
3387 omp_clauses
3388 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
3389 code->loc);
f014c653
JJ
3390 if (pblock == NULL)
3391 {
3392 if (!clausesa[GFC_OMP_SPLIT_DO].ordered
3393 && clausesa[GFC_OMP_SPLIT_DO].sched_kind != OMP_SCHED_STATIC)
3394 new_pblock = &block;
3395 else
3396 pushlevel ();
3397 }
3398 stmt = gfc_trans_omp_do (code, EXEC_OMP_DO, new_pblock,
dd2fc525 3399 &clausesa[GFC_OMP_SPLIT_DO], omp_clauses);
f014c653
JJ
3400 if (pblock == NULL)
3401 {
3402 if (TREE_CODE (stmt) != BIND_EXPR)
3403 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
3404 else
3405 poplevel (0, 0);
3406 }
3407 else if (TREE_CODE (stmt) != BIND_EXPR)
3408 stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
dd2fc525
JJ
3409 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
3410 omp_clauses);
3411 OMP_PARALLEL_COMBINED (stmt) = 1;
3412 gfc_add_expr_to_block (&block, stmt);
3413 return gfc_finish_block (&block);
3414}
3415
3416static tree
f014c653
JJ
3417gfc_trans_omp_parallel_do_simd (gfc_code *code, stmtblock_t *pblock,
3418 gfc_omp_clauses *clausesa)
dd2fc525
JJ
3419{
3420 stmtblock_t block;
f014c653 3421 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
dd2fc525
JJ
3422 tree stmt, omp_clauses = NULL_TREE;
3423
f014c653
JJ
3424 if (pblock == NULL)
3425 gfc_start_block (&block);
3426 else
3427 gfc_init_block (&block);
dd2fc525 3428
f014c653
JJ
3429 if (clausesa == NULL)
3430 {
3431 clausesa = clausesa_buf;
3432 gfc_split_omp_clauses (code, clausesa);
3433 }
92d28cbb
JJ
3434 if (gfc_option.gfc_flag_openmp)
3435 omp_clauses
3436 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
3437 code->loc);
f014c653
JJ
3438 if (pblock == NULL)
3439 pushlevel ();
3440 stmt = gfc_trans_omp_do_simd (code, pblock, clausesa, omp_clauses);
3441 if (pblock == NULL)
3442 {
3443 if (TREE_CODE (stmt) != BIND_EXPR)
3444 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
3445 else
3446 poplevel (0, 0);
3447 }
3448 else if (TREE_CODE (stmt) != BIND_EXPR)
3449 stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
92d28cbb
JJ
3450 if (gfc_option.gfc_flag_openmp)
3451 {
3452 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
3453 omp_clauses);
3454 OMP_PARALLEL_COMBINED (stmt) = 1;
3455 }
6c7a4dfd
JJ
3456 gfc_add_expr_to_block (&block, stmt);
3457 return gfc_finish_block (&block);
3458}
3459
3460static tree
3461gfc_trans_omp_parallel_sections (gfc_code *code)
3462{
3463 stmtblock_t block;
3464 gfc_omp_clauses section_clauses;
3465 tree stmt, omp_clauses;
3466
3467 memset (&section_clauses, 0, sizeof (section_clauses));
3468 section_clauses.nowait = true;
3469
3470 gfc_start_block (&block);
3471 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
3472 code->loc);
87a60f68 3473 pushlevel ();
6c7a4dfd
JJ
3474 stmt = gfc_trans_omp_sections (code, &section_clauses);
3475 if (TREE_CODE (stmt) != BIND_EXPR)
87a60f68 3476 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6c7a4dfd 3477 else
87a60f68 3478 poplevel (0, 0);
5d44e5c8
TB
3479 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
3480 omp_clauses);
761041be 3481 OMP_PARALLEL_COMBINED (stmt) = 1;
6c7a4dfd
JJ
3482 gfc_add_expr_to_block (&block, stmt);
3483 return gfc_finish_block (&block);
3484}
3485
3486static tree
3487gfc_trans_omp_parallel_workshare (gfc_code *code)
3488{
3489 stmtblock_t block;
3490 gfc_omp_clauses workshare_clauses;
3491 tree stmt, omp_clauses;
3492
3493 memset (&workshare_clauses, 0, sizeof (workshare_clauses));
3494 workshare_clauses.nowait = true;
3495
3496 gfc_start_block (&block);
3497 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
3498 code->loc);
87a60f68 3499 pushlevel ();
6c7a4dfd
JJ
3500 stmt = gfc_trans_omp_workshare (code, &workshare_clauses);
3501 if (TREE_CODE (stmt) != BIND_EXPR)
87a60f68 3502 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6c7a4dfd 3503 else
87a60f68 3504 poplevel (0, 0);
5d44e5c8
TB
3505 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
3506 omp_clauses);
761041be 3507 OMP_PARALLEL_COMBINED (stmt) = 1;
6c7a4dfd
JJ
3508 gfc_add_expr_to_block (&block, stmt);
3509 return gfc_finish_block (&block);
3510}
3511
3512static tree
3513gfc_trans_omp_sections (gfc_code *code, gfc_omp_clauses *clauses)
3514{
3515 stmtblock_t block, body;
3516 tree omp_clauses, stmt;
3517 bool has_lastprivate = clauses->lists[OMP_LIST_LASTPRIVATE] != NULL;
3518
3519 gfc_start_block (&block);
3520
3521 omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
3522
3523 gfc_init_block (&body);
3524 for (code = code->block; code; code = code->block)
3525 {
3526 /* Last section is special because of lastprivate, so even if it
3527 is empty, chain it in. */
3528 stmt = gfc_trans_omp_code (code->next,
3529 has_lastprivate && code->block == NULL);
3530 if (! IS_EMPTY_STMT (stmt))
3531 {
3532 stmt = build1_v (OMP_SECTION, stmt);
3533 gfc_add_expr_to_block (&body, stmt);
3534 }
3535 }
3536 stmt = gfc_finish_block (&body);
3537
5d44e5c8
TB
3538 stmt = build2_loc (input_location, OMP_SECTIONS, void_type_node, stmt,
3539 omp_clauses);
6c7a4dfd
JJ
3540 gfc_add_expr_to_block (&block, stmt);
3541
3542 return gfc_finish_block (&block);
3543}
3544
3545static tree
3546gfc_trans_omp_single (gfc_code *code, gfc_omp_clauses *clauses)
3547{
3548 tree omp_clauses = gfc_trans_omp_clauses (NULL, clauses, code->loc);
3549 tree stmt = gfc_trans_omp_code (code->block->next, true);
5d44e5c8
TB
3550 stmt = build2_loc (input_location, OMP_SINGLE, void_type_node, stmt,
3551 omp_clauses);
6c7a4dfd
JJ
3552 return stmt;
3553}
3554
a68ab351
JJ
3555static tree
3556gfc_trans_omp_task (gfc_code *code)
3557{
3558 stmtblock_t block;
726a989a 3559 tree stmt, omp_clauses;
a68ab351
JJ
3560
3561 gfc_start_block (&block);
3562 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
3563 code->loc);
726a989a 3564 stmt = gfc_trans_omp_code (code->block->next, true);
5d44e5c8
TB
3565 stmt = build2_loc (input_location, OMP_TASK, void_type_node, stmt,
3566 omp_clauses);
a68ab351
JJ
3567 gfc_add_expr_to_block (&block, stmt);
3568 return gfc_finish_block (&block);
3569}
3570
dd2fc525
JJ
3571static tree
3572gfc_trans_omp_taskgroup (gfc_code *code)
3573{
3574 tree stmt = gfc_trans_code (code->block->next);
3575 return build1_loc (input_location, OMP_TASKGROUP, void_type_node, stmt);
3576}
3577
a68ab351
JJ
3578static tree
3579gfc_trans_omp_taskwait (void)
3580{
e79983f4 3581 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
db3927fb 3582 return build_call_expr_loc (input_location, decl, 0);
a68ab351
JJ
3583}
3584
20906c66
JJ
3585static tree
3586gfc_trans_omp_taskyield (void)
3587{
e79983f4 3588 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
20906c66
JJ
3589 return build_call_expr_loc (input_location, decl, 0);
3590}
3591
f014c653
JJ
3592static tree
3593gfc_trans_omp_distribute (gfc_code *code, gfc_omp_clauses *clausesa)
3594{
3595 stmtblock_t block;
3596 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
3597 tree stmt, omp_clauses = NULL_TREE;
3598
3599 gfc_start_block (&block);
3600 if (clausesa == NULL)
3601 {
3602 clausesa = clausesa_buf;
3603 gfc_split_omp_clauses (code, clausesa);
3604 }
3605 if (gfc_option.gfc_flag_openmp)
3606 omp_clauses
3607 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
3608 code->loc);
3609 switch (code->op)
3610 {
3611 case EXEC_OMP_DISTRIBUTE:
3612 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
3613 case EXEC_OMP_TEAMS_DISTRIBUTE:
3614 /* This is handled in gfc_trans_omp_do. */
3615 gcc_unreachable ();
3616 break;
3617 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
3618 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
3619 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
3620 stmt = gfc_trans_omp_parallel_do (code, &block, clausesa);
3621 if (TREE_CODE (stmt) != BIND_EXPR)
3622 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
3623 else
3624 poplevel (0, 0);
3625 break;
3626 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
3627 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
3628 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
3629 stmt = gfc_trans_omp_parallel_do_simd (code, &block, clausesa);
3630 if (TREE_CODE (stmt) != BIND_EXPR)
3631 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
3632 else
3633 poplevel (0, 0);
3634 break;
3635 case EXEC_OMP_DISTRIBUTE_SIMD:
3636 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
3637 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
3638 stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
3639 &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
3640 if (TREE_CODE (stmt) != BIND_EXPR)
3641 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
3642 else
3643 poplevel (0, 0);
3644 break;
3645 default:
3646 gcc_unreachable ();
3647 }
3648 if (gfc_option.gfc_flag_openmp)
3649 {
3650 tree distribute = make_node (OMP_DISTRIBUTE);
3651 TREE_TYPE (distribute) = void_type_node;
3652 OMP_FOR_BODY (distribute) = stmt;
3653 OMP_FOR_CLAUSES (distribute) = omp_clauses;
3654 stmt = distribute;
3655 }
3656 gfc_add_expr_to_block (&block, stmt);
3657 return gfc_finish_block (&block);
3658}
3659
3660static tree
3661gfc_trans_omp_teams (gfc_code *code, gfc_omp_clauses *clausesa)
3662{
3663 stmtblock_t block;
3664 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
3665 tree stmt, omp_clauses = NULL_TREE;
3666
3667 gfc_start_block (&block);
3668 if (clausesa == NULL)
3669 {
3670 clausesa = clausesa_buf;
3671 gfc_split_omp_clauses (code, clausesa);
3672 }
3673 if (gfc_option.gfc_flag_openmp)
3674 omp_clauses
3675 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TEAMS],
3676 code->loc);
3677 switch (code->op)
3678 {
3679 case EXEC_OMP_TARGET_TEAMS:
3680 case EXEC_OMP_TEAMS:
3681 stmt = gfc_trans_omp_code (code->block->next, true);
3682 break;
3683 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
3684 case EXEC_OMP_TEAMS_DISTRIBUTE:
3685 stmt = gfc_trans_omp_do (code, EXEC_OMP_DISTRIBUTE, NULL,
3686 &clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
3687 NULL);
3688 break;
3689 default:
3690 stmt = gfc_trans_omp_distribute (code, clausesa);
3691 break;
3692 }
3693 stmt = build2_loc (input_location, OMP_TEAMS, void_type_node, stmt,
3694 omp_clauses);
3695 gfc_add_expr_to_block (&block, stmt);
3696 return gfc_finish_block (&block);
3697}
3698
3699static tree
3700gfc_trans_omp_target (gfc_code *code)
3701{
3702 stmtblock_t block;
3703 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
3704 tree stmt, omp_clauses = NULL_TREE;
3705
3706 gfc_start_block (&block);
3707 gfc_split_omp_clauses (code, clausesa);
3708 if (gfc_option.gfc_flag_openmp)
3709 omp_clauses
3710 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TARGET],
3711 code->loc);
3712 if (code->op == EXEC_OMP_TARGET)
3713 stmt = gfc_trans_omp_code (code->block->next, true);
3714 else
3715 stmt = gfc_trans_omp_teams (code, clausesa);
3716 if (TREE_CODE (stmt) != BIND_EXPR)
3717 stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
3718 if (gfc_option.gfc_flag_openmp)
3719 stmt = build2_loc (input_location, OMP_TARGET, void_type_node, stmt,
3720 omp_clauses);
3721 gfc_add_expr_to_block (&block, stmt);
3722 return gfc_finish_block (&block);
3723}
3724
3725static tree
3726gfc_trans_omp_target_data (gfc_code *code)
3727{
3728 stmtblock_t block;
3729 tree stmt, omp_clauses;
3730
3731 gfc_start_block (&block);
3732 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
3733 code->loc);
3734 stmt = gfc_trans_omp_code (code->block->next, true);
3735 stmt = build2_loc (input_location, OMP_TARGET_DATA, void_type_node, stmt,
3736 omp_clauses);
3737 gfc_add_expr_to_block (&block, stmt);
3738 return gfc_finish_block (&block);
3739}
3740
3741static tree
3742gfc_trans_omp_target_update (gfc_code *code)
3743{
3744 stmtblock_t block;
3745 tree stmt, omp_clauses;
3746
3747 gfc_start_block (&block);
3748 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
3749 code->loc);
3750 stmt = build1_loc (input_location, OMP_TARGET_UPDATE, void_type_node,
3751 omp_clauses);
3752 gfc_add_expr_to_block (&block, stmt);
3753 return gfc_finish_block (&block);
3754}
3755
6c7a4dfd
JJ
3756static tree
3757gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses)
3758{
34d01e1d
VL
3759 tree res, tmp, stmt;
3760 stmtblock_t block, *pblock = NULL;
3761 stmtblock_t singleblock;
3762 int saved_ompws_flags;
3763 bool singleblock_in_progress = false;
3764 /* True if previous gfc_code in workshare construct is not workshared. */
3765 bool prev_singleunit;
3766
3767 code = code->block->next;
3768
87a60f68 3769 pushlevel ();
34d01e1d 3770
34d01e1d
VL
3771 gfc_start_block (&block);
3772 pblock = &block;
3773
3774 ompws_flags = OMPWS_WORKSHARE_FLAG;
3775 prev_singleunit = false;
3776
3777 /* Translate statements one by one to trees until we reach
3778 the end of the workshare construct. Adjacent gfc_codes that
3779 are a single unit of work are clustered and encapsulated in a
3780 single OMP_SINGLE construct. */
3781 for (; code; code = code->next)
3782 {
3783 if (code->here != 0)
3784 {
3785 res = gfc_trans_label_here (code);
3786 gfc_add_expr_to_block (pblock, res);
3787 }
3788
3789 /* No dependence analysis, use for clauses with wait.
3790 If this is the last gfc_code, use default omp_clauses. */
3791 if (code->next == NULL && clauses->nowait)
3792 ompws_flags |= OMPWS_NOWAIT;
3793
3794 /* By default, every gfc_code is a single unit of work. */
3795 ompws_flags |= OMPWS_CURR_SINGLEUNIT;
3796 ompws_flags &= ~OMPWS_SCALARIZER_WS;
3797
3798 switch (code->op)
3799 {
3800 case EXEC_NOP:
3801 res = NULL_TREE;
3802 break;
3803
3804 case EXEC_ASSIGN:
3805 res = gfc_trans_assign (code);
3806 break;
3807
3808 case EXEC_POINTER_ASSIGN:
3809 res = gfc_trans_pointer_assign (code);
3810 break;
3811
3812 case EXEC_INIT_ASSIGN:
3813 res = gfc_trans_init_assign (code);
3814 break;
3815
3816 case EXEC_FORALL:
3817 res = gfc_trans_forall (code);
3818 break;
3819
3820 case EXEC_WHERE:
3821 res = gfc_trans_where (code);
3822 break;
3823
3824 case EXEC_OMP_ATOMIC:
3825 res = gfc_trans_omp_directive (code);
3826 break;
3827
3828 case EXEC_OMP_PARALLEL:
3829 case EXEC_OMP_PARALLEL_DO:
3830 case EXEC_OMP_PARALLEL_SECTIONS:
3831 case EXEC_OMP_PARALLEL_WORKSHARE:
3832 case EXEC_OMP_CRITICAL:
3833 saved_ompws_flags = ompws_flags;
3834 ompws_flags = 0;
3835 res = gfc_trans_omp_directive (code);
3836 ompws_flags = saved_ompws_flags;
3837 break;
3838
3839 default:
3840 internal_error ("gfc_trans_omp_workshare(): Bad statement code");
3841 }
3842
3843 gfc_set_backend_locus (&code->loc);
3844
3845 if (res != NULL_TREE && ! IS_EMPTY_STMT (res))
3846 {
34d01e1d
VL
3847 if (prev_singleunit)
3848 {
3849 if (ompws_flags & OMPWS_CURR_SINGLEUNIT)
3850 /* Add current gfc_code to single block. */
3851 gfc_add_expr_to_block (&singleblock, res);
3852 else
3853 {
3854 /* Finish single block and add it to pblock. */
3855 tmp = gfc_finish_block (&singleblock);
5d44e5c8
TB
3856 tmp = build2_loc (input_location, OMP_SINGLE,
3857 void_type_node, tmp, NULL_TREE);
34d01e1d
VL
3858 gfc_add_expr_to_block (pblock, tmp);
3859 /* Add current gfc_code to pblock. */
3860 gfc_add_expr_to_block (pblock, res);
3861 singleblock_in_progress = false;
3862 }
3863 }
3864 else
3865 {
3866 if (ompws_flags & OMPWS_CURR_SINGLEUNIT)
3867 {
3868 /* Start single block. */
3869 gfc_init_block (&singleblock);
3870 gfc_add_expr_to_block (&singleblock, res);
3871 singleblock_in_progress = true;
3872 }
3873 else
3874 /* Add the new statement to the block. */
3875 gfc_add_expr_to_block (pblock, res);
3876 }
3877 prev_singleunit = (ompws_flags & OMPWS_CURR_SINGLEUNIT) != 0;
3878 }
3879 }
3880
3881 /* Finish remaining SINGLE block, if we were in the middle of one. */
3882 if (singleblock_in_progress)
3883 {
3884 /* Finish single block and add it to pblock. */
3885 tmp = gfc_finish_block (&singleblock);
5d44e5c8
TB
3886 tmp = build2_loc (input_location, OMP_SINGLE, void_type_node, tmp,
3887 clauses->nowait
3888 ? build_omp_clause (input_location, OMP_CLAUSE_NOWAIT)
3889 : NULL_TREE);
34d01e1d
VL
3890 gfc_add_expr_to_block (pblock, tmp);
3891 }
3892
3893 stmt = gfc_finish_block (pblock);
3894 if (TREE_CODE (stmt) != BIND_EXPR)
3895 {
3896 if (!IS_EMPTY_STMT (stmt))
3897 {
87a60f68 3898 tree bindblock = poplevel (1, 0);
34d01e1d
VL
3899 stmt = build3_v (BIND_EXPR, NULL, stmt, bindblock);
3900 }
3901 else
87a60f68 3902 poplevel (0, 0);
34d01e1d
VL
3903 }
3904 else
87a60f68 3905 poplevel (0, 0);
34d01e1d 3906
c26dffff
JJ
3907 if (IS_EMPTY_STMT (stmt) && !clauses->nowait)
3908 stmt = gfc_trans_omp_barrier ();
3909
34d01e1d
VL
3910 ompws_flags = 0;
3911 return stmt;
6c7a4dfd
JJ
3912}
3913
3914tree
3915gfc_trans_omp_directive (gfc_code *code)
3916{
3917 switch (code->op)
3918 {
3919 case EXEC_OMP_ATOMIC:
3920 return gfc_trans_omp_atomic (code);
3921 case EXEC_OMP_BARRIER:
3922 return gfc_trans_omp_barrier ();
dd2fc525
JJ
3923 case EXEC_OMP_CANCEL:
3924 return gfc_trans_omp_cancel (code);
3925 case EXEC_OMP_CANCELLATION_POINT:
3926 return gfc_trans_omp_cancellation_point (code);
6c7a4dfd
JJ
3927 case EXEC_OMP_CRITICAL:
3928 return gfc_trans_omp_critical (code);
f014c653 3929 case EXEC_OMP_DISTRIBUTE:
6c7a4dfd 3930 case EXEC_OMP_DO:
dd2fc525
JJ
3931 case EXEC_OMP_SIMD:
3932 return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses,
3933 NULL);
f014c653
JJ
3934 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
3935 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
3936 case EXEC_OMP_DISTRIBUTE_SIMD:
3937 return gfc_trans_omp_distribute (code, NULL);
dd2fc525 3938 case EXEC_OMP_DO_SIMD:
f014c653 3939 return gfc_trans_omp_do_simd (code, NULL, NULL, NULL_TREE);
6c7a4dfd
JJ
3940 case EXEC_OMP_FLUSH:
3941 return gfc_trans_omp_flush ();
3942 case EXEC_OMP_MASTER:
3943 return gfc_trans_omp_master (code);
3944 case EXEC_OMP_ORDERED:
3945 return gfc_trans_omp_ordered (code);
3946 case EXEC_OMP_PARALLEL:
3947 return gfc_trans_omp_parallel (code);
3948 case EXEC_OMP_PARALLEL_DO:
f014c653 3949 return gfc_trans_omp_parallel_do (code, NULL, NULL);
dd2fc525 3950 case EXEC_OMP_PARALLEL_DO_SIMD:
f014c653 3951 return gfc_trans_omp_parallel_do_simd (code, NULL, NULL);
6c7a4dfd
JJ
3952 case EXEC_OMP_PARALLEL_SECTIONS:
3953 return gfc_trans_omp_parallel_sections (code);
3954 case EXEC_OMP_PARALLEL_WORKSHARE:
3955 return gfc_trans_omp_parallel_workshare (code);
3956 case EXEC_OMP_SECTIONS:
3957 return gfc_trans_omp_sections (code, code->ext.omp_clauses);
3958 case EXEC_OMP_SINGLE:
3959 return gfc_trans_omp_single (code, code->ext.omp_clauses);
f014c653
JJ
3960 case EXEC_OMP_TARGET:
3961 case EXEC_OMP_TARGET_TEAMS:
3962 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
3963 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
3964 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
3965 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
3966 return gfc_trans_omp_target (code);
3967 case EXEC_OMP_TARGET_DATA:
3968 return gfc_trans_omp_target_data (code);
3969 case EXEC_OMP_TARGET_UPDATE:
3970 return gfc_trans_omp_target_update (code);
a68ab351
JJ
3971 case EXEC_OMP_TASK:
3972 return gfc_trans_omp_task (code);
dd2fc525
JJ
3973 case EXEC_OMP_TASKGROUP:
3974 return gfc_trans_omp_taskgroup (code);
a68ab351
JJ
3975 case EXEC_OMP_TASKWAIT:
3976 return gfc_trans_omp_taskwait ();
20906c66
JJ
3977 case EXEC_OMP_TASKYIELD:
3978 return gfc_trans_omp_taskyield ();
f014c653
JJ
3979 case EXEC_OMP_TEAMS:
3980 case EXEC_OMP_TEAMS_DISTRIBUTE:
3981 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
3982 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
3983 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
3984 return gfc_trans_omp_teams (code, NULL);
6c7a4dfd
JJ
3985 case EXEC_OMP_WORKSHARE:
3986 return gfc_trans_omp_workshare (code, code->ext.omp_clauses);
3987 default:
3988 gcc_unreachable ();
3989 }
3990}
dd2fc525
JJ
3991
3992void
3993gfc_trans_omp_declare_simd (gfc_namespace *ns)
3994{
3995 if (ns->entries)
3996 return;
3997
3998 gfc_omp_declare_simd *ods;
3999 for (ods = ns->omp_declare_simd; ods; ods = ods->next)
4000 {
4001 tree c = gfc_trans_omp_clauses (NULL, ods->clauses, ods->where, true);
4002 tree fndecl = ns->proc_name->backend_decl;
4003 if (c != NULL_TREE)
4004 c = tree_cons (NULL_TREE, c, NULL_TREE);
4005 c = build_tree_list (get_identifier ("omp declare simd"), c);
4006 TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
4007 DECL_ATTRIBUTES (fndecl) = c;
4008 }
4009}