Line data Source code
1 : /* OpenMP directive translation -- generate GCC trees from gfc_code.
2 : Copyright (C) 2005-2026 Free Software Foundation, Inc.
3 : Contributed by Jakub Jelinek <jakub@redhat.com>
4 :
5 : This file is part of GCC.
6 :
7 : GCC is free software; you can redistribute it and/or modify it under
8 : the terms of the GNU General Public License as published by the Free
9 : Software Foundation; either version 3, or (at your option) any later
10 : version.
11 :
12 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 : for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with GCC; see the file COPYING3. If not see
19 : <http://www.gnu.org/licenses/>. */
20 :
21 :
22 : #include "config.h"
23 : #include "system.h"
24 : #include "coretypes.h"
25 : #include "options.h"
26 : #include "tree.h"
27 : #include "gfortran.h"
28 : #include "basic-block.h"
29 : #include "tree-ssa.h"
30 : #include "function.h"
31 : #include "gimple.h"
32 : #include "gimple-expr.h"
33 : #include "trans.h"
34 : #include "stringpool.h"
35 : #include "fold-const.h"
36 : #include "gimplify.h" /* For create_tmp_var_raw. */
37 : #include "trans-stmt.h"
38 : #include "trans-types.h"
39 : #include "trans-array.h"
40 : #include "trans-const.h"
41 : #include "arith.h"
42 : #include "constructor.h"
43 : #include "gomp-constants.h"
44 : #include "omp-general.h"
45 : #include "omp-low.h"
46 : #include "memmodel.h" /* For MEMMODEL_ enums. */
47 : #include "dependency.h"
48 : #include "gimple-iterator.h" /* For gsi_iterator_update. */
49 : #include "gimplify-me.h" /* For force_gimple_operand. */
50 :
51 : #undef GCC_DIAG_STYLE
52 : #define GCC_DIAG_STYLE __gcc_tdiag__
53 : #include "diagnostic-core.h"
54 : #undef GCC_DIAG_STYLE
55 : #define GCC_DIAG_STYLE __gcc_gfc__
56 : #include "attribs.h"
57 : #include "function.h"
58 :
59 : int ompws_flags;
60 :
61 : /* True if OpenMP should regard this DECL as being a scalar which has Fortran's
62 : allocatable or pointer attribute. */
63 :
64 : bool
65 5964 : gfc_omp_is_allocatable_or_ptr (const_tree decl)
66 : {
67 5964 : return (DECL_P (decl)
68 5964 : && (GFC_DECL_GET_SCALAR_POINTER (decl)
69 4233 : || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)));
70 : }
71 :
72 : /* True if the argument is an optional argument; except that false is also
73 : returned for arguments with the value attribute (nonpointers) and for
74 : assumed-shape variables (decl is a local variable containing arg->data).
75 : Note that for 'procedure(), optional' the value false is used as that's
76 : always a pointer and no additional indirection is used.
77 : Note that pvoid_type_node is for 'type(c_ptr), value' (and c_funloc). */
78 :
79 : static bool
80 46207 : gfc_omp_is_optional_argument (const_tree decl)
81 : {
82 : /* Note: VAR_DECL can occur with BIND(C) and array descriptors. */
83 30406 : return ((TREE_CODE (decl) == PARM_DECL || VAR_P (decl))
84 46207 : && DECL_LANG_SPECIFIC (decl)
85 20785 : && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
86 20601 : && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
87 20366 : && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) != FUNCTION_TYPE
88 66548 : && GFC_DECL_OPTIONAL_ARGUMENT (decl));
89 : }
90 :
91 : /* Check whether this DECL belongs to a Fortran optional argument.
92 : With 'for_present_check' set to false, decls which are optional parameters
93 : themselves are returned as tree - or a NULL_TREE otherwise. Those decls are
94 : always pointers. With 'for_present_check' set to true, the decl for checking
95 : whether an argument is present is returned; for arguments with value
96 : attribute this is the hidden argument and of BOOLEAN_TYPE. If the decl is
97 : unrelated to optional arguments, NULL_TREE is returned. */
98 :
99 : tree
100 22187 : gfc_omp_check_optional_argument (tree decl, bool for_present_check)
101 : {
102 22187 : if (!for_present_check)
103 2175 : return gfc_omp_is_optional_argument (decl) ? decl : NULL_TREE;
104 :
105 20012 : if (!DECL_LANG_SPECIFIC (decl))
106 : return NULL_TREE;
107 :
108 5349 : tree orig_decl = decl;
109 :
110 : /* For assumed-shape arrays, a local decl with arg->data is used. */
111 5349 : if (TREE_CODE (decl) != PARM_DECL
112 5349 : && (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))
113 1945 : || GFC_ARRAY_TYPE_P (TREE_TYPE (decl))))
114 744 : decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
115 :
116 : /* Note: With BIND(C), array descriptors are converted to a VAR_DECL. */
117 5349 : if (decl == NULL_TREE
118 5212 : || (TREE_CODE (decl) != PARM_DECL && TREE_CODE (decl) != VAR_DECL)
119 5212 : || !DECL_LANG_SPECIFIC (decl)
120 10157 : || !GFC_DECL_OPTIONAL_ARGUMENT (decl))
121 : return NULL_TREE;
122 :
123 : /* Scalars with VALUE attribute which are passed by value use a hidden
124 : argument to denote the present status. They are passed as nonpointer type
125 : with one exception: 'type(c_ptr), value' as 'void*'. */
126 : /* Cf. trans-expr.cc's gfc_conv_expr_present. */
127 2834 : if (TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE
128 2834 : || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
129 : {
130 205 : char name[GFC_MAX_SYMBOL_LEN + 2];
131 205 : tree tree_name;
132 :
133 205 : name[0] = '.';
134 205 : strcpy (&name[1], IDENTIFIER_POINTER (DECL_NAME (decl)));
135 205 : tree_name = get_identifier (name);
136 :
137 : /* Walk function argument list to find the hidden arg. */
138 205 : decl = DECL_ARGUMENTS (DECL_CONTEXT (decl));
139 1437 : for ( ; decl != NULL_TREE; decl = TREE_CHAIN (decl))
140 1437 : if (DECL_NAME (decl) == tree_name
141 1437 : && DECL_ARTIFICIAL (decl))
142 : break;
143 :
144 205 : gcc_assert (decl);
145 205 : return decl;
146 : }
147 :
148 2629 : return fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
149 2629 : orig_decl, null_pointer_node);
150 : }
151 :
152 :
153 : /* Returns tree with NULL if it is not an array descriptor and with the tree to
154 : access the 'data' component otherwise. With type_only = true, it returns the
155 : TREE_TYPE without creating a new tree. */
156 :
157 : tree
158 18967 : gfc_omp_array_data (tree decl, bool type_only)
159 : {
160 18967 : tree type = TREE_TYPE (decl);
161 :
162 18967 : if (POINTER_TYPE_P (type))
163 10206 : type = TREE_TYPE (type);
164 :
165 18967 : if (!GFC_DESCRIPTOR_TYPE_P (type))
166 : return NULL_TREE;
167 :
168 4577 : if (type_only)
169 3356 : return GFC_TYPE_ARRAY_DATAPTR_TYPE (type);
170 :
171 1221 : if (POINTER_TYPE_P (TREE_TYPE (decl)))
172 415 : decl = build_fold_indirect_ref (decl);
173 :
174 1221 : decl = gfc_conv_descriptor_data_get (decl);
175 1221 : STRIP_NOPS (decl);
176 1221 : return decl;
177 : }
178 :
179 : /* Return the byte-size of the passed array descriptor. */
180 :
181 : tree
182 19 : gfc_omp_array_size (tree decl, gimple_seq *pre_p)
183 : {
184 19 : stmtblock_t block;
185 19 : if (POINTER_TYPE_P (TREE_TYPE (decl)))
186 19 : decl = build_fold_indirect_ref (decl);
187 19 : tree type = TREE_TYPE (decl);
188 19 : gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
189 19 : bool allocatable = (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
190 2 : || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER
191 19 : || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT);
192 19 : gfc_init_block (&block);
193 57 : tree size = gfc_full_array_size (&block, decl,
194 19 : GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)));
195 19 : size = fold_convert (size_type_node, size);
196 19 : tree elemsz = gfc_get_element_type (TREE_TYPE (decl));
197 19 : if (TREE_CODE (elemsz) == ARRAY_TYPE && TYPE_STRING_FLAG (elemsz))
198 6 : elemsz = gfc_conv_descriptor_elem_len (decl);
199 : else
200 13 : elemsz = TYPE_SIZE_UNIT (elemsz);
201 19 : size = fold_build2 (MULT_EXPR, size_type_node, size, elemsz);
202 19 : if (!allocatable)
203 0 : gimplify_and_add (gfc_finish_block (&block), pre_p);
204 : else
205 : {
206 19 : tree var = create_tmp_var (size_type_node);
207 19 : gfc_add_expr_to_block (&block, build2 (MODIFY_EXPR, sizetype, var, size));
208 19 : tree tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
209 : gfc_conv_descriptor_data_get (decl),
210 : null_pointer_node);
211 19 : tmp = build3_loc (input_location, COND_EXPR, void_type_node, tmp,
212 : gfc_finish_block (&block),
213 : build2 (MODIFY_EXPR, sizetype, var, size_zero_node));
214 19 : gimplify_and_add (tmp, pre_p);
215 19 : size = var;
216 : }
217 19 : return size;
218 : }
219 :
220 :
221 : /* True if OpenMP should privatize what this DECL points to rather
222 : than the DECL itself. */
223 :
224 : bool
225 457719 : gfc_omp_privatize_by_reference (const_tree decl)
226 : {
227 457719 : tree type = TREE_TYPE (decl);
228 :
229 457719 : if (TREE_CODE (type) == REFERENCE_TYPE
230 457719 : && (!DECL_ARTIFICIAL (decl) || TREE_CODE (decl) == PARM_DECL))
231 : return true;
232 :
233 434898 : if (TREE_CODE (type) == POINTER_TYPE
234 434898 : && gfc_omp_is_optional_argument (decl))
235 : return true;
236 :
237 425813 : if (TREE_CODE (type) == POINTER_TYPE)
238 : {
239 32796 : while (TREE_CODE (decl) == COMPONENT_REF)
240 0 : decl = TREE_OPERAND (decl, 1);
241 :
242 : /* Array POINTER/ALLOCATABLE have aggregate types, all user variables
243 : that have POINTER_TYPE type and aren't scalar pointers, scalar
244 : allocatables, Cray pointees or C pointers are supposed to be
245 : privatized by reference. */
246 32796 : if (GFC_DECL_GET_SCALAR_POINTER (decl)
247 31283 : || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
248 28948 : || GFC_DECL_CRAY_POINTEE (decl)
249 28942 : || GFC_DECL_ASSOCIATE_VAR_P (decl)
250 38303 : || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
251 : return false;
252 :
253 20902 : if (!DECL_ARTIFICIAL (decl)
254 20902 : && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
255 : return true;
256 :
257 : /* Some arrays are expanded as DECL_ARTIFICIAL pointers
258 : by the frontend. */
259 13449 : if (DECL_LANG_SPECIFIC (decl)
260 13449 : && GFC_DECL_SAVED_DESCRIPTOR (decl))
261 : return true;
262 : }
263 :
264 : return false;
265 : }
266 :
267 : /* OMP_CLAUSE_DEFAULT_UNSPECIFIED unless OpenMP sharing attribute
268 : of DECL is predetermined. */
269 :
270 : enum omp_clause_default_kind
271 8455 : gfc_omp_predetermined_sharing (tree decl)
272 : {
273 : /* Associate names preserve the association established during ASSOCIATE.
274 : As they are implemented either as pointers to the selector or array
275 : descriptor and shouldn't really change in the ASSOCIATE region,
276 : this decl can be either shared or firstprivate. If it is a pointer,
277 : use firstprivate, as it is cheaper that way, otherwise make it shared. */
278 8455 : if (GFC_DECL_ASSOCIATE_VAR_P (decl))
279 : {
280 45 : if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
281 : return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
282 : else
283 18 : return OMP_CLAUSE_DEFAULT_SHARED;
284 : }
285 :
286 8410 : if (DECL_ARTIFICIAL (decl)
287 1588 : && ! GFC_DECL_RESULT (decl)
288 9974 : && ! (DECL_LANG_SPECIFIC (decl)
289 375 : && GFC_DECL_SAVED_DESCRIPTOR (decl)))
290 : return OMP_CLAUSE_DEFAULT_SHARED;
291 :
292 : /* Cray pointees shouldn't be listed in any clauses and should be
293 : gimplified to dereference of the corresponding Cray pointer.
294 : Make them all private, so that they are emitted in the debug
295 : information. */
296 7172 : if (GFC_DECL_CRAY_POINTEE (decl))
297 : return OMP_CLAUSE_DEFAULT_PRIVATE;
298 :
299 : /* Assumed-size arrays are predetermined shared. */
300 7136 : if (TREE_CODE (decl) == PARM_DECL
301 1963 : && GFC_ARRAY_TYPE_P (TREE_TYPE (decl))
302 716 : && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN
303 7852 : && GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (decl),
304 : GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)) - 1)
305 : == NULL)
306 : return OMP_CLAUSE_DEFAULT_SHARED;
307 :
308 : /* Dummy procedures aren't considered variables by OpenMP, thus are
309 : disallowed in OpenMP clauses. They are represented as PARM_DECLs
310 : in the middle-end, so return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE here
311 : to avoid complaining about their uses with default(none). */
312 7068 : if (TREE_CODE (decl) == PARM_DECL
313 1895 : && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
314 7853 : && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == FUNCTION_TYPE)
315 : return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
316 :
317 : /* COMMON and EQUIVALENCE decls are shared. They
318 : are only referenced through DECL_VALUE_EXPR of the variables
319 : contained in them. If those are privatized, they will not be
320 : gimplified to the COMMON or EQUIVALENCE decls. */
321 7052 : if (GFC_DECL_COMMON_OR_EQUIV (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
322 : return OMP_CLAUSE_DEFAULT_SHARED;
323 :
324 7023 : if (GFC_DECL_RESULT (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
325 : return OMP_CLAUSE_DEFAULT_SHARED;
326 :
327 : /* These are either array or derived parameters, or vtables.
328 : In the former cases, the OpenMP standard doesn't consider them to be
329 : variables at all (they can't be redefined), but they can nevertheless appear
330 : in parallel/task regions and for default(none) purposes treat them as shared.
331 : For vtables likely the same handling is desirable. */
332 5120 : if (VAR_P (decl) && TREE_READONLY (decl)
333 7002 : && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
334 3 : return OMP_CLAUSE_DEFAULT_SHARED;
335 :
336 : return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
337 : }
338 :
339 :
340 : /* OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED unless OpenMP mapping attribute
341 : of DECL is predetermined. */
342 :
343 : enum omp_clause_defaultmap_kind
344 3980 : gfc_omp_predetermined_mapping (tree decl)
345 : {
346 3980 : if (DECL_ARTIFICIAL (decl)
347 879 : && ! GFC_DECL_RESULT (decl)
348 4853 : && ! (DECL_LANG_SPECIFIC (decl)
349 72 : && GFC_DECL_SAVED_DESCRIPTOR (decl)))
350 : return OMP_CLAUSE_DEFAULTMAP_TO;
351 :
352 : /* Dummy procedures aren't considered variables by OpenMP, thus are
353 : disallowed in OpenMP clauses. They are represented as PARM_DECLs
354 : in the middle-end, so return OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE here
355 : to avoid complaining about their uses with defaultmap(none). */
356 3150 : if (TREE_CODE (decl) == PARM_DECL
357 1814 : && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
358 3529 : && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == FUNCTION_TYPE)
359 : return OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
360 :
361 : /* These are either array or derived parameters, or vtables. */
362 1336 : if (VAR_P (decl) && TREE_READONLY (decl)
363 3143 : && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
364 0 : return OMP_CLAUSE_DEFAULTMAP_TO;
365 :
366 : return OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
367 : }
368 :
369 :
370 : /* Return decl that should be used when reporting DEFAULT(NONE)
371 : diagnostics. */
372 :
373 : tree
374 130 : gfc_omp_report_decl (tree decl)
375 : {
376 130 : if (DECL_ARTIFICIAL (decl)
377 3 : && DECL_LANG_SPECIFIC (decl)
378 133 : && GFC_DECL_SAVED_DESCRIPTOR (decl))
379 3 : return GFC_DECL_SAVED_DESCRIPTOR (decl);
380 :
381 : return decl;
382 : }
383 :
384 : /* Return true if TYPE has any allocatable components;
385 : if ptr_ok, the decl itself is permitted to have the POINTER attribute.
386 : if shallow_alloc_only, returns only true if any of the fields is an
387 : allocatable; called with true by gfc_omp_replace_alloc_by_to_mapping. */
388 :
389 : static bool
390 122013 : gfc_has_alloc_comps (tree type, tree decl, bool ptr_ok,
391 : bool shallow_alloc_only=false)
392 : {
393 122013 : tree field, ftype;
394 :
395 122013 : if (POINTER_TYPE_P (type))
396 : {
397 3455 : if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
398 3455 : || (ptr_ok && GFC_DECL_GET_SCALAR_POINTER (decl)))
399 2380 : type = TREE_TYPE (type);
400 1075 : else if (GFC_DECL_GET_SCALAR_POINTER (decl))
401 : return false;
402 : }
403 :
404 121833 : if (!ptr_ok
405 98187 : && GFC_DESCRIPTOR_TYPE_P (type)
406 124980 : && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER
407 2887 : || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
408 : return false;
409 :
410 121570 : if (GFC_DESCRIPTOR_TYPE_P (type) || GFC_ARRAY_TYPE_P (type))
411 12464 : type = gfc_get_element_type (type);
412 :
413 121570 : if (TREE_CODE (type) != RECORD_TYPE)
414 : return false;
415 :
416 9763 : for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
417 : {
418 8773 : ftype = TREE_TYPE (field);
419 8773 : if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
420 : return true;
421 8205 : if (GFC_DESCRIPTOR_TYPE_P (ftype)
422 8205 : && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
423 : return true;
424 5735 : if (!shallow_alloc_only
425 5735 : && gfc_has_alloc_comps (ftype, field, false))
426 : return true;
427 : }
428 : return false;
429 : }
430 :
431 : /* gfc_omp_replace_alloc_by_to_mapping is used with gfc_omp_deep_mapping... to
432 : handle the following:
433 :
434 : For map(alloc: dt), the array descriptors of allocatable components should
435 : be mapped as 'to'; this could be done by (A) adding 'map(to: dt%alloc_comp)'
436 : for each component (and avoiding to increment the reference count).
437 : Or (B) by just mapping all of 'dt' as 'to'.
438 :
439 : If 'dt' contains several allocatable components and not much other data,
440 : (A) is more efficient. If 'dt' contains a large const-size array, (A) will
441 : copy it to the device instead of only 'alloc'ating it.
442 :
443 : IMPLEMENTATION CHOICE: We do (A). It avoids the ref-count issue and it is
444 : expected that, for real-world code, derived types with allocatable
445 : components only have few other components and either no const-size arrays.
446 : This copying is done irrespectively whether the allocatables are allocated.
447 :
448 : If users wanted to save memory, they have to use 'map(alloc:dt%comp)' as
449 : also with 'map(alloc:dt)' all components get copied.
450 :
451 : For the copy to the device, only allocatable arrays are relevant as their
452 : the bounds are required; the pointer is set separately (GOMP_MAP_ATTACH)
453 : and the only setting required for scalars. However, when later copying out
454 : of the device, an unallocated allocatable must remain unallocated/NULL on
455 : the host; to achieve this we also must have it set to NULL on the device
456 : to avoid issues with uninitialized memory being copied back for the pointer
457 : address. If we could set the pointer to NULL, gfc_has_alloc_comps's
458 : shallow_alloc_only could be restricted to return true only for arrays.
459 :
460 : We only need to return true if there are allocatable-array components. */
461 :
462 : static bool
463 62 : gfc_omp_replace_alloc_by_to_mapping (tree type, tree decl, bool ptr_ok)
464 : {
465 18 : return gfc_has_alloc_comps (type, decl, ptr_ok, true);
466 : }
467 :
468 :
469 : /* Return true if TYPE is polymorphic but not with pointer attribute. */
470 :
471 : static bool
472 66220 : gfc_is_polymorphic_nonptr (tree type)
473 : {
474 66220 : if (POINTER_TYPE_P (type))
475 3636 : type = TREE_TYPE (type);
476 66220 : return GFC_CLASS_TYPE_P (type);
477 : }
478 :
479 : /* Return true if TYPE is unlimited polymorphic but not with pointer attribute;
480 : unlimited means also intrinsic types are handled and _len is used. */
481 :
482 : static bool
483 77 : gfc_is_unlimited_polymorphic_nonptr (tree type)
484 : {
485 77 : if (POINTER_TYPE_P (type))
486 0 : type = TREE_TYPE (type);
487 77 : if (!GFC_CLASS_TYPE_P (type))
488 : return false;
489 :
490 77 : tree field = TYPE_FIELDS (type); /* _data */
491 77 : gcc_assert (field);
492 77 : field = DECL_CHAIN (field); /* _vptr */
493 77 : gcc_assert (field);
494 77 : field = DECL_CHAIN (field);
495 77 : if (!field)
496 : return false;
497 26 : gcc_assert (strcmp ("_len", IDENTIFIER_POINTER (DECL_NAME (field))) == 0);
498 : return true;
499 : }
500 :
501 : /* Return true if the DECL is for an allocatable array or scalar. */
502 :
503 : bool
504 3980 : gfc_omp_allocatable_p (tree decl)
505 : {
506 3980 : if (!DECL_P (decl))
507 : return false;
508 :
509 3980 : if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
510 : return true;
511 :
512 3758 : tree type = TREE_TYPE (decl);
513 3758 : if (gfc_omp_privatize_by_reference (decl))
514 1801 : type = TREE_TYPE (type);
515 :
516 3758 : if (GFC_DESCRIPTOR_TYPE_P (type)
517 3758 : && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
518 : return true;
519 :
520 : return false;
521 : }
522 :
523 :
524 : /* Return true if DECL in private clause needs
525 : OMP_CLAUSE_PRIVATE_OUTER_REF on the private clause. */
526 : bool
527 14470 : gfc_omp_private_outer_ref (tree decl)
528 : {
529 14470 : tree type = TREE_TYPE (decl);
530 :
531 14470 : if (gfc_omp_privatize_by_reference (decl))
532 617 : type = TREE_TYPE (type);
533 :
534 14470 : if (GFC_DESCRIPTOR_TYPE_P (type)
535 14470 : && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
536 : return true;
537 :
538 14343 : if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
539 : return true;
540 :
541 14257 : if (gfc_has_alloc_comps (type, decl, false))
542 : return true;
543 :
544 : return false;
545 : }
546 :
547 : /* Callback for gfc_omp_unshare_expr. */
548 :
549 : static tree
550 92286 : gfc_omp_unshare_expr_r (tree *tp, int *walk_subtrees, void *)
551 : {
552 92286 : tree t = *tp;
553 92286 : enum tree_code code = TREE_CODE (t);
554 :
555 : /* Stop at types, decls, constants like copy_tree_r. */
556 92286 : if (TREE_CODE_CLASS (code) == tcc_type
557 : || TREE_CODE_CLASS (code) == tcc_declaration
558 92286 : || TREE_CODE_CLASS (code) == tcc_constant
559 61181 : || code == BLOCK)
560 31105 : *walk_subtrees = 0;
561 61181 : else if (handled_component_p (t)
562 46252 : || TREE_CODE (t) == MEM_REF)
563 : {
564 14989 : *tp = unshare_expr (t);
565 14989 : *walk_subtrees = 0;
566 : }
567 :
568 92286 : return NULL_TREE;
569 : }
570 :
571 : /* Unshare in expr anything that the FE which normally doesn't
572 : care much about tree sharing (because during gimplification
573 : everything is unshared) could cause problems with tree sharing
574 : at omp-low.cc time. */
575 :
576 : static tree
577 5067 : gfc_omp_unshare_expr (tree expr)
578 : {
579 5067 : walk_tree (&expr, gfc_omp_unshare_expr_r, NULL, NULL);
580 5067 : return expr;
581 : }
582 :
583 : enum walk_alloc_comps
584 : {
585 : WALK_ALLOC_COMPS_DTOR,
586 : WALK_ALLOC_COMPS_DEFAULT_CTOR,
587 : WALK_ALLOC_COMPS_COPY_CTOR
588 : };
589 :
590 : /* Handle allocatable components in OpenMP clauses. */
591 :
592 : static tree
593 2801 : gfc_walk_alloc_comps (tree decl, tree dest, tree var,
594 : enum walk_alloc_comps kind)
595 : {
596 2801 : stmtblock_t block, tmpblock;
597 2801 : tree type = TREE_TYPE (decl), then_b, tem, field;
598 2801 : gfc_init_block (&block);
599 :
600 2801 : if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
601 : {
602 1092 : if (GFC_DESCRIPTOR_TYPE_P (type))
603 : {
604 548 : gfc_init_block (&tmpblock);
605 1644 : tem = gfc_full_array_size (&tmpblock, decl,
606 548 : GFC_TYPE_ARRAY_RANK (type));
607 548 : then_b = gfc_finish_block (&tmpblock);
608 548 : gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (then_b));
609 548 : tem = gfc_omp_unshare_expr (tem);
610 548 : tem = fold_build2_loc (input_location, MINUS_EXPR,
611 : gfc_array_index_type, tem,
612 : gfc_index_one_node);
613 : }
614 : else
615 : {
616 544 : bool compute_nelts = false;
617 544 : if (!TYPE_DOMAIN (type)
618 544 : || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE
619 544 : || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node
620 1088 : || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node)
621 : compute_nelts = true;
622 544 : else if (VAR_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
623 : {
624 80 : tree a = DECL_ATTRIBUTES (TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
625 80 : if (lookup_attribute ("omp dummy var", a))
626 : compute_nelts = true;
627 : }
628 : if (compute_nelts)
629 : {
630 80 : tem = fold_build2 (EXACT_DIV_EXPR, sizetype,
631 : TYPE_SIZE_UNIT (type),
632 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
633 80 : tem = size_binop (MINUS_EXPR, tem, size_one_node);
634 : }
635 : else
636 464 : tem = array_type_nelts_minus_one (type);
637 544 : tem = fold_convert (gfc_array_index_type, tem);
638 : }
639 :
640 1092 : tree nelems = gfc_evaluate_now (tem, &block);
641 1092 : tree index = gfc_create_var (gfc_array_index_type, "S");
642 :
643 1092 : gfc_init_block (&tmpblock);
644 1092 : tem = gfc_conv_array_data (decl);
645 1092 : tree declvar = build_fold_indirect_ref_loc (input_location, tem);
646 1092 : tree declvref = gfc_build_array_ref (declvar, index, NULL);
647 1092 : tree destvar, destvref = NULL_TREE;
648 1092 : if (dest)
649 : {
650 546 : tem = gfc_conv_array_data (dest);
651 546 : destvar = build_fold_indirect_ref_loc (input_location, tem);
652 546 : destvref = gfc_build_array_ref (destvar, index, NULL);
653 : }
654 1092 : gfc_add_expr_to_block (&tmpblock,
655 : gfc_walk_alloc_comps (declvref, destvref,
656 : var, kind));
657 :
658 1092 : gfc_loopinfo loop;
659 1092 : gfc_init_loopinfo (&loop);
660 1092 : loop.dimen = 1;
661 1092 : loop.from[0] = gfc_index_zero_node;
662 1092 : loop.loopvar[0] = index;
663 1092 : loop.to[0] = nelems;
664 1092 : gfc_trans_scalarizing_loops (&loop, &tmpblock);
665 1092 : gfc_add_block_to_block (&block, &loop.pre);
666 1092 : return gfc_finish_block (&block);
667 : }
668 1709 : else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (var))
669 : {
670 536 : decl = build_fold_indirect_ref_loc (input_location, decl);
671 536 : if (dest)
672 268 : dest = build_fold_indirect_ref_loc (input_location, dest);
673 536 : type = TREE_TYPE (decl);
674 : }
675 :
676 1709 : gcc_assert (TREE_CODE (type) == RECORD_TYPE);
677 11488 : for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
678 : {
679 9779 : tree ftype = TREE_TYPE (field);
680 9779 : tree declf, destf = NULL_TREE;
681 9779 : bool has_alloc_comps = gfc_has_alloc_comps (ftype, field, false);
682 9779 : if ((!GFC_DESCRIPTOR_TYPE_P (ftype)
683 1708 : || GFC_TYPE_ARRAY_AKIND (ftype) != GFC_ARRAY_ALLOCATABLE)
684 8071 : && !GFC_DECL_GET_SCALAR_ALLOCATABLE (field)
685 16153 : && !has_alloc_comps)
686 5950 : continue;
687 3829 : declf = fold_build3_loc (input_location, COMPONENT_REF, ftype,
688 : decl, field, NULL_TREE);
689 3829 : if (dest)
690 1915 : destf = fold_build3_loc (input_location, COMPONENT_REF, ftype,
691 : dest, field, NULL_TREE);
692 :
693 3829 : tem = NULL_TREE;
694 3829 : switch (kind)
695 : {
696 : case WALK_ALLOC_COMPS_DTOR:
697 : break;
698 961 : case WALK_ALLOC_COMPS_DEFAULT_CTOR:
699 961 : if (GFC_DESCRIPTOR_TYPE_P (ftype)
700 961 : && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
701 : {
702 430 : gfc_add_modify (&block, unshare_expr (destf),
703 : unshare_expr (declf));
704 430 : tem = gfc_duplicate_allocatable_nocopy
705 430 : (destf, declf, ftype,
706 430 : GFC_TYPE_ARRAY_RANK (ftype));
707 : }
708 531 : else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
709 425 : tem = gfc_duplicate_allocatable_nocopy (destf, declf, ftype, 0);
710 : break;
711 954 : case WALK_ALLOC_COMPS_COPY_CTOR:
712 954 : if (GFC_DESCRIPTOR_TYPE_P (ftype)
713 954 : && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
714 848 : tem = gfc_duplicate_allocatable (destf, declf, ftype,
715 424 : GFC_TYPE_ARRAY_RANK (ftype),
716 : NULL_TREE);
717 530 : else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
718 424 : tem = gfc_duplicate_allocatable (destf, declf, ftype, 0,
719 : NULL_TREE);
720 : break;
721 : }
722 1703 : if (tem)
723 1703 : gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
724 3829 : if (has_alloc_comps)
725 : {
726 1272 : gfc_init_block (&tmpblock);
727 1272 : gfc_add_expr_to_block (&tmpblock,
728 : gfc_walk_alloc_comps (declf, destf,
729 : field, kind));
730 1272 : then_b = gfc_finish_block (&tmpblock);
731 1272 : if (GFC_DESCRIPTOR_TYPE_P (ftype)
732 1272 : && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
733 424 : tem = gfc_conv_descriptor_data_get (unshare_expr (declf));
734 848 : else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
735 424 : tem = unshare_expr (declf);
736 : else
737 : tem = NULL_TREE;
738 848 : if (tem)
739 : {
740 848 : tem = fold_convert (pvoid_type_node, tem);
741 848 : tem = fold_build2_loc (input_location, NE_EXPR,
742 : logical_type_node, tem,
743 : null_pointer_node);
744 848 : then_b = build3_loc (input_location, COND_EXPR, void_type_node,
745 : tem, then_b,
746 : build_empty_stmt (input_location));
747 : }
748 1272 : gfc_add_expr_to_block (&block, then_b);
749 : }
750 3829 : if (kind == WALK_ALLOC_COMPS_DTOR)
751 : {
752 1914 : if (GFC_DESCRIPTOR_TYPE_P (ftype)
753 1914 : && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
754 : {
755 854 : tem = gfc_conv_descriptor_data_get (unshare_expr (declf));
756 854 : tem = gfc_deallocate_with_status (tem, NULL_TREE, NULL_TREE,
757 : NULL_TREE, NULL_TREE, true,
758 : NULL,
759 : GFC_CAF_COARRAY_NOCOARRAY);
760 854 : gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
761 : }
762 1060 : else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
763 : {
764 848 : tem = gfc_call_free (unshare_expr (declf));
765 848 : gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
766 : }
767 : }
768 : }
769 :
770 1709 : return gfc_finish_block (&block);
771 : }
772 :
773 : /* Return code to initialize DECL with its default constructor, or
774 : NULL if there's nothing to do. */
775 :
776 : tree
777 20380 : gfc_omp_clause_default_ctor (tree clause, tree decl, tree outer)
778 : {
779 20380 : tree type = TREE_TYPE (decl), size, ptr, cond, then_b, else_b;
780 20380 : stmtblock_t block, cond_block;
781 :
782 20380 : switch (OMP_CLAUSE_CODE (clause))
783 : {
784 : case OMP_CLAUSE__LOOPTEMP_:
785 : case OMP_CLAUSE__REDUCTEMP_:
786 : case OMP_CLAUSE__CONDTEMP_:
787 : case OMP_CLAUSE__SCANTEMP_:
788 : return NULL;
789 20353 : case OMP_CLAUSE_PRIVATE:
790 20353 : case OMP_CLAUSE_LASTPRIVATE:
791 20353 : case OMP_CLAUSE_LINEAR:
792 20353 : case OMP_CLAUSE_REDUCTION:
793 20353 : case OMP_CLAUSE_IN_REDUCTION:
794 20353 : case OMP_CLAUSE_TASK_REDUCTION:
795 20353 : break;
796 0 : default:
797 0 : gcc_unreachable ();
798 : }
799 :
800 20353 : if ((! GFC_DESCRIPTOR_TYPE_P (type)
801 263 : || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
802 20372 : && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
803 85 : || !POINTER_TYPE_P (type)))
804 : {
805 20024 : if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause), false))
806 : {
807 51 : gcc_assert (outer);
808 51 : gfc_start_block (&block);
809 102 : tree tem = gfc_walk_alloc_comps (outer, decl,
810 51 : OMP_CLAUSE_DECL (clause),
811 : WALK_ALLOC_COMPS_DEFAULT_CTOR);
812 51 : gfc_add_expr_to_block (&block, tem);
813 51 : return gfc_finish_block (&block);
814 : }
815 : return NULL_TREE;
816 : }
817 :
818 329 : gcc_assert (outer != NULL_TREE);
819 :
820 : /* Allocatable arrays and scalars in PRIVATE clauses need to be set to
821 : "not currently allocated" allocation status if outer
822 : array is "not currently allocated", otherwise should be allocated. */
823 329 : gfc_start_block (&block);
824 :
825 329 : gfc_init_block (&cond_block);
826 :
827 329 : if (GFC_DESCRIPTOR_TYPE_P (type))
828 : {
829 244 : gfc_add_modify (&cond_block, decl, outer);
830 244 : tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
831 244 : size = gfc_conv_descriptor_ubound_get (decl, rank);
832 244 : size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
833 : size,
834 : gfc_conv_descriptor_lbound_get (decl, rank));
835 244 : size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
836 : size, gfc_index_one_node);
837 244 : if (GFC_TYPE_ARRAY_RANK (type) > 1)
838 130 : size = fold_build2_loc (input_location, MULT_EXPR,
839 : gfc_array_index_type, size,
840 : gfc_conv_descriptor_stride_get (decl, rank));
841 244 : tree esize = fold_convert (gfc_array_index_type,
842 : TYPE_SIZE_UNIT (gfc_get_element_type (type)));
843 244 : size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
844 : size, esize);
845 244 : size = unshare_expr (size);
846 244 : size = gfc_evaluate_now (fold_convert (size_type_node, size),
847 : &cond_block);
848 : }
849 : else
850 85 : size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
851 329 : ptr = gfc_create_var (pvoid_type_node, NULL);
852 329 : gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
853 329 : if (GFC_DESCRIPTOR_TYPE_P (type))
854 244 : gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl), ptr);
855 : else
856 85 : gfc_add_modify (&cond_block, unshare_expr (decl),
857 85 : fold_convert (TREE_TYPE (decl), ptr));
858 329 : if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause), false))
859 : {
860 124 : tree tem = gfc_walk_alloc_comps (outer, decl,
861 62 : OMP_CLAUSE_DECL (clause),
862 : WALK_ALLOC_COMPS_DEFAULT_CTOR);
863 62 : gfc_add_expr_to_block (&cond_block, tem);
864 : }
865 329 : then_b = gfc_finish_block (&cond_block);
866 :
867 : /* Reduction clause requires allocated ALLOCATABLE. */
868 329 : if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_REDUCTION
869 185 : && OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_IN_REDUCTION
870 514 : && OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_TASK_REDUCTION)
871 : {
872 185 : gfc_init_block (&cond_block);
873 185 : if (GFC_DESCRIPTOR_TYPE_P (type))
874 124 : gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl),
875 : null_pointer_node);
876 : else
877 61 : gfc_add_modify (&cond_block, unshare_expr (decl),
878 61 : build_zero_cst (TREE_TYPE (decl)));
879 185 : else_b = gfc_finish_block (&cond_block);
880 :
881 185 : tree tem = fold_convert (pvoid_type_node,
882 : GFC_DESCRIPTOR_TYPE_P (type)
883 : ? gfc_conv_descriptor_data_get (outer) : outer);
884 185 : tem = unshare_expr (tem);
885 185 : cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
886 : tem, null_pointer_node);
887 185 : gfc_add_expr_to_block (&block,
888 : build3_loc (input_location, COND_EXPR,
889 : void_type_node, cond, then_b,
890 : else_b));
891 : /* Avoid -W*uninitialized warnings. */
892 185 : if (DECL_P (decl))
893 146 : suppress_warning (decl, OPT_Wuninitialized);
894 : }
895 : else
896 144 : gfc_add_expr_to_block (&block, then_b);
897 :
898 329 : return gfc_finish_block (&block);
899 : }
900 :
901 : /* Build and return code for a copy constructor from SRC to DEST. */
902 :
903 : tree
904 9230 : gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
905 : {
906 9230 : tree type = TREE_TYPE (dest), ptr, size, call;
907 9230 : tree decl_type = TREE_TYPE (OMP_CLAUSE_DECL (clause));
908 9230 : tree cond, then_b, else_b;
909 9230 : stmtblock_t block, cond_block;
910 :
911 9230 : gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE
912 : || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
913 :
914 : /* Privatize pointer, only; cf. gfc_omp_predetermined_sharing. */
915 9230 : if (DECL_P (OMP_CLAUSE_DECL (clause))
916 9230 : && GFC_DECL_ASSOCIATE_VAR_P (OMP_CLAUSE_DECL (clause)))
917 27 : return build2 (MODIFY_EXPR, TREE_TYPE (dest), dest, src);
918 :
919 9203 : if (DECL_ARTIFICIAL (OMP_CLAUSE_DECL (clause))
920 6152 : && DECL_LANG_SPECIFIC (OMP_CLAUSE_DECL (clause))
921 9384 : && GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause)))
922 167 : decl_type
923 167 : = TREE_TYPE (GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause)));
924 :
925 9203 : if (gfc_is_polymorphic_nonptr (decl_type))
926 : {
927 40 : if (POINTER_TYPE_P (decl_type))
928 27 : decl_type = TREE_TYPE (decl_type);
929 40 : decl_type = TREE_TYPE (TYPE_FIELDS (decl_type));
930 40 : if (GFC_DESCRIPTOR_TYPE_P (decl_type) || GFC_ARRAY_TYPE_P (decl_type))
931 4 : fatal_error (input_location,
932 : "Sorry, polymorphic arrays not yet supported for "
933 : "firstprivate");
934 36 : tree src_len;
935 36 : tree nelems = build_int_cst (size_type_node, 1); /* Scalar. */
936 36 : tree src_data = gfc_class_data_get (unshare_expr (src));
937 36 : tree dest_data = gfc_class_data_get (unshare_expr (dest));
938 36 : bool unlimited = gfc_is_unlimited_polymorphic_nonptr (type);
939 :
940 36 : gfc_start_block (&block);
941 36 : gfc_add_modify (&block, gfc_class_vptr_get (dest),
942 : gfc_class_vptr_get (src));
943 36 : gfc_init_block (&cond_block);
944 :
945 36 : if (unlimited)
946 : {
947 24 : src_len = gfc_class_len_get (src);
948 24 : gfc_add_modify (&cond_block, gfc_class_len_get (unshare_expr (dest)), src_len);
949 : }
950 :
951 : /* Use: size = class._vtab._size * (class._len > 0 ? class._len : 1). */
952 36 : size = fold_convert (size_type_node, gfc_class_vtab_size_get (src));
953 36 : if (unlimited)
954 : {
955 24 : cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
956 : unshare_expr (src_len),
957 24 : build_zero_cst (TREE_TYPE (src_len)));
958 24 : cond = build3_loc (input_location, COND_EXPR, size_type_node, cond,
959 : fold_convert (size_type_node,
960 : unshare_expr (src_len)),
961 : build_int_cst (size_type_node, 1));
962 24 : size = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
963 : size, cond);
964 : }
965 :
966 : /* Malloc memory + call class->_vpt->_copy. */
967 36 : call = builtin_decl_explicit (BUILT_IN_MALLOC);
968 36 : call = build_call_expr_loc (input_location, call, 1, size);
969 36 : gfc_add_modify (&cond_block, dest_data,
970 36 : fold_convert (TREE_TYPE (dest_data), call));
971 36 : gfc_add_expr_to_block (&cond_block,
972 : gfc_copy_class_to_class (src, dest, nelems,
973 : unlimited));
974 :
975 36 : gcc_assert (TREE_CODE (dest_data) == COMPONENT_REF);
976 36 : if (!GFC_DECL_GET_SCALAR_ALLOCATABLE (TREE_OPERAND (dest_data, 1)))
977 : {
978 12 : gfc_add_block_to_block (&block, &cond_block);
979 : }
980 : else
981 : {
982 : /* Create: if (class._data != 0) <cond_block> else class._data = NULL; */
983 24 : cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
984 : src_data, null_pointer_node);
985 24 : gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR,
986 : void_type_node, cond,
987 : gfc_finish_block (&cond_block),
988 : fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
989 : unshare_expr (dest_data), null_pointer_node)));
990 : }
991 36 : return gfc_finish_block (&block);
992 : }
993 :
994 9163 : if ((! GFC_DESCRIPTOR_TYPE_P (type)
995 139 : || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
996 9187 : && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
997 77 : || !POINTER_TYPE_P (type)))
998 : {
999 8973 : if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause), false))
1000 : {
1001 20 : gfc_start_block (&block);
1002 20 : gfc_add_modify (&block, dest, src);
1003 20 : tree tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause),
1004 : WALK_ALLOC_COMPS_COPY_CTOR);
1005 20 : gfc_add_expr_to_block (&block, tem);
1006 20 : return gfc_finish_block (&block);
1007 : }
1008 : else
1009 8953 : return build2_v (MODIFY_EXPR, dest, src);
1010 : }
1011 :
1012 : /* Allocatable arrays in FIRSTPRIVATE clauses need to be allocated
1013 : and copied from SRC. */
1014 190 : gfc_start_block (&block);
1015 :
1016 190 : gfc_init_block (&cond_block);
1017 :
1018 190 : gfc_add_modify (&cond_block, dest, fold_convert (TREE_TYPE (dest), src));
1019 190 : if (GFC_DESCRIPTOR_TYPE_P (type))
1020 : {
1021 115 : tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
1022 115 : size = gfc_conv_descriptor_ubound_get (dest, rank);
1023 115 : size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
1024 : size,
1025 : gfc_conv_descriptor_lbound_get (dest, rank));
1026 115 : size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1027 : size, gfc_index_one_node);
1028 115 : if (GFC_TYPE_ARRAY_RANK (type) > 1)
1029 42 : size = fold_build2_loc (input_location, MULT_EXPR,
1030 : gfc_array_index_type, size,
1031 : gfc_conv_descriptor_stride_get (dest, rank));
1032 115 : tree esize = fold_convert (gfc_array_index_type,
1033 : TYPE_SIZE_UNIT (gfc_get_element_type (type)));
1034 115 : size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1035 : size, esize);
1036 115 : size = unshare_expr (size);
1037 115 : size = gfc_evaluate_now (fold_convert (size_type_node, size),
1038 : &cond_block);
1039 : }
1040 : else
1041 75 : size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
1042 190 : ptr = gfc_create_var (pvoid_type_node, NULL);
1043 190 : gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
1044 190 : if (GFC_DESCRIPTOR_TYPE_P (type))
1045 115 : gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest), ptr);
1046 : else
1047 75 : gfc_add_modify (&cond_block, unshare_expr (dest),
1048 75 : fold_convert (TREE_TYPE (dest), ptr));
1049 :
1050 190 : tree srcptr = GFC_DESCRIPTOR_TYPE_P (type)
1051 190 : ? gfc_conv_descriptor_data_get (src) : src;
1052 190 : srcptr = unshare_expr (srcptr);
1053 190 : srcptr = fold_convert (pvoid_type_node, srcptr);
1054 190 : call = build_call_expr_loc (input_location,
1055 : builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr,
1056 : srcptr, size);
1057 190 : gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
1058 190 : if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause), false))
1059 : {
1060 48 : tree tem = gfc_walk_alloc_comps (src, dest,
1061 24 : OMP_CLAUSE_DECL (clause),
1062 : WALK_ALLOC_COMPS_COPY_CTOR);
1063 24 : gfc_add_expr_to_block (&cond_block, tem);
1064 : }
1065 190 : then_b = gfc_finish_block (&cond_block);
1066 :
1067 190 : gfc_init_block (&cond_block);
1068 190 : if (GFC_DESCRIPTOR_TYPE_P (type))
1069 115 : gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest),
1070 : null_pointer_node);
1071 : else
1072 75 : gfc_add_modify (&cond_block, unshare_expr (dest),
1073 75 : build_zero_cst (TREE_TYPE (dest)));
1074 190 : else_b = gfc_finish_block (&cond_block);
1075 :
1076 190 : cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1077 : unshare_expr (srcptr), null_pointer_node);
1078 190 : gfc_add_expr_to_block (&block,
1079 : build3_loc (input_location, COND_EXPR,
1080 : void_type_node, cond, then_b, else_b));
1081 : /* Avoid -W*uninitialized warnings. */
1082 190 : if (DECL_P (dest))
1083 121 : suppress_warning (dest, OPT_Wuninitialized);
1084 :
1085 190 : return gfc_finish_block (&block);
1086 : }
1087 :
1088 : /* Similarly, except use an intrinsic or pointer assignment operator
1089 : instead. */
1090 :
1091 : tree
1092 6345 : gfc_omp_clause_assign_op (tree clause, tree dest, tree src)
1093 : {
1094 6345 : tree type = TREE_TYPE (dest), ptr, size, call, nonalloc;
1095 6345 : tree cond, then_b, else_b;
1096 6345 : stmtblock_t block, cond_block, cond_block2, inner_block;
1097 :
1098 6345 : if ((! GFC_DESCRIPTOR_TYPE_P (type)
1099 234 : || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
1100 12487 : && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
1101 136 : || !POINTER_TYPE_P (type)))
1102 : {
1103 6006 : if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause), false))
1104 : {
1105 30 : gfc_start_block (&block);
1106 : /* First dealloc any allocatable components in DEST. */
1107 60 : tree tem = gfc_walk_alloc_comps (dest, NULL_TREE,
1108 30 : OMP_CLAUSE_DECL (clause),
1109 : WALK_ALLOC_COMPS_DTOR);
1110 30 : gfc_add_expr_to_block (&block, tem);
1111 : /* Then copy over toplevel data. */
1112 30 : gfc_add_modify (&block, dest, src);
1113 : /* Finally allocate any allocatable components and copy. */
1114 30 : tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause),
1115 : WALK_ALLOC_COMPS_COPY_CTOR);
1116 30 : gfc_add_expr_to_block (&block, tem);
1117 30 : return gfc_finish_block (&block);
1118 : }
1119 : else
1120 5976 : return build2_v (MODIFY_EXPR, dest, src);
1121 : }
1122 :
1123 339 : gfc_start_block (&block);
1124 :
1125 339 : if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause), false))
1126 : {
1127 32 : then_b = gfc_walk_alloc_comps (dest, NULL_TREE, OMP_CLAUSE_DECL (clause),
1128 : WALK_ALLOC_COMPS_DTOR);
1129 32 : tree tem = fold_convert (pvoid_type_node,
1130 : GFC_DESCRIPTOR_TYPE_P (type)
1131 : ? gfc_conv_descriptor_data_get (dest) : dest);
1132 32 : tem = unshare_expr (tem);
1133 32 : cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1134 : tem, null_pointer_node);
1135 32 : tem = build3_loc (input_location, COND_EXPR, void_type_node, cond,
1136 : then_b, build_empty_stmt (input_location));
1137 32 : gfc_add_expr_to_block (&block, tem);
1138 : }
1139 :
1140 339 : gfc_init_block (&cond_block);
1141 :
1142 339 : if (GFC_DESCRIPTOR_TYPE_P (type))
1143 : {
1144 203 : tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
1145 203 : size = gfc_conv_descriptor_ubound_get (src, rank);
1146 203 : size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
1147 : size,
1148 : gfc_conv_descriptor_lbound_get (src, rank));
1149 203 : size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1150 : size, gfc_index_one_node);
1151 203 : if (GFC_TYPE_ARRAY_RANK (type) > 1)
1152 88 : size = fold_build2_loc (input_location, MULT_EXPR,
1153 : gfc_array_index_type, size,
1154 : gfc_conv_descriptor_stride_get (src, rank));
1155 203 : tree esize = fold_convert (gfc_array_index_type,
1156 : TYPE_SIZE_UNIT (gfc_get_element_type (type)));
1157 203 : size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1158 : size, esize);
1159 203 : size = unshare_expr (size);
1160 203 : size = gfc_evaluate_now (fold_convert (size_type_node, size),
1161 : &cond_block);
1162 : }
1163 : else
1164 136 : size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
1165 339 : ptr = gfc_create_var (pvoid_type_node, NULL);
1166 :
1167 339 : tree destptr = GFC_DESCRIPTOR_TYPE_P (type)
1168 339 : ? gfc_conv_descriptor_data_get (dest) : dest;
1169 339 : destptr = unshare_expr (destptr);
1170 339 : destptr = fold_convert (pvoid_type_node, destptr);
1171 339 : gfc_add_modify (&cond_block, ptr, destptr);
1172 :
1173 339 : nonalloc = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
1174 : destptr, null_pointer_node);
1175 339 : cond = nonalloc;
1176 339 : if (GFC_DESCRIPTOR_TYPE_P (type))
1177 : {
1178 : int i;
1179 494 : for (i = 0; i < GFC_TYPE_ARRAY_RANK (type); i++)
1180 : {
1181 291 : tree rank = gfc_rank_cst[i];
1182 291 : tree tem = gfc_conv_descriptor_ubound_get (src, rank);
1183 291 : tem = fold_build2_loc (input_location, MINUS_EXPR,
1184 : gfc_array_index_type, tem,
1185 : gfc_conv_descriptor_lbound_get (src, rank));
1186 291 : tem = fold_build2_loc (input_location, PLUS_EXPR,
1187 : gfc_array_index_type, tem,
1188 : gfc_conv_descriptor_lbound_get (dest, rank));
1189 291 : tem = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1190 : tem, gfc_conv_descriptor_ubound_get (dest,
1191 : rank));
1192 291 : cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1193 : logical_type_node, cond, tem);
1194 : }
1195 : }
1196 :
1197 339 : gfc_init_block (&cond_block2);
1198 :
1199 339 : if (GFC_DESCRIPTOR_TYPE_P (type))
1200 : {
1201 203 : gfc_init_block (&inner_block);
1202 203 : gfc_allocate_using_malloc (&inner_block, ptr, size, NULL_TREE);
1203 203 : then_b = gfc_finish_block (&inner_block);
1204 :
1205 203 : gfc_init_block (&inner_block);
1206 203 : gfc_add_modify (&inner_block, ptr,
1207 : gfc_call_realloc (&inner_block, ptr, size));
1208 203 : else_b = gfc_finish_block (&inner_block);
1209 :
1210 203 : gfc_add_expr_to_block (&cond_block2,
1211 : build3_loc (input_location, COND_EXPR,
1212 : void_type_node,
1213 : unshare_expr (nonalloc),
1214 : then_b, else_b));
1215 203 : gfc_add_modify (&cond_block2, dest, src);
1216 203 : gfc_conv_descriptor_data_set (&cond_block2, unshare_expr (dest), ptr);
1217 : }
1218 : else
1219 : {
1220 136 : gfc_allocate_using_malloc (&cond_block2, ptr, size, NULL_TREE);
1221 136 : gfc_add_modify (&cond_block2, unshare_expr (dest),
1222 : fold_convert (type, ptr));
1223 : }
1224 339 : then_b = gfc_finish_block (&cond_block2);
1225 339 : else_b = build_empty_stmt (input_location);
1226 :
1227 339 : gfc_add_expr_to_block (&cond_block,
1228 : build3_loc (input_location, COND_EXPR,
1229 : void_type_node, unshare_expr (cond),
1230 : then_b, else_b));
1231 :
1232 339 : tree srcptr = GFC_DESCRIPTOR_TYPE_P (type)
1233 339 : ? gfc_conv_descriptor_data_get (src) : src;
1234 339 : srcptr = unshare_expr (srcptr);
1235 339 : srcptr = fold_convert (pvoid_type_node, srcptr);
1236 339 : call = build_call_expr_loc (input_location,
1237 : builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr,
1238 : srcptr, size);
1239 339 : gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
1240 339 : if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause), false))
1241 : {
1242 64 : tree tem = gfc_walk_alloc_comps (src, dest,
1243 32 : OMP_CLAUSE_DECL (clause),
1244 : WALK_ALLOC_COMPS_COPY_CTOR);
1245 32 : gfc_add_expr_to_block (&cond_block, tem);
1246 : }
1247 339 : then_b = gfc_finish_block (&cond_block);
1248 :
1249 339 : if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_COPYIN)
1250 : {
1251 66 : gfc_init_block (&cond_block);
1252 66 : if (GFC_DESCRIPTOR_TYPE_P (type))
1253 : {
1254 48 : tree tmp = gfc_conv_descriptor_data_get (unshare_expr (dest));
1255 48 : tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE,
1256 : NULL_TREE, NULL_TREE, true, NULL,
1257 : GFC_CAF_COARRAY_NOCOARRAY);
1258 48 : gfc_add_expr_to_block (&cond_block, tmp);
1259 : }
1260 : else
1261 : {
1262 18 : destptr = gfc_evaluate_now (destptr, &cond_block);
1263 18 : gfc_add_expr_to_block (&cond_block, gfc_call_free (destptr));
1264 18 : gfc_add_modify (&cond_block, unshare_expr (dest),
1265 18 : build_zero_cst (TREE_TYPE (dest)));
1266 : }
1267 66 : else_b = gfc_finish_block (&cond_block);
1268 :
1269 66 : cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1270 : unshare_expr (srcptr), null_pointer_node);
1271 66 : gfc_add_expr_to_block (&block,
1272 : build3_loc (input_location, COND_EXPR,
1273 : void_type_node, cond,
1274 : then_b, else_b));
1275 : }
1276 : else
1277 273 : gfc_add_expr_to_block (&block, then_b);
1278 :
1279 339 : return gfc_finish_block (&block);
1280 : }
1281 :
1282 : static void
1283 84 : gfc_omp_linear_clause_add_loop (stmtblock_t *block, tree dest, tree src,
1284 : tree add, tree nelems)
1285 : {
1286 84 : stmtblock_t tmpblock;
1287 84 : tree desta, srca, index = gfc_create_var (gfc_array_index_type, "S");
1288 84 : nelems = gfc_evaluate_now (nelems, block);
1289 :
1290 84 : gfc_init_block (&tmpblock);
1291 84 : if (TREE_CODE (TREE_TYPE (dest)) == ARRAY_TYPE)
1292 : {
1293 60 : desta = gfc_build_array_ref (dest, index, NULL);
1294 60 : srca = gfc_build_array_ref (src, index, NULL);
1295 : }
1296 : else
1297 : {
1298 24 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (dest)));
1299 24 : tree idx = fold_build2 (MULT_EXPR, sizetype,
1300 : fold_convert (sizetype, index),
1301 : TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (dest))));
1302 24 : desta = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR,
1303 : TREE_TYPE (dest), dest,
1304 : idx));
1305 24 : srca = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR,
1306 : TREE_TYPE (src), src,
1307 : idx));
1308 : }
1309 84 : gfc_add_modify (&tmpblock, desta,
1310 84 : fold_build2 (PLUS_EXPR, TREE_TYPE (desta),
1311 : srca, add));
1312 :
1313 84 : gfc_loopinfo loop;
1314 84 : gfc_init_loopinfo (&loop);
1315 84 : loop.dimen = 1;
1316 84 : loop.from[0] = gfc_index_zero_node;
1317 84 : loop.loopvar[0] = index;
1318 84 : loop.to[0] = nelems;
1319 84 : gfc_trans_scalarizing_loops (&loop, &tmpblock);
1320 84 : gfc_add_block_to_block (block, &loop.pre);
1321 84 : }
1322 :
1323 : /* Build and return code for a constructor of DEST that initializes
1324 : it to SRC plus ADD (ADD is scalar integer). */
1325 :
1326 : tree
1327 108 : gfc_omp_clause_linear_ctor (tree clause, tree dest, tree src, tree add)
1328 : {
1329 108 : tree type = TREE_TYPE (dest), ptr, size, nelems = NULL_TREE;
1330 108 : stmtblock_t block;
1331 :
1332 108 : gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
1333 :
1334 108 : gfc_start_block (&block);
1335 108 : add = gfc_evaluate_now (add, &block);
1336 :
1337 108 : if ((! GFC_DESCRIPTOR_TYPE_P (type)
1338 24 : || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
1339 192 : && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
1340 24 : || !POINTER_TYPE_P (type)))
1341 : {
1342 60 : bool compute_nelts = false;
1343 60 : gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1344 60 : if (!TYPE_DOMAIN (type)
1345 60 : || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE
1346 60 : || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node
1347 120 : || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node)
1348 : compute_nelts = true;
1349 60 : else if (VAR_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
1350 : {
1351 48 : tree a = DECL_ATTRIBUTES (TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
1352 48 : if (lookup_attribute ("omp dummy var", a))
1353 : compute_nelts = true;
1354 : }
1355 : if (compute_nelts)
1356 : {
1357 48 : nelems = fold_build2 (EXACT_DIV_EXPR, sizetype,
1358 : TYPE_SIZE_UNIT (type),
1359 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
1360 48 : nelems = size_binop (MINUS_EXPR, nelems, size_one_node);
1361 : }
1362 : else
1363 12 : nelems = array_type_nelts_minus_one (type);
1364 60 : nelems = fold_convert (gfc_array_index_type, nelems);
1365 :
1366 60 : gfc_omp_linear_clause_add_loop (&block, dest, src, add, nelems);
1367 60 : return gfc_finish_block (&block);
1368 : }
1369 :
1370 : /* Allocatable arrays in LINEAR clauses need to be allocated
1371 : and copied from SRC. */
1372 48 : gfc_add_modify (&block, dest, src);
1373 48 : if (GFC_DESCRIPTOR_TYPE_P (type))
1374 : {
1375 24 : tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
1376 24 : size = gfc_conv_descriptor_ubound_get (dest, rank);
1377 24 : size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
1378 : size,
1379 : gfc_conv_descriptor_lbound_get (dest, rank));
1380 24 : size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1381 : size, gfc_index_one_node);
1382 24 : if (GFC_TYPE_ARRAY_RANK (type) > 1)
1383 0 : size = fold_build2_loc (input_location, MULT_EXPR,
1384 : gfc_array_index_type, size,
1385 : gfc_conv_descriptor_stride_get (dest, rank));
1386 24 : tree esize = fold_convert (gfc_array_index_type,
1387 : TYPE_SIZE_UNIT (gfc_get_element_type (type)));
1388 24 : nelems = gfc_evaluate_now (unshare_expr (size), &block);
1389 24 : size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1390 : nelems, unshare_expr (esize));
1391 24 : size = gfc_evaluate_now (fold_convert (size_type_node, size),
1392 : &block);
1393 24 : nelems = fold_build2_loc (input_location, MINUS_EXPR,
1394 : gfc_array_index_type, nelems,
1395 : gfc_index_one_node);
1396 : }
1397 : else
1398 24 : size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
1399 48 : ptr = gfc_create_var (pvoid_type_node, NULL);
1400 48 : gfc_allocate_using_malloc (&block, ptr, size, NULL_TREE);
1401 48 : if (GFC_DESCRIPTOR_TYPE_P (type))
1402 : {
1403 24 : gfc_conv_descriptor_data_set (&block, unshare_expr (dest), ptr);
1404 24 : tree etype = gfc_get_element_type (type);
1405 24 : ptr = fold_convert (build_pointer_type (etype), ptr);
1406 24 : tree srcptr = gfc_conv_descriptor_data_get (unshare_expr (src));
1407 24 : srcptr = fold_convert (build_pointer_type (etype), srcptr);
1408 24 : gfc_omp_linear_clause_add_loop (&block, ptr, srcptr, add, nelems);
1409 : }
1410 : else
1411 : {
1412 24 : gfc_add_modify (&block, unshare_expr (dest),
1413 24 : fold_convert (TREE_TYPE (dest), ptr));
1414 24 : ptr = fold_convert (TREE_TYPE (dest), ptr);
1415 24 : tree dstm = build_fold_indirect_ref (ptr);
1416 24 : tree srcm = build_fold_indirect_ref (unshare_expr (src));
1417 24 : gfc_add_modify (&block, dstm,
1418 24 : fold_build2 (PLUS_EXPR, TREE_TYPE (add), srcm, add));
1419 : }
1420 48 : return gfc_finish_block (&block);
1421 : }
1422 :
1423 : /* Build and return code destructing DECL. Return NULL if nothing
1424 : to be done. */
1425 :
1426 : tree
1427 32072 : gfc_omp_clause_dtor (tree clause, tree decl)
1428 : {
1429 32072 : tree type = TREE_TYPE (decl), tem;
1430 32072 : tree decl_type = TREE_TYPE (OMP_CLAUSE_DECL (clause));
1431 :
1432 : /* Only pointer was privatized; cf. gfc_omp_clause_copy_ctor. */
1433 32072 : if (DECL_P (OMP_CLAUSE_DECL (clause))
1434 32072 : && GFC_DECL_ASSOCIATE_VAR_P (OMP_CLAUSE_DECL (clause)))
1435 : return NULL_TREE;
1436 :
1437 32045 : if (DECL_ARTIFICIAL (OMP_CLAUSE_DECL (clause))
1438 11897 : && DECL_LANG_SPECIFIC (OMP_CLAUSE_DECL (clause))
1439 32398 : && GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause)))
1440 339 : decl_type
1441 339 : = TREE_TYPE (GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause)));
1442 32045 : if (gfc_is_polymorphic_nonptr (decl_type))
1443 : {
1444 37 : if (POINTER_TYPE_P (decl_type))
1445 24 : decl_type = TREE_TYPE (decl_type);
1446 37 : decl_type = TREE_TYPE (TYPE_FIELDS (decl_type));
1447 37 : if (GFC_DESCRIPTOR_TYPE_P (decl_type) || GFC_ARRAY_TYPE_P (decl_type))
1448 0 : fatal_error (input_location,
1449 : "Sorry, polymorphic arrays not yet supported for "
1450 : "firstprivate");
1451 37 : stmtblock_t block, cond_block;
1452 37 : gfc_start_block (&block);
1453 37 : gfc_init_block (&cond_block);
1454 37 : tree final = gfc_class_vtab_final_get (decl);
1455 37 : tree size = fold_convert (size_type_node, gfc_class_vtab_size_get (decl));
1456 37 : gfc_se se;
1457 37 : gfc_init_se (&se, NULL);
1458 37 : symbol_attribute attr = {};
1459 37 : tree data = gfc_class_data_get (decl);
1460 37 : tree desc = gfc_conv_scalar_to_descriptor (&se, data, attr);
1461 :
1462 : /* Call class->_vpt->_finalize + free. */
1463 37 : tree call = build_fold_indirect_ref (final);
1464 37 : call = build_call_expr_loc (input_location, call, 3,
1465 : gfc_build_addr_expr (NULL, desc),
1466 : size, boolean_false_node);
1467 37 : gfc_add_block_to_block (&cond_block, &se.pre);
1468 37 : gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
1469 37 : gfc_add_block_to_block (&cond_block, &se.post);
1470 : /* Create: if (_vtab && _final) <cond_block> */
1471 37 : tree cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1472 : gfc_class_vptr_get (decl),
1473 : null_pointer_node);
1474 37 : tree cond2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1475 : final, null_pointer_node);
1476 37 : cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
1477 : boolean_type_node, cond, cond2);
1478 37 : gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR,
1479 : void_type_node, cond,
1480 : gfc_finish_block (&cond_block), NULL_TREE));
1481 37 : call = builtin_decl_explicit (BUILT_IN_FREE);
1482 37 : call = build_call_expr_loc (input_location, call, 1, data);
1483 37 : gfc_add_expr_to_block (&block, fold_convert (void_type_node, call));
1484 37 : return gfc_finish_block (&block);
1485 : }
1486 :
1487 32008 : if ((! GFC_DESCRIPTOR_TYPE_P (type)
1488 433 : || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
1489 32059 : && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
1490 186 : || !POINTER_TYPE_P (type)))
1491 : {
1492 31442 : if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause), false))
1493 140 : return gfc_walk_alloc_comps (decl, NULL_TREE,
1494 70 : OMP_CLAUSE_DECL (clause),
1495 70 : WALK_ALLOC_COMPS_DTOR);
1496 : return NULL_TREE;
1497 : }
1498 :
1499 566 : if (GFC_DESCRIPTOR_TYPE_P (type))
1500 : {
1501 : /* Allocatable arrays in FIRSTPRIVATE/LASTPRIVATE etc. clauses need
1502 : to be deallocated if they were allocated. */
1503 382 : tem = gfc_conv_descriptor_data_get (decl);
1504 382 : tem = gfc_deallocate_with_status (tem, NULL_TREE, NULL_TREE, NULL_TREE,
1505 : NULL_TREE, true, NULL,
1506 : GFC_CAF_COARRAY_NOCOARRAY);
1507 : }
1508 : else
1509 184 : tem = gfc_call_free (decl);
1510 566 : tem = gfc_omp_unshare_expr (tem);
1511 :
1512 566 : if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause), false))
1513 : {
1514 86 : stmtblock_t block;
1515 86 : tree then_b;
1516 :
1517 86 : gfc_init_block (&block);
1518 172 : gfc_add_expr_to_block (&block,
1519 : gfc_walk_alloc_comps (decl, NULL_TREE,
1520 86 : OMP_CLAUSE_DECL (clause),
1521 : WALK_ALLOC_COMPS_DTOR));
1522 86 : gfc_add_expr_to_block (&block, tem);
1523 86 : then_b = gfc_finish_block (&block);
1524 :
1525 86 : tem = fold_convert (pvoid_type_node,
1526 : GFC_DESCRIPTOR_TYPE_P (type)
1527 : ? gfc_conv_descriptor_data_get (decl) : decl);
1528 86 : tem = unshare_expr (tem);
1529 86 : tree cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1530 : tem, null_pointer_node);
1531 86 : tem = build3_loc (input_location, COND_EXPR, void_type_node, cond,
1532 : then_b, build_empty_stmt (input_location));
1533 : }
1534 : return tem;
1535 : }
1536 :
1537 : /* Build a conditional expression in BLOCK. If COND_VAL is not
1538 : null, then the block THEN_B is executed, otherwise ELSE_VAL
1539 : is assigned to VAL. */
1540 :
1541 : static void
1542 1026 : gfc_build_cond_assign (stmtblock_t *block, tree val, tree cond_val,
1543 : tree then_b, tree else_val)
1544 : {
1545 1026 : stmtblock_t cond_block;
1546 1026 : tree else_b = NULL_TREE;
1547 1026 : tree val_ty = TREE_TYPE (val);
1548 :
1549 1026 : if (else_val)
1550 : {
1551 1026 : gfc_init_block (&cond_block);
1552 1026 : gfc_add_modify (&cond_block, val, fold_convert (val_ty, else_val));
1553 1026 : else_b = gfc_finish_block (&cond_block);
1554 : }
1555 1026 : gfc_add_expr_to_block (block,
1556 : build3_loc (input_location, COND_EXPR, void_type_node,
1557 : cond_val, then_b, else_b));
1558 1026 : }
1559 :
1560 : /* Build a conditional expression in BLOCK, returning a temporary
1561 : variable containing the result. If COND_VAL is not null, then
1562 : THEN_VAL will be assigned to the variable, otherwise ELSE_VAL
1563 : is assigned.
1564 : */
1565 :
1566 : static tree
1567 1025 : gfc_build_cond_assign_expr (stmtblock_t *block, tree cond_val,
1568 : tree then_val, tree else_val)
1569 : {
1570 1025 : tree val;
1571 1025 : tree val_ty = TREE_TYPE (then_val);
1572 1025 : stmtblock_t cond_block;
1573 :
1574 1025 : val = create_tmp_var (val_ty);
1575 :
1576 1025 : gfc_init_block (&cond_block);
1577 1025 : gfc_add_modify (&cond_block, val, then_val);
1578 1025 : tree then_b = gfc_finish_block (&cond_block);
1579 :
1580 1025 : gfc_build_cond_assign (block, val, cond_val, then_b, else_val);
1581 :
1582 1025 : return val;
1583 : }
1584 :
1585 : void
1586 28752 : gfc_omp_finish_clause (tree c, gimple_seq *pre_p, bool openacc)
1587 : {
1588 28752 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
1589 : return;
1590 :
1591 6975 : tree decl = OMP_CLAUSE_DECL (c);
1592 6975 : location_t loc = OMP_CLAUSE_LOCATION (c);
1593 :
1594 : /* Assumed-size arrays can't be mapped implicitly, they have to be
1595 : mapped explicitly using array sections. */
1596 6975 : if (TREE_CODE (decl) == PARM_DECL
1597 1047 : && GFC_ARRAY_TYPE_P (TREE_TYPE (decl))
1598 371 : && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN
1599 7346 : && GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (decl),
1600 : GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)) - 1)
1601 : == NULL)
1602 : {
1603 1 : error_at (OMP_CLAUSE_LOCATION (c),
1604 : "implicit mapping of assumed size array %qD", decl);
1605 1 : return;
1606 : }
1607 :
1608 6974 : tree c2 = NULL_TREE, c3 = NULL_TREE, c4 = NULL_TREE;
1609 6974 : tree present = gfc_omp_check_optional_argument (decl, true);
1610 6974 : tree orig_decl = NULL_TREE;
1611 6974 : if (POINTER_TYPE_P (TREE_TYPE (decl)))
1612 : {
1613 1286 : if (!gfc_omp_privatize_by_reference (decl)
1614 154 : && !GFC_DECL_GET_SCALAR_POINTER (decl)
1615 91 : && !GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
1616 3 : && !GFC_DECL_CRAY_POINTEE (decl)
1617 1289 : && !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
1618 : return;
1619 1283 : orig_decl = decl;
1620 :
1621 1283 : c4 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
1622 1283 : OMP_CLAUSE_SET_MAP_KIND (c4, GOMP_MAP_POINTER);
1623 1283 : OMP_CLAUSE_DECL (c4) = decl;
1624 1283 : OMP_CLAUSE_SIZE (c4) = size_int (0);
1625 1283 : decl = build_fold_indirect_ref (decl);
1626 1283 : if (present
1627 1283 : && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
1628 269 : || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
1629 : {
1630 67 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
1631 67 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER);
1632 67 : OMP_CLAUSE_DECL (c2) = unshare_expr (decl);
1633 67 : OMP_CLAUSE_SIZE (c2) = size_int (0);
1634 :
1635 67 : stmtblock_t block;
1636 67 : gfc_start_block (&block);
1637 67 : tree ptr = gfc_build_cond_assign_expr (&block, present,
1638 : unshare_expr (decl),
1639 : null_pointer_node);
1640 67 : gimplify_and_add (gfc_finish_block (&block), pre_p);
1641 67 : ptr = build_fold_indirect_ref (ptr);
1642 67 : OMP_CLAUSE_DECL (c) = ptr;
1643 67 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
1644 : }
1645 : else
1646 : {
1647 1216 : OMP_CLAUSE_DECL (c) = decl;
1648 1216 : OMP_CLAUSE_SIZE (c) = NULL_TREE;
1649 : }
1650 1283 : if (TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE
1651 1283 : && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
1652 391 : || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
1653 : {
1654 67 : c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
1655 67 : OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_POINTER);
1656 67 : OMP_CLAUSE_DECL (c3) = decl;
1657 67 : OMP_CLAUSE_SIZE (c3) = size_int (0);
1658 67 : decl = build_fold_indirect_ref (decl);
1659 67 : OMP_CLAUSE_DECL (c) = unshare_expr (decl);
1660 : }
1661 : }
1662 6971 : if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
1663 : {
1664 1729 : stmtblock_t block;
1665 1729 : gfc_start_block (&block);
1666 1729 : tree type = TREE_TYPE (decl);
1667 1729 : tree ptr = gfc_conv_descriptor_data_get (decl);
1668 :
1669 : /* OpenMP: automatically map pointer targets with the pointer;
1670 : hence, always update the descriptor/pointer itself.
1671 : NOTE: This also remaps the pointer for allocatable arrays with
1672 : 'target' attribute which also don't have the 'restrict' qualifier. */
1673 1729 : bool always_modifier = false;
1674 :
1675 1729 : if (!openacc
1676 1729 : && !(TYPE_QUALS (TREE_TYPE (ptr)) & TYPE_QUAL_RESTRICT))
1677 : always_modifier = true;
1678 :
1679 1729 : if (present)
1680 56 : ptr = gfc_build_cond_assign_expr (&block, present, ptr,
1681 : null_pointer_node);
1682 1729 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
1683 1729 : ptr = build_fold_indirect_ref (ptr);
1684 1729 : OMP_CLAUSE_DECL (c) = ptr;
1685 1729 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
1686 1729 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_TO_PSET);
1687 1729 : if (present)
1688 : {
1689 56 : ptr = create_tmp_var (TREE_TYPE (TREE_OPERAND (decl, 0)));
1690 56 : gfc_add_modify (&block, ptr, TREE_OPERAND (decl, 0));
1691 :
1692 56 : OMP_CLAUSE_DECL (c2) = build_fold_indirect_ref (ptr);
1693 : }
1694 : else
1695 1673 : OMP_CLAUSE_DECL (c2) = decl;
1696 1729 : OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (type);
1697 1729 : c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
1698 3247 : OMP_CLAUSE_SET_MAP_KIND (c3, always_modifier ? GOMP_MAP_ALWAYS_POINTER
1699 : : GOMP_MAP_POINTER);
1700 1729 : if (present)
1701 : {
1702 56 : ptr = gfc_conv_descriptor_data_get (unshare_expr (decl));
1703 56 : ptr = gfc_build_addr_expr (NULL, ptr);
1704 56 : ptr = gfc_build_cond_assign_expr (&block, present,
1705 : ptr, null_pointer_node);
1706 56 : ptr = build_fold_indirect_ref (ptr);
1707 56 : OMP_CLAUSE_DECL (c3) = ptr;
1708 : }
1709 : else
1710 1673 : OMP_CLAUSE_DECL (c3) = gfc_conv_descriptor_data_get (decl);
1711 1729 : OMP_CLAUSE_SIZE (c3) = size_int (0);
1712 1729 : tree size = create_tmp_var (gfc_array_index_type);
1713 1729 : tree elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
1714 1729 : elemsz = fold_convert (gfc_array_index_type, elemsz);
1715 :
1716 1729 : if (orig_decl == NULL_TREE)
1717 1495 : orig_decl = decl;
1718 1729 : if (!openacc
1719 1729 : && gfc_has_alloc_comps (type, orig_decl, true))
1720 : {
1721 : /* Save array descriptor for use in gfc_omp_deep_mapping{,_p,_cnt};
1722 : force evaluate to ensure that it is not gimplified + is a decl. */
1723 3 : gfc_allocate_lang_decl (size);
1724 3 : GFC_DECL_SAVED_DESCRIPTOR (size) = orig_decl;
1725 : }
1726 1729 : enum gfc_array_kind akind = GFC_TYPE_ARRAY_AKIND (type);
1727 1729 : if (akind == GFC_ARRAY_ALLOCATABLE
1728 : || akind == GFC_ARRAY_POINTER
1729 1729 : || akind == GFC_ARRAY_POINTER_CONT
1730 1729 : || akind == GFC_ARRAY_ASSUMED_RANK_ALLOCATABLE
1731 : || akind == GFC_ARRAY_ASSUMED_RANK_POINTER
1732 1 : || akind == GFC_ARRAY_ASSUMED_RANK_POINTER_CONT)
1733 : {
1734 1728 : stmtblock_t cond_block;
1735 1728 : tree tem, then_b, else_b, zero, cond;
1736 :
1737 1728 : int rank = ((akind == GFC_ARRAY_ASSUMED_RANK_ALLOCATABLE
1738 : || akind == GFC_ARRAY_ASSUMED_RANK_POINTER
1739 1728 : || akind == GFC_ARRAY_ASSUMED_RANK_POINTER_CONT)
1740 1728 : ? -1 : GFC_TYPE_ARRAY_RANK (type));
1741 1728 : gfc_init_block (&cond_block);
1742 1728 : tem = gfc_full_array_size (&cond_block, unshare_expr (decl), rank);
1743 1728 : gfc_add_modify (&cond_block, size, tem);
1744 1728 : gfc_add_modify (&cond_block, size,
1745 : fold_build2 (MULT_EXPR, gfc_array_index_type,
1746 : size, elemsz));
1747 1728 : then_b = gfc_finish_block (&cond_block);
1748 1728 : gfc_init_block (&cond_block);
1749 1728 : zero = build_int_cst (gfc_array_index_type, 0);
1750 1728 : gfc_add_modify (&cond_block, size, zero);
1751 1728 : else_b = gfc_finish_block (&cond_block);
1752 1728 : tem = gfc_conv_descriptor_data_get (unshare_expr (decl));
1753 1728 : tem = fold_convert (pvoid_type_node, tem);
1754 1728 : cond = fold_build2_loc (loc, NE_EXPR,
1755 : boolean_type_node, tem, null_pointer_node);
1756 1728 : if (present)
1757 : {
1758 55 : cond = fold_build2_loc (loc, TRUTH_ANDIF_EXPR,
1759 : boolean_type_node, present, cond);
1760 : }
1761 1728 : gfc_add_expr_to_block (&block, build3_loc (loc, COND_EXPR,
1762 : void_type_node, cond,
1763 : then_b, else_b));
1764 1728 : }
1765 1 : else if (present)
1766 : {
1767 1 : stmtblock_t cond_block;
1768 1 : tree then_b;
1769 :
1770 1 : int rank = ((akind == GFC_ARRAY_ASSUMED_RANK
1771 1 : || akind == GFC_ARRAY_ASSUMED_RANK_CONT)
1772 1 : ? -1 : GFC_TYPE_ARRAY_RANK (type));
1773 1 : gfc_init_block (&cond_block);
1774 1 : gfc_add_modify (&cond_block, size,
1775 : gfc_full_array_size (&cond_block, unshare_expr (decl),
1776 : rank));
1777 1 : gfc_add_modify (&cond_block, size,
1778 : fold_build2 (MULT_EXPR, gfc_array_index_type,
1779 : size, elemsz));
1780 1 : then_b = gfc_finish_block (&cond_block);
1781 :
1782 1 : gfc_build_cond_assign (&block, size, present, then_b,
1783 : build_int_cst (gfc_array_index_type, 0));
1784 : }
1785 : else
1786 : {
1787 0 : int rank = ((akind == GFC_ARRAY_ASSUMED_RANK
1788 0 : || akind == GFC_ARRAY_ASSUMED_RANK_CONT)
1789 0 : ? -1 : GFC_TYPE_ARRAY_RANK (type));
1790 0 : gfc_add_modify (&block, size,
1791 : gfc_full_array_size (&block, unshare_expr (decl),
1792 : rank));
1793 0 : gfc_add_modify (&block, size,
1794 : fold_build2 (MULT_EXPR, gfc_array_index_type,
1795 : size, elemsz));
1796 : }
1797 1729 : OMP_CLAUSE_SIZE (c) = size;
1798 1729 : tree stmt = gfc_finish_block (&block);
1799 1729 : gimplify_and_add (stmt, pre_p);
1800 : }
1801 : else
1802 : {
1803 5242 : if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
1804 1194 : OMP_CLAUSE_SIZE (c)
1805 3370 : = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
1806 982 : : TYPE_SIZE_UNIT (TREE_TYPE (decl));
1807 :
1808 5242 : tree type = TREE_TYPE (decl);
1809 5242 : if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE (type)))
1810 0 : type = TREE_TYPE (type);
1811 5242 : if (!openacc
1812 5242 : && orig_decl != NULL_TREE
1813 5242 : && gfc_has_alloc_comps (type, orig_decl, true))
1814 : {
1815 : /* Save array descriptor for use in gfc_omp_deep_mapping{,_p,_cnt};
1816 : force evaluate to ensure that it is not gimplified + is a decl. */
1817 19 : tree size = create_tmp_var (TREE_TYPE (OMP_CLAUSE_SIZE (c)));
1818 19 : gfc_allocate_lang_decl (size);
1819 19 : GFC_DECL_SAVED_DESCRIPTOR (size) = orig_decl;
1820 19 : gimplify_assign (size, OMP_CLAUSE_SIZE (c), pre_p);
1821 19 : OMP_CLAUSE_SIZE (c) = size;
1822 : }
1823 : }
1824 6971 : tree last = c;
1825 6971 : if (gimplify_expr (&OMP_CLAUSE_SIZE (c), pre_p,
1826 : NULL, is_gimple_val, fb_rvalue) == GS_ERROR)
1827 0 : OMP_CLAUSE_SIZE (c) = size_int (0);
1828 6971 : if (c2)
1829 : {
1830 1796 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (last);
1831 1796 : OMP_CLAUSE_CHAIN (last) = c2;
1832 1796 : last = c2;
1833 : }
1834 6971 : if (c3)
1835 : {
1836 1796 : OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (last);
1837 1796 : OMP_CLAUSE_CHAIN (last) = c3;
1838 1796 : last = c3;
1839 : }
1840 6971 : if (c4)
1841 : {
1842 1283 : OMP_CLAUSE_CHAIN (c4) = OMP_CLAUSE_CHAIN (last);
1843 1283 : OMP_CLAUSE_CHAIN (last) = c4;
1844 : }
1845 : }
1846 :
1847 :
1848 : /* map(<flag>: data [len: <size>])
1849 : map(attach: &data [bias: <bias>])
1850 : offset += 2; offset_data += 2 */
1851 : static void
1852 645 : gfc_omp_deep_mapping_map (tree data, tree size, unsigned HOST_WIDE_INT tkind,
1853 : location_t loc, tree data_array, tree sizes_array,
1854 : tree kinds_array, tree offset_data, tree offset,
1855 : gimple_seq *seq, const gimple *ctx)
1856 : {
1857 645 : tree one = build_int_cst (size_type_node, 1);
1858 :
1859 645 : STRIP_NOPS (data);
1860 645 : if (!POINTER_TYPE_P (TREE_TYPE (data)))
1861 : {
1862 205 : gcc_assert (TREE_CODE (data) == INDIRECT_REF);
1863 205 : data = TREE_OPERAND (data, 0);
1864 : }
1865 :
1866 : /* data_array[offset_data] = data; */
1867 645 : tree tmp = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (data_array)),
1868 : unshare_expr (data_array), offset_data,
1869 : NULL_TREE, NULL_TREE);
1870 645 : gimplify_assign (tmp, data, seq);
1871 :
1872 : /* offset_data++ */
1873 645 : tmp = build2_loc (loc, PLUS_EXPR, size_type_node, offset_data, one);
1874 645 : gimplify_assign (offset_data, tmp, seq);
1875 :
1876 : /* data_array[offset_data] = &data; */
1877 645 : tmp = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (data_array)),
1878 : unshare_expr (data_array),
1879 : offset_data, NULL_TREE, NULL_TREE);
1880 645 : gimplify_assign (tmp, build_fold_addr_expr (data), seq);
1881 :
1882 : /* offset_data++ */
1883 645 : tmp = build2_loc (loc, PLUS_EXPR, size_type_node, offset_data, one);
1884 645 : gimplify_assign (offset_data, tmp, seq);
1885 :
1886 : /* sizes_array[offset] = size */
1887 645 : tmp = build2_loc (loc, MULT_EXPR, size_type_node,
1888 645 : TYPE_SIZE_UNIT (size_type_node), offset);
1889 645 : tmp = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (sizes_array),
1890 : sizes_array, tmp);
1891 645 : gimple_seq seq2 = NULL;
1892 645 : tmp = force_gimple_operand (tmp, &seq2, true, NULL_TREE);
1893 645 : gimple_seq_add_seq (seq, seq2);
1894 645 : tmp = build_fold_indirect_ref_loc (loc, tmp);
1895 645 : gimplify_assign (tmp, size, seq);
1896 :
1897 : /* FIXME: tkind |= talign << talign_shift; */
1898 : /* kinds_array[offset] = tkind. */
1899 645 : tmp = build2_loc (loc, MULT_EXPR, size_type_node,
1900 645 : TYPE_SIZE_UNIT (short_unsigned_type_node), offset);
1901 645 : tmp = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (kinds_array),
1902 : kinds_array, tmp);
1903 645 : seq2 = NULL;
1904 645 : tmp = force_gimple_operand (tmp, &seq2, true, NULL_TREE);
1905 645 : gimple_seq_add_seq (seq, seq2);
1906 645 : tmp = build_fold_indirect_ref_loc (loc, tmp);
1907 645 : gimplify_assign (tmp, build_int_cst (short_unsigned_type_node, tkind), seq);
1908 :
1909 : /* offset++ */
1910 645 : tmp = build2_loc (loc, PLUS_EXPR, size_type_node, offset, one);
1911 645 : gimplify_assign (offset, tmp, seq);
1912 :
1913 : /* sizes_array[offset] = bias (= 0). */
1914 645 : tmp = build2_loc (loc, MULT_EXPR, size_type_node,
1915 645 : TYPE_SIZE_UNIT (size_type_node), offset);
1916 645 : tmp = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (sizes_array),
1917 : sizes_array, tmp);
1918 645 : seq2 = NULL;
1919 645 : tmp = force_gimple_operand (tmp, &seq2, true, NULL_TREE);
1920 645 : gimple_seq_add_seq (seq, seq2);
1921 645 : tmp = build_fold_indirect_ref_loc (loc, tmp);
1922 645 : gimplify_assign (tmp, build_zero_cst (size_type_node), seq);
1923 :
1924 645 : gcc_assert (gimple_code (ctx) == GIMPLE_OMP_TARGET);
1925 645 : tkind = (gimple_omp_target_kind (ctx) == GF_OMP_TARGET_KIND_EXIT_DATA
1926 645 : ? GOMP_MAP_DETACH : GOMP_MAP_ATTACH);
1927 :
1928 : /* kinds_array[offset] = tkind. */
1929 645 : tmp = build2_loc (loc, MULT_EXPR, size_type_node,
1930 645 : TYPE_SIZE_UNIT (short_unsigned_type_node), offset);
1931 645 : tmp = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (kinds_array),
1932 : kinds_array, tmp);
1933 645 : seq2 = NULL;
1934 645 : tmp = force_gimple_operand (tmp, &seq2, true, NULL_TREE);
1935 645 : gimple_seq_add_seq (seq, seq2);
1936 645 : tmp = build_fold_indirect_ref_loc (loc, tmp);
1937 645 : gimplify_assign (tmp, build_int_cst (short_unsigned_type_node, tkind), seq);
1938 :
1939 : /* offset++ */
1940 645 : tmp = build2_loc (loc, PLUS_EXPR, size_type_node, offset, one);
1941 645 : gimplify_assign (offset, tmp, seq);
1942 645 : }
1943 :
1944 : static void gfc_omp_deep_mapping_item (bool, bool, bool, location_t, tree,
1945 : tree *, unsigned HOST_WIDE_INT, tree,
1946 : tree, tree, tree, tree, tree,
1947 : gimple_seq *, const gimple *, bool *);
1948 :
1949 : /* Map allocatable components. */
1950 : static void
1951 926 : gfc_omp_deep_mapping_comps (bool is_cnt, location_t loc, tree decl,
1952 : tree *token, unsigned HOST_WIDE_INT tkind,
1953 : tree data_array, tree sizes_array, tree kinds_array,
1954 : tree offset_data, tree offset, tree num,
1955 : gimple_seq *seq, const gimple *ctx,
1956 : bool *poly_warned)
1957 : {
1958 926 : tree type = TREE_TYPE (decl);
1959 926 : if (TREE_CODE (type) != RECORD_TYPE)
1960 : return;
1961 2562 : for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
1962 : {
1963 1640 : type = TREE_TYPE (field);
1964 1640 : if (gfc_is_polymorphic_nonptr (type)
1965 1438 : || GFC_DECL_GET_SCALAR_ALLOCATABLE (field)
1966 2800 : || (GFC_DESCRIPTOR_TYPE_P (type)
1967 770 : && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE))
1968 : {
1969 1250 : tree tmp = fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (field),
1970 : decl, field, NULL_TREE);
1971 1250 : gfc_omp_deep_mapping_item (is_cnt, true, true, loc, tmp, token,
1972 : tkind, data_array, sizes_array,
1973 : kinds_array, offset_data, offset, num,
1974 : seq, ctx, poly_warned);
1975 : }
1976 390 : else if (GFC_DECL_GET_SCALAR_POINTER (field)
1977 390 : || GFC_DESCRIPTOR_TYPE_P (type))
1978 0 : continue;
1979 390 : else if (gfc_has_alloc_comps (TREE_TYPE (field), field, false))
1980 : {
1981 104 : tree tmp = fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (field),
1982 : decl, field, NULL_TREE);
1983 104 : if (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
1984 40 : gfc_omp_deep_mapping_item (is_cnt, false, false, loc, tmp,
1985 : token, tkind, data_array, sizes_array,
1986 : kinds_array, offset_data, offset, num,
1987 : seq, ctx, poly_warned);
1988 : else
1989 64 : gfc_omp_deep_mapping_comps (is_cnt, loc, tmp, token, tkind,
1990 : data_array, sizes_array, kinds_array,
1991 : offset_data, offset, num, seq, ctx,
1992 : poly_warned);
1993 : }
1994 : }
1995 : }
1996 :
1997 : static void
1998 944 : gfc_omp_gen_simple_loop (tree var, tree begin, tree end, enum tree_code cond,
1999 : tree step, location_t loc, gimple_seq *seq1,
2000 : gimple_seq *seq2)
2001 : {
2002 944 : tree tmp;
2003 :
2004 : /* var = begin. */
2005 944 : gimplify_assign (var, begin, seq1);
2006 :
2007 : /* Loop: for (var = begin; var <cond> end; var += step). */
2008 944 : tree label_loop = create_artificial_label (loc);
2009 944 : tree label_cond = create_artificial_label (loc);
2010 :
2011 944 : gimplify_and_add (fold_build1_loc (loc, GOTO_EXPR, void_type_node,
2012 : label_cond), seq1);
2013 944 : gimple_seq_add_stmt (seq1, gimple_build_label (label_loop));
2014 :
2015 : /* Everything above is seq1; place loop body here. */
2016 :
2017 : /* End of loop body -> put into seq2. */
2018 944 : tmp = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (var), var, step);
2019 944 : gimplify_assign (var, tmp, seq2);
2020 944 : gimple_seq_add_stmt (seq2, gimple_build_label (label_cond));
2021 944 : tmp = fold_build2_loc (loc, cond, boolean_type_node, var, end);
2022 944 : tmp = build3_v (COND_EXPR, tmp, build1_v (GOTO_EXPR, label_loop),
2023 : build_empty_stmt (loc));
2024 944 : gimplify_and_add (tmp, seq2);
2025 944 : }
2026 :
2027 : /* Return size variable with the size of an array. */
2028 : static tree
2029 604 : gfc_omp_get_array_size (location_t loc, tree desc, gimple_seq *seq)
2030 : {
2031 604 : tree tmp;
2032 604 : gimple_seq seq1 = NULL, seq2 = NULL;
2033 604 : tree size = build_decl (loc, VAR_DECL, create_tmp_var_name ("size"),
2034 : size_type_node);
2035 604 : tree extent = build_decl (loc, VAR_DECL, create_tmp_var_name ("extent"),
2036 : gfc_array_index_type);
2037 604 : tree idx = build_decl (loc, VAR_DECL, create_tmp_var_name ("idx"),
2038 : signed_char_type_node);
2039 :
2040 604 : tree begin = build_zero_cst (signed_char_type_node);
2041 604 : tree end;
2042 604 : if (GFC_TYPE_ARRAY_AKIND (TREE_TYPE (desc)) == GFC_ARRAY_ASSUMED_SHAPE_CONT
2043 604 : || GFC_TYPE_ARRAY_AKIND (TREE_TYPE (desc)) == GFC_ARRAY_ASSUMED_SHAPE)
2044 8 : end = gfc_conv_descriptor_rank (desc);
2045 : else
2046 596 : end = build_int_cst (signed_char_type_node,
2047 596 : GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc)));
2048 604 : tree step = build_int_cst (signed_char_type_node, 1);
2049 :
2050 : /* size = 0
2051 : for (idx = 0; idx < rank; idx++)
2052 : extent = gfc->dim[i].ubound - gfc->dim[i].lbound + 1
2053 : if (extent < 0) extent = 0
2054 : size *= extent. */
2055 604 : gimplify_assign (size, build_int_cst (size_type_node, 1), seq);
2056 :
2057 604 : gfc_omp_gen_simple_loop (idx, begin, end, LT_EXPR, step, loc, &seq1, &seq2);
2058 604 : gimple_seq_add_seq (seq, seq1);
2059 :
2060 604 : tmp = fold_build2_loc (loc, MINUS_EXPR, gfc_array_index_type,
2061 : gfc_conv_descriptor_ubound_get (desc, idx),
2062 : gfc_conv_descriptor_lbound_get (desc, idx));
2063 604 : tmp = fold_build2_loc (loc, PLUS_EXPR, gfc_array_index_type,
2064 : tmp, gfc_index_one_node);
2065 604 : gimplify_assign (extent, tmp, seq);
2066 604 : tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node,
2067 : extent, gfc_index_zero_node);
2068 604 : tmp = build3_v (COND_EXPR, tmp,
2069 : fold_build2_loc (loc, MODIFY_EXPR,
2070 : gfc_array_index_type,
2071 : extent, gfc_index_zero_node),
2072 : build_empty_stmt (loc));
2073 604 : gimplify_and_add (tmp, seq);
2074 : /* size *= extent. */
2075 604 : gimplify_assign (size, fold_build2_loc (loc, MULT_EXPR, size_type_node, size,
2076 : fold_convert (size_type_node,
2077 : extent)), seq);
2078 604 : gimple_seq_add_seq (seq, seq2);
2079 604 : return size;
2080 : }
2081 :
2082 : /* Generate loop to access every array element; takes addr of first element
2083 : (decl's data comp); returns loop code in seq1 + seq2
2084 : and the pointer to the element as return value. */
2085 : static tree
2086 340 : gfc_omp_elmental_loop (location_t loc, tree decl, tree size, tree elem_len,
2087 : gimple_seq *seq1, gimple_seq *seq2)
2088 : {
2089 340 : tree idx = build_decl (loc, VAR_DECL, create_tmp_var_name ("idx"),
2090 : size_type_node);
2091 340 : tree begin = build_zero_cst (size_type_node);
2092 340 : tree end = size;
2093 340 : tree step = build_int_cst (size_type_node, 1);
2094 340 : tree ptr;
2095 :
2096 340 : gfc_omp_gen_simple_loop (idx, begin, end, LT_EXPR, step, loc, seq1, seq2);
2097 :
2098 340 : tree type = TREE_TYPE (decl);
2099 340 : if (POINTER_TYPE_P (type))
2100 : {
2101 296 : type = TREE_TYPE (type);
2102 296 : gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
2103 296 : decl = fold_convert (build_pointer_type (TREE_TYPE (type)), decl);
2104 : }
2105 : else
2106 : {
2107 44 : gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
2108 44 : decl = build_fold_addr_expr_loc (loc, decl);
2109 : }
2110 340 : decl = fold_convert (build_pointer_type (TREE_TYPE (type)), decl);
2111 340 : tree tmp = build2_loc (loc, MULT_EXPR, size_type_node, idx,
2112 : fold_convert (size_type_node, elem_len));
2113 340 : ptr = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (decl), decl, tmp);
2114 340 : gimple_seq seq3 = NULL;
2115 340 : ptr = force_gimple_operand (ptr, &seq3, true, NULL_TREE);
2116 340 : gimple_seq_add_seq (seq1, seq3);
2117 :
2118 340 : return ptr;
2119 : }
2120 :
2121 :
2122 : /* If do_copy, copy data pointer and vptr (if applicable) as well.
2123 : Otherwise, only handle allocatable components.
2124 : do_copy == false can happen only with nonpolymorphic arguments
2125 : to a copy clause.
2126 : if (is_cnt) token ... offset is ignored and num is used, otherwise
2127 : num is NULL_TREE and unused. */
2128 :
2129 : static void
2130 1696 : gfc_omp_deep_mapping_item (bool is_cnt, bool do_copy, bool do_alloc_check,
2131 : location_t loc, tree decl, tree *token,
2132 : unsigned HOST_WIDE_INT tkind, tree data_array,
2133 : tree sizes_array, tree kinds_array, tree offset_data,
2134 : tree offset, tree num, gimple_seq *seq,
2135 : const gimple *ctx, bool *poly_warned)
2136 : {
2137 1696 : tree tmp;
2138 1696 : tree type = TREE_TYPE (decl);
2139 1696 : if (POINTER_TYPE_P (type))
2140 416 : type = TREE_TYPE (type);
2141 1696 : tree end_label = NULL_TREE;
2142 1696 : tree size = NULL_TREE, elem_len = NULL_TREE;
2143 :
2144 1696 : bool poly = gfc_is_polymorphic_nonptr (type);
2145 1696 : if (poly && is_cnt && !*poly_warned)
2146 : {
2147 41 : if (gfc_is_unlimited_polymorphic_nonptr (type))
2148 2 : error_at (loc,
2149 : "Mapping of unlimited polymorphic list item %qD is "
2150 : "unspecified behavior and unsupported", decl);
2151 :
2152 : else
2153 39 : warning_at (loc, OPT_Wopenmp,
2154 : "Mapping of polymorphic list item %qD is "
2155 : "unspecified behavior", decl);
2156 41 : *poly_warned = true;
2157 : }
2158 1696 : if (do_alloc_check)
2159 : {
2160 1428 : tree then_label = create_artificial_label (loc);
2161 1428 : end_label = create_artificial_label (loc);
2162 1428 : tmp = decl;
2163 1428 : if (TREE_CODE (TREE_TYPE (tmp)) == REFERENCE_TYPE
2164 1428 : || (POINTER_TYPE_P (TREE_TYPE (tmp))
2165 396 : && (POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (tmp)))
2166 396 : || GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (tmp))))))
2167 8 : tmp = build_fold_indirect_ref_loc (loc, tmp);
2168 1428 : if (poly)
2169 242 : tmp = gfc_class_data_get (tmp);
2170 1428 : if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
2171 904 : tmp = gfc_conv_descriptor_data_get (tmp);
2172 1428 : gimple_seq seq2 = NULL;
2173 1428 : tmp = force_gimple_operand (tmp, &seq2, true, NULL_TREE);
2174 1428 : gimple_seq_add_seq (seq, seq2);
2175 :
2176 1428 : gimple_seq_add_stmt (seq,
2177 1428 : gimple_build_cond (NE_EXPR, tmp, null_pointer_node,
2178 : then_label, end_label));
2179 1428 : gimple_seq_add_stmt (seq, gimple_build_label (then_label));
2180 : }
2181 1696 : tree class_decl = decl;
2182 1696 : if (poly)
2183 : {
2184 242 : decl = gfc_class_data_get (decl);
2185 242 : type = TREE_TYPE (decl);
2186 : }
2187 1696 : if (POINTER_TYPE_P (TREE_TYPE (decl)))
2188 : {
2189 548 : decl = build_fold_indirect_ref (decl);
2190 548 : type = TREE_TYPE (decl);
2191 : }
2192 :
2193 1696 : if (is_cnt && do_copy)
2194 : {
2195 645 : tree tmp = fold_build2_loc (loc, PLUS_EXPR, size_type_node,
2196 : num, build_int_cst (size_type_node, 1));
2197 645 : gimplify_assign (num, tmp, seq);
2198 : }
2199 1051 : else if (do_copy)
2200 : {
2201 : /* copy data pointer */
2202 645 : tree bytesize;
2203 645 : if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
2204 : {
2205 : /* TODO: Optimization: Shouldn't this be an expr. const, except for
2206 : deferred-length strings. (Cf. also below). */
2207 440 : elem_len = (poly ? gfc_class_vtab_size_get (class_decl)
2208 385 : : gfc_conv_descriptor_elem_len (decl));
2209 880 : tmp = (POINTER_TYPE_P (TREE_TYPE (decl))
2210 440 : ? build_fold_indirect_ref (decl) : decl);
2211 440 : size = gfc_omp_get_array_size (loc, tmp, seq);
2212 440 : bytesize = fold_build2_loc (loc, MULT_EXPR, size_type_node,
2213 : fold_convert (size_type_node, size),
2214 : fold_convert (size_type_node, elem_len));
2215 440 : tmp = gfc_conv_descriptor_data_get (decl);
2216 : }
2217 205 : else if (poly)
2218 : {
2219 66 : tmp = decl;
2220 66 : bytesize = fold_convert (size_type_node,
2221 : gfc_class_vtab_size_get (class_decl));
2222 : }
2223 : else
2224 : {
2225 139 : tmp = decl;
2226 139 : bytesize = TYPE_SIZE_UNIT (TREE_TYPE (decl));
2227 : }
2228 645 : unsigned HOST_WIDE_INT tkind2 = tkind;
2229 645 : if (!is_cnt
2230 645 : && (tkind == GOMP_MAP_ALLOC
2231 617 : || (tkind == GOMP_MAP_FROM
2232 60 : && (gimple_omp_target_kind (ctx)
2233 : != GF_OMP_TARGET_KIND_EXIT_DATA)))
2234 689 : && gfc_omp_replace_alloc_by_to_mapping (TREE_TYPE (decl), decl, true))
2235 12 : tkind2 = tkind == GOMP_MAP_ALLOC ? GOMP_MAP_TO : GOMP_MAP_TOFROM;
2236 :
2237 645 : gfc_omp_deep_mapping_map (tmp, bytesize, tkind2, loc, data_array,
2238 : sizes_array, kinds_array, offset_data,
2239 : offset, seq, ctx);
2240 : }
2241 :
2242 1696 : tmp = decl;
2243 1696 : if (POINTER_TYPE_P (TREE_TYPE (decl)))
2244 0 : while (TREE_CODE (tmp) == COMPONENT_REF || TREE_CODE (tmp) == ARRAY_REF)
2245 0 : tmp = TREE_OPERAND (tmp, TREE_CODE (tmp) == COMPONENT_REF ? 1 : 0);
2246 1696 : if (poly || gfc_has_alloc_comps (type, tmp, true))
2247 : {
2248 862 : gimple_seq seq2 = NULL;
2249 862 : if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
2250 : {
2251 296 : if (elem_len == NULL_TREE)
2252 : {
2253 164 : elem_len = gfc_conv_descriptor_elem_len (decl);
2254 164 : size = fold_convert (size_type_node,
2255 : gfc_omp_get_array_size (loc, decl, seq));
2256 : }
2257 296 : decl = gfc_conv_descriptor_data_get (decl);
2258 296 : decl = gfc_omp_elmental_loop (loc, decl, size, elem_len, seq, &seq2);
2259 296 : decl = build_fold_indirect_ref_loc (loc, decl);
2260 : }
2261 566 : else if (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
2262 : {
2263 44 : type = TREE_TYPE (tmp);
2264 : /* FIXME: PR95868 - for var%str of deferred length, elem_len == 0;
2265 : len is stored as var%_str_length, but not in GFC_DECL_STRING_LEN
2266 : nor in TYPE_SIZE_UNIT as expression. */
2267 44 : elem_len = TYPE_SIZE_UNIT (TREE_TYPE (type));
2268 44 : size = fold_convert (size_type_node, GFC_TYPE_ARRAY_SIZE (type));
2269 44 : decl = gfc_omp_elmental_loop (loc, decl, size, elem_len, seq, &seq2);
2270 44 : decl = build_fold_indirect_ref_loc (loc, decl);
2271 : }
2272 522 : else if (POINTER_TYPE_P (TREE_TYPE (decl)))
2273 0 : decl = build_fold_indirect_ref (decl);
2274 :
2275 862 : gfc_omp_deep_mapping_comps (is_cnt, loc, decl, token, tkind,
2276 : data_array, sizes_array, kinds_array,
2277 : offset_data, offset, num, seq, ctx,
2278 : poly_warned);
2279 862 : gimple_seq_add_seq (seq, seq2);
2280 : }
2281 1696 : if (end_label)
2282 1428 : gimple_seq_add_stmt (seq, gimple_build_label (end_label));
2283 1696 : }
2284 :
2285 :
2286 : /* Which map types to check/handle for deep mapping. */
2287 : static bool
2288 40439 : gfc_omp_deep_map_kind_p (tree clause)
2289 : {
2290 40439 : switch (OMP_CLAUSE_CODE (clause))
2291 : {
2292 36883 : case OMP_CLAUSE_MAP:
2293 36883 : break;
2294 : case OMP_CLAUSE_FIRSTPRIVATE:
2295 : case OMP_CLAUSE_TO:
2296 : case OMP_CLAUSE_FROM:
2297 : return true;
2298 0 : default:
2299 0 : gcc_unreachable ();
2300 : }
2301 :
2302 36883 : switch (OMP_CLAUSE_MAP_KIND (clause))
2303 : {
2304 : case GOMP_MAP_TO:
2305 : case GOMP_MAP_FROM:
2306 : case GOMP_MAP_TOFROM:
2307 : case GOMP_MAP_ALWAYS_TO:
2308 : case GOMP_MAP_ALWAYS_FROM:
2309 : case GOMP_MAP_ALWAYS_TOFROM:
2310 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
2311 : case GOMP_MAP_ALWAYS_PRESENT_TO:
2312 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
2313 : case GOMP_MAP_FIRSTPRIVATE:
2314 : case GOMP_MAP_ALLOC:
2315 : return true;
2316 : case GOMP_MAP_POINTER:
2317 : case GOMP_MAP_TO_PSET:
2318 : case GOMP_MAP_FORCE_PRESENT:
2319 : case GOMP_MAP_DELETE:
2320 : case GOMP_MAP_FORCE_DEVICEPTR:
2321 : case GOMP_MAP_DEVICE_RESIDENT:
2322 : case GOMP_MAP_LINK:
2323 : case GOMP_MAP_IF_PRESENT:
2324 : case GOMP_MAP_PRESENT_ALLOC:
2325 : case GOMP_MAP_PRESENT_FROM:
2326 : case GOMP_MAP_PRESENT_TO:
2327 : case GOMP_MAP_PRESENT_TOFROM:
2328 : case GOMP_MAP_FIRSTPRIVATE_INT:
2329 : case GOMP_MAP_USE_DEVICE_PTR:
2330 : case GOMP_MAP_ZERO_LEN_ARRAY_SECTION:
2331 : case GOMP_MAP_FORCE_ALLOC:
2332 : case GOMP_MAP_FORCE_TO:
2333 : case GOMP_MAP_FORCE_FROM:
2334 : case GOMP_MAP_FORCE_TOFROM:
2335 : case GOMP_MAP_USE_DEVICE_PTR_IF_PRESENT:
2336 : case GOMP_MAP_STRUCT:
2337 : case GOMP_MAP_STRUCT_UNORD:
2338 : case GOMP_MAP_ALWAYS_POINTER:
2339 : case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
2340 : case GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION:
2341 : case GOMP_MAP_RELEASE:
2342 : case GOMP_MAP_ATTACH:
2343 : case GOMP_MAP_DETACH:
2344 : case GOMP_MAP_FORCE_DETACH:
2345 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
2346 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
2347 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
2348 : case GOMP_MAP_ATTACH_DETACH:
2349 : break;
2350 0 : default:
2351 0 : gcc_unreachable ();
2352 : }
2353 : return false;
2354 : }
2355 :
2356 : /* Three OpenMP deep-mapping lang hooks: gfc_omp_deep_mapping{_p,_cnt,}. */
2357 :
2358 : /* Common check for gfc_omp_deep_mapping_p and gfc_omp_deep_mapping_do. */
2359 :
2360 : static tree
2361 91974 : gfc_omp_deep_mapping_int_p (const gimple *ctx, tree clause)
2362 : {
2363 91974 : if (is_gimple_omp_oacc (ctx) || !gfc_omp_deep_map_kind_p (clause))
2364 : return NULL_TREE;
2365 21230 : tree decl = OMP_CLAUSE_DECL (clause);
2366 21230 : if (OMP_CLAUSE_SIZE (clause) != NULL_TREE
2367 21220 : && DECL_P (OMP_CLAUSE_SIZE (clause))
2368 6569 : && DECL_LANG_SPECIFIC (OMP_CLAUSE_SIZE (clause))
2369 21529 : && GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_SIZE (clause)))
2370 : /* Saved decl. */
2371 299 : decl = GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_SIZE (clause));
2372 20931 : else if (TREE_CODE (decl) == MEM_REF || TREE_CODE (decl) == INDIRECT_REF)
2373 : /* The following can happen for, e.g., class(t) :: var(..) */
2374 12216 : decl = TREE_OPERAND (decl, 0);
2375 21230 : if (TREE_CODE (decl) == INDIRECT_REF)
2376 : /* The following can happen for, e.g., class(t) :: var(..) */
2377 132 : decl = TREE_OPERAND (decl, 0);
2378 21230 : if (DECL_P (decl)
2379 12652 : && DECL_LANG_SPECIFIC (decl)
2380 23380 : && GFC_DECL_SAVED_DESCRIPTOR (decl))
2381 62 : decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
2382 : /* Handle map(to: var.desc) map([to/from/tofrom:] var.desc.data)
2383 : to get proper map kind by skipping to the next item. */
2384 21230 : tree tmp = OMP_CLAUSE_CHAIN (clause);
2385 21230 : if (tmp != NULL_TREE
2386 15843 : && OMP_CLAUSE_CODE (tmp) == OMP_CLAUSE_CODE (clause)
2387 14276 : && OMP_CLAUSE_SIZE (tmp) != NULL_TREE
2388 14276 : && DECL_P (OMP_CLAUSE_SIZE (tmp))
2389 1410 : && DECL_LANG_SPECIFIC (OMP_CLAUSE_SIZE (tmp))
2390 21302 : && GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_SIZE (tmp)) == decl)
2391 : return NULL_TREE;
2392 21230 : if (DECL_P (decl)
2393 12652 : && DECL_LANG_SPECIFIC (decl)
2394 23347 : && GFC_DECL_SAVED_DESCRIPTOR (decl))
2395 29 : decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
2396 21230 : tree type = TREE_TYPE (decl);
2397 21230 : if (POINTER_TYPE_P (type))
2398 13146 : type = TREE_TYPE (type);
2399 21230 : if (POINTER_TYPE_P (type))
2400 140 : type = TREE_TYPE (type);
2401 21230 : tmp = decl;
2402 22905 : while (TREE_CODE (tmp) == COMPONENT_REF || TREE_CODE (tmp) == ARRAY_REF)
2403 2248 : tmp = TREE_OPERAND (tmp, TREE_CODE (tmp) == COMPONENT_REF ? 1 : 0);
2404 21230 : if (!gfc_is_polymorphic_nonptr (type)
2405 21230 : && !gfc_has_alloc_comps (type, tmp, true))
2406 : return NULL_TREE;
2407 : return decl;
2408 : }
2409 :
2410 : /* Return true if there is deep mapping, even if the number of mapping is known
2411 : at compile time. */
2412 : bool
2413 44494 : gfc_omp_deep_mapping_p (const gimple *ctx, tree clause)
2414 : {
2415 44494 : tree decl = gfc_omp_deep_mapping_int_p (ctx, clause);
2416 44494 : if (decl == NULL_TREE)
2417 44350 : return false;
2418 : return true;
2419 : }
2420 :
2421 : /* Handle gfc_omp_deep_mapping{,_cnt} */
2422 : static tree
2423 47456 : gfc_omp_deep_mapping_do (bool is_cnt, const gimple *ctx, tree clause,
2424 : unsigned HOST_WIDE_INT tkind, tree data, tree sizes,
2425 : tree kinds, tree offset_data, tree offset,
2426 : gimple_seq *seq)
2427 : {
2428 47456 : tree num = NULL_TREE;
2429 47456 : location_t loc = OMP_CLAUSE_LOCATION (clause);
2430 47456 : tree decl = gfc_omp_deep_mapping_int_p (ctx, clause);
2431 47456 : bool poly_warned = false;
2432 47456 : if (decl == NULL_TREE)
2433 : return NULL_TREE;
2434 : /* Handle: map(alloc:dt%cmp [len: ptr_size]) map(tofrom: D.0123...),
2435 : where GFC_DECL_SAVED_DESCRIPTOR(D.0123) is the same (here: dt%cmp). */
2436 418 : if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_MAP
2437 418 : && (OMP_CLAUSE_MAP_KIND (clause) == GOMP_MAP_ALLOC
2438 374 : || OMP_CLAUSE_MAP_KIND (clause) == GOMP_MAP_PRESENT_ALLOC))
2439 : {
2440 : tree c = clause;
2441 84 : while ((c = OMP_CLAUSE_CHAIN (c)) != NULL_TREE)
2442 : {
2443 60 : if (!gfc_omp_deep_map_kind_p (c))
2444 36 : continue;
2445 24 : tree d = gfc_omp_deep_mapping_int_p (ctx, c);
2446 24 : if (d != NULL_TREE && operand_equal_p (decl, d, 0))
2447 : return NULL_TREE;
2448 : }
2449 : }
2450 406 : tree type = TREE_TYPE (decl);
2451 406 : if (POINTER_TYPE_P (type))
2452 138 : type = TREE_TYPE (type);
2453 406 : if (POINTER_TYPE_P (type))
2454 8 : type = TREE_TYPE (type);
2455 406 : bool poly = gfc_is_polymorphic_nonptr (type);
2456 :
2457 406 : if (is_cnt)
2458 : {
2459 203 : num = build_decl (loc, VAR_DECL,
2460 : create_tmp_var_name ("n_deepmap"), size_type_node);
2461 203 : tree tmp = fold_build2_loc (loc, MODIFY_EXPR, size_type_node, num,
2462 : build_int_cst (size_type_node, 0));
2463 203 : gimple_add_tmp_var (num);
2464 203 : gimplify_and_add (tmp, seq);
2465 : }
2466 : else
2467 203 : gcc_assert (short_unsigned_type_node == TREE_TYPE (TREE_TYPE (kinds)));
2468 :
2469 406 : bool do_copy = poly;
2470 406 : bool do_alloc_check = false;
2471 406 : tree token = NULL_TREE;
2472 406 : tree tmp = decl;
2473 406 : if (poly)
2474 : {
2475 40 : tmp = TYPE_FIELDS (type);
2476 40 : type = TREE_TYPE (tmp);
2477 : }
2478 : else
2479 418 : while (TREE_CODE (tmp) == COMPONENT_REF || TREE_CODE (tmp) == ARRAY_REF)
2480 72 : tmp = TREE_OPERAND (tmp, TREE_CODE (tmp) == COMPONENT_REF ? 1 : 0);
2481 406 : if (TREE_CODE (tmp) == MEM_REF)
2482 16 : tmp = TREE_OPERAND (tmp, 0);
2483 406 : if (TREE_CODE (tmp) == SSA_NAME)
2484 : {
2485 16 : gimple *def_stmt = SSA_NAME_DEF_STMT (tmp);
2486 16 : if (gimple_code (def_stmt) == GIMPLE_ASSIGN)
2487 : {
2488 16 : tmp = gimple_assign_rhs1 (def_stmt);
2489 16 : if (poly)
2490 : {
2491 0 : tmp = TYPE_FIELDS (type);
2492 0 : type = TREE_TYPE (tmp);
2493 : }
2494 : else
2495 32 : while (TREE_CODE (tmp) == COMPONENT_REF
2496 32 : || TREE_CODE (tmp) == ARRAY_REF)
2497 16 : tmp = TREE_OPERAND (tmp,
2498 : TREE_CODE (tmp) == COMPONENT_REF ? 1 : 0);
2499 : }
2500 : }
2501 : /* If the clause argument is nonallocatable, skip is-allocate check. */
2502 406 : if (GFC_DECL_GET_SCALAR_ALLOCATABLE (tmp)
2503 278 : || GFC_DECL_GET_SCALAR_POINTER (tmp)
2504 420 : || (GFC_DESCRIPTOR_TYPE_P (type)
2505 42 : && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
2506 24 : || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER
2507 8 : || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT)))
2508 : do_alloc_check = true;
2509 :
2510 406 : if (!is_cnt
2511 203 : && OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_MAP
2512 199 : && (tkind == GOMP_MAP_ALLOC
2513 187 : || (tkind == GOMP_MAP_FROM
2514 21 : && (gimple_omp_target_kind (ctx)
2515 : != GF_OMP_TARGET_KIND_EXIT_DATA)))
2516 442 : && (poly || gfc_omp_replace_alloc_by_to_mapping (type, tmp, true)))
2517 24 : OMP_CLAUSE_SET_MAP_KIND (clause, tkind == GOMP_MAP_ALLOC ? GOMP_MAP_TO
2518 : : GOMP_MAP_TOFROM);
2519 :
2520 : /* TODO: For map(a(:)), we know it is present & allocated. */
2521 :
2522 406 : tree present = (DECL_P (decl) ? gfc_omp_check_optional_argument (decl, true)
2523 : : NULL_TREE);
2524 690 : if (POINTER_TYPE_P (TREE_TYPE (decl))
2525 422 : && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
2526 8 : decl = build_fold_indirect_ref (decl);
2527 406 : if (present)
2528 : {
2529 16 : tree then_label = create_artificial_label (loc);
2530 16 : tree end_label = create_artificial_label (loc);
2531 16 : gimple_seq seq2 = NULL;
2532 16 : tmp = force_gimple_operand (present, &seq2, true, NULL_TREE);
2533 16 : gimple_seq_add_seq (seq, seq2);
2534 16 : gimple_seq_add_stmt (seq,
2535 16 : gimple_build_cond_from_tree (present,
2536 : then_label, end_label));
2537 16 : gimple_seq_add_stmt (seq, gimple_build_label (then_label));
2538 16 : gfc_omp_deep_mapping_item (is_cnt, do_copy, do_alloc_check, loc, decl,
2539 : &token, tkind, data, sizes, kinds,
2540 : offset_data, offset, num, seq, ctx,
2541 : &poly_warned);
2542 16 : gimple_seq_add_stmt (seq, gimple_build_label (end_label));
2543 : }
2544 : else
2545 390 : gfc_omp_deep_mapping_item (is_cnt, do_copy, do_alloc_check, loc, decl,
2546 : &token, tkind, data, sizes, kinds, offset_data,
2547 : offset, num, seq, ctx, &poly_warned);
2548 : /* Multiply by 2 as there are two mappings: data + pointer assign. */
2549 406 : if (is_cnt)
2550 203 : gimplify_assign (num,
2551 : fold_build2_loc (loc, MULT_EXPR,
2552 : size_type_node, num,
2553 : build_int_cst (size_type_node, 2)), seq);
2554 : return num;
2555 : }
2556 :
2557 : /* Return tree with a variable which contains the count of deep-mappyings
2558 : (value depends, e.g., on allocation status) */
2559 : tree
2560 47028 : gfc_omp_deep_mapping_cnt (const gimple *ctx, tree clause, gimple_seq *seq)
2561 : {
2562 47028 : return gfc_omp_deep_mapping_do (true, ctx, clause, 0, NULL_TREE, NULL_TREE,
2563 47028 : NULL_TREE, NULL_TREE, NULL_TREE, seq);
2564 : }
2565 :
2566 : /* Does the actual deep mapping. */
2567 : void
2568 428 : gfc_omp_deep_mapping (const gimple *ctx, tree clause,
2569 : unsigned HOST_WIDE_INT tkind, tree data,
2570 : tree sizes, tree kinds, tree offset_data, tree offset,
2571 : gimple_seq *seq)
2572 : {
2573 428 : (void) gfc_omp_deep_mapping_do (false, ctx, clause, tkind, data, sizes, kinds,
2574 : offset_data, offset, seq);
2575 428 : }
2576 :
2577 : /* Return true if DECL is a scalar variable (for the purpose of
2578 : implicit firstprivatization/mapping). Only if 'ptr_alloc_ok.'
2579 : is true, allocatables and pointers are permitted. */
2580 :
2581 : bool
2582 3744 : gfc_omp_scalar_p (tree decl, bool ptr_alloc_ok)
2583 : {
2584 3744 : tree type = TREE_TYPE (decl);
2585 3744 : if (TREE_CODE (type) == REFERENCE_TYPE)
2586 1350 : type = TREE_TYPE (type);
2587 3744 : if (TREE_CODE (type) == POINTER_TYPE)
2588 : {
2589 587 : if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
2590 587 : || GFC_DECL_GET_SCALAR_POINTER (decl))
2591 : {
2592 148 : if (!ptr_alloc_ok)
2593 : return false;
2594 0 : type = TREE_TYPE (type);
2595 : }
2596 439 : if (GFC_ARRAY_TYPE_P (type)
2597 439 : || GFC_CLASS_TYPE_P (type))
2598 : return false;
2599 : }
2600 3196 : if ((TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == INTEGER_TYPE)
2601 5700 : && TYPE_STRING_FLAG (type))
2602 : return false;
2603 3272 : if (INTEGRAL_TYPE_P (type)
2604 3272 : || SCALAR_FLOAT_TYPE_P (type)
2605 3272 : || COMPLEX_FLOAT_TYPE_P (type))
2606 2692 : return true;
2607 : return false;
2608 : }
2609 :
2610 :
2611 : /* Return true if DECL is a scalar with target attribute but does not have the
2612 : allocatable (or pointer) attribute (for the purpose of implicit mapping). */
2613 :
2614 : bool
2615 3636 : gfc_omp_scalar_target_p (tree decl)
2616 : {
2617 3636 : return (DECL_P (decl) && GFC_DECL_GET_SCALAR_TARGET (decl)
2618 3737 : && gfc_omp_scalar_p (decl, false));
2619 : }
2620 :
2621 :
2622 : /* Return true if DECL's DECL_VALUE_EXPR (if any) should be
2623 : disregarded in OpenMP construct, because it is going to be
2624 : remapped during OpenMP lowering. SHARED is true if DECL
2625 : is going to be shared, false if it is going to be privatized. */
2626 :
2627 : bool
2628 1674733 : gfc_omp_disregard_value_expr (tree decl, bool shared)
2629 : {
2630 1674733 : if (GFC_DECL_COMMON_OR_EQUIV (decl)
2631 1674733 : && DECL_HAS_VALUE_EXPR_P (decl))
2632 : {
2633 3030 : tree value = DECL_VALUE_EXPR (decl);
2634 :
2635 3030 : if (TREE_CODE (value) == COMPONENT_REF
2636 3030 : && VAR_P (TREE_OPERAND (value, 0))
2637 6060 : && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
2638 : {
2639 : /* If variable in COMMON or EQUIVALENCE is privatized, return
2640 : true, as just that variable is supposed to be privatized,
2641 : not the whole COMMON or whole EQUIVALENCE.
2642 : For shared variables in COMMON or EQUIVALENCE, let them be
2643 : gimplified to DECL_VALUE_EXPR, so that for multiple shared vars
2644 : from the same COMMON or EQUIVALENCE just one sharing of the
2645 : whole COMMON or EQUIVALENCE is enough. */
2646 3030 : return ! shared;
2647 : }
2648 : }
2649 :
2650 1671703 : if (GFC_DECL_RESULT (decl) && DECL_HAS_VALUE_EXPR_P (decl))
2651 334 : return ! shared;
2652 :
2653 : return false;
2654 : }
2655 :
2656 : /* Return true if DECL that is shared iff SHARED is true should
2657 : be put into OMP_CLAUSE_PRIVATE with OMP_CLAUSE_PRIVATE_DEBUG
2658 : flag set. */
2659 :
2660 : bool
2661 38499 : gfc_omp_private_debug_clause (tree decl, bool shared)
2662 : {
2663 38499 : if (GFC_DECL_CRAY_POINTEE (decl))
2664 : return true;
2665 :
2666 38463 : if (GFC_DECL_COMMON_OR_EQUIV (decl)
2667 38463 : && DECL_HAS_VALUE_EXPR_P (decl))
2668 : {
2669 326 : tree value = DECL_VALUE_EXPR (decl);
2670 :
2671 326 : if (TREE_CODE (value) == COMPONENT_REF
2672 326 : && VAR_P (TREE_OPERAND (value, 0))
2673 652 : && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
2674 : return shared;
2675 : }
2676 :
2677 : return false;
2678 : }
2679 :
2680 : /* Register language specific type size variables as potentially OpenMP
2681 : firstprivate variables. */
2682 :
2683 : void
2684 21722 : gfc_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
2685 : {
2686 21722 : if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
2687 : {
2688 3982 : int r;
2689 :
2690 3982 : gcc_assert (TYPE_LANG_SPECIFIC (type) != NULL);
2691 9166 : for (r = 0; r < GFC_TYPE_ARRAY_RANK (type); r++)
2692 : {
2693 5184 : omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_LBOUND (type, r));
2694 5184 : omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_UBOUND (type, r));
2695 5184 : omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_STRIDE (type, r));
2696 : }
2697 3982 : omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_SIZE (type));
2698 3982 : omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_OFFSET (type));
2699 : }
2700 21722 : }
2701 :
2702 :
2703 : static inline tree
2704 75545 : gfc_trans_add_clause (tree node, tree tail)
2705 : {
2706 75545 : OMP_CLAUSE_CHAIN (node) = tail;
2707 75545 : return node;
2708 : }
2709 :
2710 : static tree
2711 43331 : gfc_trans_omp_variable (gfc_symbol *sym, bool declare_simd)
2712 : {
2713 43331 : if (declare_simd)
2714 : {
2715 182 : int cnt = 0;
2716 182 : gfc_symbol *proc_sym;
2717 182 : gfc_formal_arglist *f;
2718 :
2719 182 : gcc_assert (sym->attr.dummy);
2720 182 : proc_sym = sym->ns->proc_name;
2721 182 : if (proc_sym->attr.entry_master)
2722 0 : ++cnt;
2723 182 : if (gfc_return_by_reference (proc_sym))
2724 : {
2725 0 : ++cnt;
2726 0 : if (proc_sym->ts.type == BT_CHARACTER)
2727 0 : ++cnt;
2728 : }
2729 349 : for (f = gfc_sym_get_dummy_args (proc_sym); f; f = f->next)
2730 349 : if (f->sym == sym)
2731 : break;
2732 167 : else if (f->sym)
2733 167 : ++cnt;
2734 182 : gcc_assert (f);
2735 182 : return build_int_cst (integer_type_node, cnt);
2736 : }
2737 :
2738 43149 : tree t = gfc_get_symbol_decl (sym);
2739 43149 : tree parent_decl;
2740 43149 : int parent_flag;
2741 43149 : bool return_value;
2742 43149 : bool alternate_entry;
2743 43149 : bool entry_master;
2744 :
2745 43149 : return_value = sym->attr.function && sym->result == sym;
2746 167 : alternate_entry = sym->attr.function && sym->attr.entry
2747 43183 : && sym->result == sym;
2748 86298 : entry_master = sym->attr.result
2749 172 : && sym->ns->proc_name->attr.entry_master
2750 43161 : && !gfc_return_by_reference (sym->ns->proc_name);
2751 43149 : parent_decl = current_function_decl
2752 43149 : ? DECL_CONTEXT (current_function_decl) : NULL_TREE;
2753 :
2754 43149 : if ((t == parent_decl && return_value)
2755 43142 : || (sym->ns && sym->ns->proc_name
2756 43142 : && sym->ns->proc_name->backend_decl == parent_decl
2757 2173 : && (alternate_entry || entry_master)))
2758 : parent_flag = 1;
2759 : else
2760 43140 : parent_flag = 0;
2761 :
2762 : /* Special case for assigning the return value of a function.
2763 : Self recursive functions must have an explicit return value. */
2764 43149 : if (return_value && (t == current_function_decl || parent_flag))
2765 97 : t = gfc_get_fake_result_decl (sym, parent_flag);
2766 :
2767 : /* Similarly for alternate entry points. */
2768 43052 : else if (alternate_entry
2769 32 : && (sym->ns->proc_name->backend_decl == current_function_decl
2770 0 : || parent_flag))
2771 : {
2772 32 : gfc_entry_list *el = NULL;
2773 :
2774 51 : for (el = sym->ns->entries; el; el = el->next)
2775 51 : if (sym == el->sym)
2776 : {
2777 32 : t = gfc_get_fake_result_decl (sym, parent_flag);
2778 32 : break;
2779 : }
2780 : }
2781 :
2782 43020 : else if (entry_master
2783 12 : && (sym->ns->proc_name->backend_decl == current_function_decl
2784 0 : || parent_flag))
2785 12 : t = gfc_get_fake_result_decl (sym, parent_flag);
2786 :
2787 : return t;
2788 : }
2789 :
2790 : static tree
2791 11702 : gfc_trans_omp_variable_list (enum omp_clause_code code,
2792 : gfc_omp_namelist *namelist, tree list,
2793 : bool declare_simd)
2794 : {
2795 : /* PARAMETER (named constants) are excluded as OpenACC 3.4 permits them now
2796 : as 'var' but permits compilers to ignore them. In expressions, it should
2797 : have been replaced by the value (and this function should not be called
2798 : anyway) and for var-using clauses, they should just be skipped. */
2799 30164 : for (; namelist != NULL; namelist = namelist->next)
2800 18462 : if ((namelist->sym->attr.referenced || declare_simd)
2801 18462 : && namelist->sym->attr.flavor != FL_PARAMETER)
2802 : {
2803 18457 : tree t = gfc_trans_omp_variable (namelist->sym, declare_simd);
2804 18457 : if (t != error_mark_node)
2805 : {
2806 18457 : tree node;
2807 18457 : node = build_omp_clause (input_location, code);
2808 18457 : OMP_CLAUSE_DECL (node) = t;
2809 18457 : list = gfc_trans_add_clause (node, list);
2810 :
2811 18457 : if (code == OMP_CLAUSE_LASTPRIVATE
2812 2864 : && namelist->u.lastprivate_conditional)
2813 88 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (node) = 1;
2814 : }
2815 : }
2816 11702 : return list;
2817 : }
2818 :
2819 : struct omp_udr_find_orig_data
2820 : {
2821 : gfc_omp_udr *omp_udr;
2822 : bool omp_orig_seen;
2823 : };
2824 :
2825 : static int
2826 678 : omp_udr_find_orig (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
2827 : void *data)
2828 : {
2829 678 : struct omp_udr_find_orig_data *cd = (struct omp_udr_find_orig_data *) data;
2830 678 : if ((*e)->expr_type == EXPR_VARIABLE
2831 366 : && (*e)->symtree->n.sym == cd->omp_udr->omp_orig)
2832 72 : cd->omp_orig_seen = true;
2833 :
2834 678 : return 0;
2835 : }
2836 :
2837 : static void
2838 683 : gfc_trans_omp_array_reduction_or_udr (tree c, gfc_omp_namelist *n, locus where)
2839 : {
2840 683 : gfc_symbol *sym = n->sym;
2841 683 : gfc_symtree *root1 = NULL, *root2 = NULL, *root3 = NULL, *root4 = NULL;
2842 683 : gfc_symtree *symtree1, *symtree2, *symtree3, *symtree4 = NULL;
2843 683 : gfc_symbol init_val_sym, outer_sym, intrinsic_sym;
2844 683 : gfc_symbol omp_var_copy[4];
2845 683 : gfc_expr *e1, *e2, *e3, *e4;
2846 683 : gfc_ref *ref;
2847 683 : tree decl, backend_decl, stmt, type, outer_decl;
2848 683 : locus old_loc = gfc_current_locus;
2849 683 : const char *iname;
2850 683 : bool t;
2851 683 : gfc_omp_udr *udr = n->u2.udr ? n->u2.udr->udr : NULL;
2852 :
2853 683 : decl = OMP_CLAUSE_DECL (c);
2854 683 : gfc_current_locus = where;
2855 683 : type = TREE_TYPE (decl);
2856 683 : outer_decl = create_tmp_var_raw (type);
2857 683 : if (TREE_CODE (decl) == PARM_DECL
2858 31 : && TREE_CODE (type) == REFERENCE_TYPE
2859 12 : && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type))
2860 695 : && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (type)) == GFC_ARRAY_ALLOCATABLE)
2861 : {
2862 12 : decl = build_fold_indirect_ref (decl);
2863 12 : type = TREE_TYPE (type);
2864 : }
2865 :
2866 : /* Create a fake symbol for init value. */
2867 683 : memset (&init_val_sym, 0, sizeof (init_val_sym));
2868 683 : init_val_sym.ns = sym->ns;
2869 683 : init_val_sym.name = sym->name;
2870 683 : init_val_sym.ts = sym->ts;
2871 683 : init_val_sym.attr.referenced = 1;
2872 683 : init_val_sym.declared_at = where;
2873 683 : init_val_sym.attr.flavor = FL_VARIABLE;
2874 683 : if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK)
2875 283 : backend_decl = omp_reduction_init (c, gfc_sym_type (&init_val_sym));
2876 400 : else if (udr->initializer_ns)
2877 : backend_decl = NULL;
2878 : else
2879 130 : switch (sym->ts.type)
2880 : {
2881 15 : case BT_LOGICAL:
2882 15 : case BT_INTEGER:
2883 15 : case BT_REAL:
2884 15 : case BT_COMPLEX:
2885 15 : backend_decl = build_zero_cst (gfc_sym_type (&init_val_sym));
2886 15 : break;
2887 : default:
2888 : backend_decl = NULL_TREE;
2889 : break;
2890 : }
2891 683 : init_val_sym.backend_decl = backend_decl;
2892 :
2893 : /* Create a fake symbol for the outer array reference. */
2894 683 : outer_sym = *sym;
2895 683 : if (sym->as)
2896 426 : outer_sym.as = gfc_copy_array_spec (sym->as);
2897 683 : outer_sym.attr.dummy = 0;
2898 683 : outer_sym.attr.result = 0;
2899 683 : outer_sym.attr.flavor = FL_VARIABLE;
2900 683 : outer_sym.backend_decl = outer_decl;
2901 683 : if (decl != OMP_CLAUSE_DECL (c))
2902 12 : outer_sym.backend_decl = build_fold_indirect_ref (outer_decl);
2903 :
2904 : /* Create fake symtrees for it. */
2905 683 : symtree1 = gfc_new_symtree (&root1, sym->name);
2906 683 : symtree1->n.sym = sym;
2907 683 : gcc_assert (symtree1 == root1);
2908 :
2909 683 : symtree2 = gfc_new_symtree (&root2, sym->name);
2910 683 : symtree2->n.sym = &init_val_sym;
2911 683 : gcc_assert (symtree2 == root2);
2912 :
2913 683 : symtree3 = gfc_new_symtree (&root3, sym->name);
2914 683 : symtree3->n.sym = &outer_sym;
2915 683 : gcc_assert (symtree3 == root3);
2916 :
2917 683 : memset (omp_var_copy, 0, sizeof omp_var_copy);
2918 683 : if (udr)
2919 : {
2920 400 : omp_var_copy[0] = *udr->omp_out;
2921 400 : omp_var_copy[1] = *udr->omp_in;
2922 400 : *udr->omp_out = outer_sym;
2923 400 : *udr->omp_in = *sym;
2924 400 : if (udr->initializer_ns)
2925 : {
2926 270 : omp_var_copy[2] = *udr->omp_priv;
2927 270 : omp_var_copy[3] = *udr->omp_orig;
2928 270 : *udr->omp_priv = *sym;
2929 270 : *udr->omp_orig = outer_sym;
2930 : }
2931 : }
2932 :
2933 : /* Create expressions. */
2934 683 : e1 = gfc_get_expr ();
2935 683 : e1->expr_type = EXPR_VARIABLE;
2936 683 : e1->where = where;
2937 683 : e1->symtree = symtree1;
2938 683 : e1->ts = sym->ts;
2939 683 : if (sym->attr.dimension)
2940 : {
2941 426 : e1->ref = ref = gfc_get_ref ();
2942 426 : ref->type = REF_ARRAY;
2943 426 : ref->u.ar.where = where;
2944 426 : ref->u.ar.as = sym->as;
2945 426 : ref->u.ar.type = AR_FULL;
2946 426 : ref->u.ar.dimen = 0;
2947 : }
2948 683 : t = gfc_resolve_expr (e1);
2949 683 : gcc_assert (t);
2950 :
2951 683 : e2 = NULL;
2952 683 : if (backend_decl != NULL_TREE)
2953 : {
2954 298 : e2 = gfc_get_expr ();
2955 298 : e2->expr_type = EXPR_VARIABLE;
2956 298 : e2->where = where;
2957 298 : e2->symtree = symtree2;
2958 298 : e2->ts = sym->ts;
2959 298 : t = gfc_resolve_expr (e2);
2960 298 : gcc_assert (t);
2961 : }
2962 385 : else if (udr->initializer_ns == NULL)
2963 : {
2964 115 : gcc_assert (sym->ts.type == BT_DERIVED);
2965 115 : e2 = gfc_default_initializer (&sym->ts);
2966 115 : gcc_assert (e2);
2967 115 : t = gfc_resolve_expr (e2);
2968 115 : gcc_assert (t);
2969 : }
2970 270 : else if (n->u2.udr->initializer->op == EXEC_ASSIGN)
2971 : {
2972 204 : e2 = gfc_copy_expr (n->u2.udr->initializer->expr2);
2973 204 : t = gfc_resolve_expr (e2);
2974 204 : gcc_assert (t);
2975 : }
2976 683 : if (udr && udr->initializer_ns)
2977 : {
2978 270 : struct omp_udr_find_orig_data cd;
2979 270 : cd.omp_udr = udr;
2980 270 : cd.omp_orig_seen = false;
2981 270 : gfc_code_walker (&n->u2.udr->initializer,
2982 : gfc_dummy_code_callback, omp_udr_find_orig, &cd);
2983 270 : if (cd.omp_orig_seen)
2984 72 : OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c) = 1;
2985 : }
2986 :
2987 683 : e3 = gfc_copy_expr (e1);
2988 683 : e3->symtree = symtree3;
2989 683 : t = gfc_resolve_expr (e3);
2990 683 : gcc_assert (t);
2991 :
2992 683 : iname = NULL;
2993 683 : e4 = NULL;
2994 683 : switch (OMP_CLAUSE_REDUCTION_CODE (c))
2995 : {
2996 159 : case PLUS_EXPR:
2997 159 : case MINUS_EXPR:
2998 159 : e4 = gfc_add (e3, e1);
2999 159 : break;
3000 26 : case MULT_EXPR:
3001 26 : e4 = gfc_multiply (e3, e1);
3002 26 : break;
3003 6 : case TRUTH_ANDIF_EXPR:
3004 6 : e4 = gfc_and (e3, e1);
3005 6 : break;
3006 6 : case TRUTH_ORIF_EXPR:
3007 6 : e4 = gfc_or (e3, e1);
3008 6 : break;
3009 6 : case EQ_EXPR:
3010 6 : e4 = gfc_eqv (e3, e1);
3011 6 : break;
3012 6 : case NE_EXPR:
3013 6 : e4 = gfc_neqv (e3, e1);
3014 6 : break;
3015 : case MIN_EXPR:
3016 : iname = "min";
3017 : break;
3018 : case MAX_EXPR:
3019 : iname = "max";
3020 : break;
3021 : case BIT_AND_EXPR:
3022 : iname = "iand";
3023 : break;
3024 : case BIT_IOR_EXPR:
3025 : iname = "ior";
3026 : break;
3027 : case BIT_XOR_EXPR:
3028 : iname = "ieor";
3029 : break;
3030 400 : case ERROR_MARK:
3031 400 : if (n->u2.udr->combiner->op == EXEC_ASSIGN)
3032 : {
3033 334 : gfc_free_expr (e3);
3034 334 : e3 = gfc_copy_expr (n->u2.udr->combiner->expr1);
3035 334 : e4 = gfc_copy_expr (n->u2.udr->combiner->expr2);
3036 334 : t = gfc_resolve_expr (e3);
3037 334 : gcc_assert (t);
3038 334 : t = gfc_resolve_expr (e4);
3039 334 : gcc_assert (t);
3040 : }
3041 : break;
3042 0 : default:
3043 0 : gcc_unreachable ();
3044 : }
3045 209 : if (iname != NULL)
3046 : {
3047 74 : memset (&intrinsic_sym, 0, sizeof (intrinsic_sym));
3048 74 : intrinsic_sym.ns = sym->ns;
3049 74 : intrinsic_sym.name = iname;
3050 74 : intrinsic_sym.ts = sym->ts;
3051 74 : intrinsic_sym.attr.referenced = 1;
3052 74 : intrinsic_sym.attr.intrinsic = 1;
3053 74 : intrinsic_sym.attr.function = 1;
3054 74 : intrinsic_sym.attr.implicit_type = 1;
3055 74 : intrinsic_sym.result = &intrinsic_sym;
3056 74 : intrinsic_sym.declared_at = where;
3057 :
3058 74 : symtree4 = gfc_new_symtree (&root4, iname);
3059 74 : symtree4->n.sym = &intrinsic_sym;
3060 74 : gcc_assert (symtree4 == root4);
3061 :
3062 74 : e4 = gfc_get_expr ();
3063 74 : e4->expr_type = EXPR_FUNCTION;
3064 74 : e4->where = where;
3065 74 : e4->symtree = symtree4;
3066 74 : e4->value.function.actual = gfc_get_actual_arglist ();
3067 74 : e4->value.function.actual->expr = e3;
3068 74 : e4->value.function.actual->next = gfc_get_actual_arglist ();
3069 74 : e4->value.function.actual->next->expr = e1;
3070 : }
3071 683 : if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK)
3072 : {
3073 : /* e1 and e3 have been stored as arguments of e4, avoid sharing. */
3074 283 : e1 = gfc_copy_expr (e1);
3075 283 : e3 = gfc_copy_expr (e3);
3076 283 : t = gfc_resolve_expr (e4);
3077 283 : gcc_assert (t);
3078 : }
3079 :
3080 : /* Create the init statement list. */
3081 683 : pushlevel ();
3082 683 : if (e2)
3083 617 : stmt = gfc_trans_assignment (e1, e2, false, false);
3084 : else
3085 66 : stmt = gfc_trans_call (n->u2.udr->initializer, false,
3086 : NULL_TREE, NULL_TREE, false);
3087 683 : if (TREE_CODE (stmt) != BIND_EXPR)
3088 196 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
3089 : else
3090 487 : poplevel (0, 0);
3091 683 : OMP_CLAUSE_REDUCTION_INIT (c) = stmt;
3092 :
3093 : /* Create the merge statement list. */
3094 683 : pushlevel ();
3095 683 : if (e4)
3096 617 : stmt = gfc_trans_assignment (e3, e4, false, true);
3097 : else
3098 66 : stmt = gfc_trans_call (n->u2.udr->combiner, false,
3099 : NULL_TREE, NULL_TREE, false);
3100 683 : if (TREE_CODE (stmt) != BIND_EXPR)
3101 233 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
3102 : else
3103 450 : poplevel (0, 0);
3104 683 : OMP_CLAUSE_REDUCTION_MERGE (c) = stmt;
3105 :
3106 : /* And stick the placeholder VAR_DECL into the clause as well. */
3107 683 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = outer_decl;
3108 :
3109 683 : gfc_current_locus = old_loc;
3110 :
3111 683 : gfc_free_expr (e1);
3112 683 : if (e2)
3113 617 : gfc_free_expr (e2);
3114 683 : gfc_free_expr (e3);
3115 683 : if (e4)
3116 617 : gfc_free_expr (e4);
3117 683 : free (symtree1);
3118 683 : free (symtree2);
3119 683 : free (symtree3);
3120 683 : free (symtree4);
3121 683 : if (outer_sym.as)
3122 426 : gfc_free_array_spec (outer_sym.as);
3123 :
3124 683 : if (udr)
3125 : {
3126 400 : *udr->omp_out = omp_var_copy[0];
3127 400 : *udr->omp_in = omp_var_copy[1];
3128 400 : if (udr->initializer_ns)
3129 : {
3130 270 : *udr->omp_priv = omp_var_copy[2];
3131 270 : *udr->omp_orig = omp_var_copy[3];
3132 : }
3133 : }
3134 683 : }
3135 :
3136 : static tree
3137 3847 : gfc_trans_omp_reduction_list (int kind, gfc_omp_namelist *namelist, tree list,
3138 : locus where, bool mark_addressable)
3139 : {
3140 3847 : omp_clause_code clause = OMP_CLAUSE_REDUCTION;
3141 3847 : switch (kind)
3142 : {
3143 : case OMP_LIST_REDUCTION:
3144 : case OMP_LIST_REDUCTION_INSCAN:
3145 : case OMP_LIST_REDUCTION_TASK:
3146 : break;
3147 : case OMP_LIST_IN_REDUCTION:
3148 : clause = OMP_CLAUSE_IN_REDUCTION;
3149 : break;
3150 : case OMP_LIST_TASK_REDUCTION:
3151 : clause = OMP_CLAUSE_TASK_REDUCTION;
3152 : break;
3153 0 : default:
3154 0 : gcc_unreachable ();
3155 : }
3156 8638 : for (; namelist != NULL; namelist = namelist->next)
3157 4791 : if (namelist->sym->attr.referenced)
3158 : {
3159 4791 : tree t = gfc_trans_omp_variable (namelist->sym, false);
3160 4791 : if (t != error_mark_node)
3161 : {
3162 4791 : tree node = build_omp_clause (gfc_get_location (&namelist->where),
3163 : clause);
3164 4791 : OMP_CLAUSE_DECL (node) = t;
3165 4791 : if (mark_addressable)
3166 38 : TREE_ADDRESSABLE (t) = 1;
3167 4791 : if (kind == OMP_LIST_REDUCTION_INSCAN)
3168 20 : OMP_CLAUSE_REDUCTION_INSCAN (node) = 1;
3169 4791 : if (kind == OMP_LIST_REDUCTION_TASK)
3170 91 : OMP_CLAUSE_REDUCTION_TASK (node) = 1;
3171 4791 : switch (namelist->u.reduction_op)
3172 : {
3173 2344 : case OMP_REDUCTION_PLUS:
3174 2344 : OMP_CLAUSE_REDUCTION_CODE (node) = PLUS_EXPR;
3175 2344 : break;
3176 198 : case OMP_REDUCTION_MINUS:
3177 198 : OMP_CLAUSE_REDUCTION_CODE (node) = MINUS_EXPR;
3178 198 : break;
3179 254 : case OMP_REDUCTION_TIMES:
3180 254 : OMP_CLAUSE_REDUCTION_CODE (node) = MULT_EXPR;
3181 254 : break;
3182 92 : case OMP_REDUCTION_AND:
3183 92 : OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ANDIF_EXPR;
3184 92 : break;
3185 785 : case OMP_REDUCTION_OR:
3186 785 : OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ORIF_EXPR;
3187 785 : break;
3188 86 : case OMP_REDUCTION_EQV:
3189 86 : OMP_CLAUSE_REDUCTION_CODE (node) = EQ_EXPR;
3190 86 : break;
3191 86 : case OMP_REDUCTION_NEQV:
3192 86 : OMP_CLAUSE_REDUCTION_CODE (node) = NE_EXPR;
3193 86 : break;
3194 218 : case OMP_REDUCTION_MAX:
3195 218 : OMP_CLAUSE_REDUCTION_CODE (node) = MAX_EXPR;
3196 218 : break;
3197 201 : case OMP_REDUCTION_MIN:
3198 201 : OMP_CLAUSE_REDUCTION_CODE (node) = MIN_EXPR;
3199 201 : break;
3200 40 : case OMP_REDUCTION_IAND:
3201 40 : OMP_CLAUSE_REDUCTION_CODE (node) = BIT_AND_EXPR;
3202 40 : break;
3203 49 : case OMP_REDUCTION_IOR:
3204 49 : OMP_CLAUSE_REDUCTION_CODE (node) = BIT_IOR_EXPR;
3205 49 : break;
3206 38 : case OMP_REDUCTION_IEOR:
3207 38 : OMP_CLAUSE_REDUCTION_CODE (node) = BIT_XOR_EXPR;
3208 38 : break;
3209 400 : case OMP_REDUCTION_USER:
3210 400 : OMP_CLAUSE_REDUCTION_CODE (node) = ERROR_MARK;
3211 400 : break;
3212 0 : default:
3213 0 : gcc_unreachable ();
3214 : }
3215 4791 : if (namelist->sym->attr.dimension
3216 4365 : || namelist->u.reduction_op == OMP_REDUCTION_USER
3217 4121 : || namelist->sym->attr.allocatable)
3218 683 : gfc_trans_omp_array_reduction_or_udr (node, namelist, where);
3219 4791 : list = gfc_trans_add_clause (node, list);
3220 : }
3221 : }
3222 3847 : return list;
3223 : }
3224 :
3225 : static inline tree
3226 3398 : gfc_convert_expr_to_tree (stmtblock_t *block, gfc_expr *expr)
3227 : {
3228 3398 : gfc_se se;
3229 3398 : tree result;
3230 :
3231 3398 : gfc_init_se (&se, NULL );
3232 3398 : gfc_conv_expr (&se, expr);
3233 3398 : gfc_add_block_to_block (block, &se.pre);
3234 3398 : result = gfc_evaluate_now (se.expr, block);
3235 3398 : gfc_add_block_to_block (block, &se.post);
3236 :
3237 3398 : return result;
3238 : }
3239 :
3240 : static vec<tree, va_heap, vl_embed> *doacross_steps;
3241 :
3242 :
3243 : /* Translate an array section or array element. */
3244 :
3245 : static void
3246 3988 : gfc_trans_omp_array_section (stmtblock_t *block, gfc_exec_op op,
3247 : gfc_omp_namelist *n, tree decl, bool element,
3248 : bool openmp, gomp_map_kind ptr_kind, tree &node,
3249 : tree &node2, tree &node3, tree &node4)
3250 : {
3251 3988 : gfc_se se;
3252 3988 : tree ptr, ptr2;
3253 3988 : tree elemsz = NULL_TREE;
3254 :
3255 3988 : gfc_init_se (&se, NULL);
3256 3988 : if (element)
3257 : {
3258 180 : gfc_conv_expr_reference (&se, n->expr);
3259 180 : gfc_add_block_to_block (block, &se.pre);
3260 180 : ptr = se.expr;
3261 : }
3262 : else
3263 : {
3264 3808 : gfc_conv_expr_descriptor (&se, n->expr);
3265 3808 : ptr = gfc_conv_array_data (se.expr);
3266 : }
3267 3988 : if (n->expr->ts.type == BT_CHARACTER && n->expr->ts.deferred)
3268 : {
3269 0 : gcc_assert (se.string_length);
3270 0 : tree len = gfc_evaluate_now (se.string_length, block);
3271 0 : elemsz = gfc_get_char_type (n->expr->ts.kind);
3272 0 : elemsz = TYPE_SIZE_UNIT (elemsz);
3273 0 : elemsz = fold_build2 (MULT_EXPR, size_type_node,
3274 : fold_convert (size_type_node, len), elemsz);
3275 : }
3276 3988 : if (element)
3277 : {
3278 180 : if (!elemsz)
3279 180 : elemsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ptr)));
3280 180 : OMP_CLAUSE_SIZE (node) = elemsz;
3281 : }
3282 : else
3283 : {
3284 3808 : tree type = TREE_TYPE (se.expr);
3285 3808 : gfc_add_block_to_block (block, &se.pre);
3286 3808 : OMP_CLAUSE_SIZE (node) = gfc_full_array_size (block, se.expr,
3287 3808 : GFC_TYPE_ARRAY_RANK (type));
3288 3808 : if (!elemsz)
3289 3808 : elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
3290 3808 : elemsz = fold_convert (gfc_array_index_type, elemsz);
3291 3808 : OMP_CLAUSE_SIZE (node) = fold_build2 (MULT_EXPR, gfc_array_index_type,
3292 : OMP_CLAUSE_SIZE (node), elemsz);
3293 3808 : if (n->expr->ts.type == BT_DERIVED
3294 21 : && n->expr->ts.u.derived->attr.alloc_comp)
3295 : {
3296 : /* Save array descriptor for use in gfc_omp_deep_mapping{,_p,_cnt};
3297 : force evaluate to ensure that it is not gimplified + is a decl. */
3298 15 : tree tmp = OMP_CLAUSE_SIZE (node);
3299 15 : tree var = gfc_create_var (TREE_TYPE (tmp), NULL);
3300 15 : gfc_add_modify_loc (input_location, block, var, tmp);
3301 15 : OMP_CLAUSE_SIZE (node) = var;
3302 15 : gfc_allocate_lang_decl (var);
3303 15 : GFC_DECL_SAVED_DESCRIPTOR (var) = se.expr;
3304 : }
3305 : }
3306 3988 : gcc_assert (se.post.head == NULL_TREE);
3307 3988 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
3308 3988 : OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
3309 3988 : ptr = fold_convert (ptrdiff_type_node, ptr);
3310 :
3311 7714 : if (POINTER_TYPE_P (TREE_TYPE (decl))
3312 340 : && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
3313 78 : && ptr_kind == GOMP_MAP_POINTER
3314 78 : && op != EXEC_OMP_TARGET_EXIT_DATA
3315 78 : && OMP_CLAUSE_MAP_KIND (node) != GOMP_MAP_RELEASE
3316 4066 : && OMP_CLAUSE_MAP_KIND (node) != GOMP_MAP_DELETE)
3317 :
3318 : {
3319 78 : node4 = build_omp_clause (input_location,
3320 : OMP_CLAUSE_MAP);
3321 78 : OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER);
3322 78 : OMP_CLAUSE_DECL (node4) = decl;
3323 78 : OMP_CLAUSE_SIZE (node4) = size_int (0);
3324 78 : decl = build_fold_indirect_ref (decl);
3325 : }
3326 3910 : else if (ptr_kind == GOMP_MAP_ALWAYS_POINTER
3327 0 : && n->expr->ts.type == BT_CHARACTER
3328 0 : && n->expr->ts.deferred)
3329 : {
3330 0 : gomp_map_kind map_kind;
3331 0 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DELETE)
3332 0 : map_kind = OMP_CLAUSE_MAP_KIND (node);
3333 0 : else if (op == EXEC_OMP_TARGET_EXIT_DATA
3334 0 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_RELEASE)
3335 : map_kind = GOMP_MAP_RELEASE;
3336 : else
3337 : map_kind = GOMP_MAP_TO;
3338 0 : gcc_assert (se.string_length);
3339 0 : node4 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
3340 0 : OMP_CLAUSE_SET_MAP_KIND (node4, map_kind);
3341 0 : OMP_CLAUSE_DECL (node4) = se.string_length;
3342 0 : OMP_CLAUSE_SIZE (node4) = TYPE_SIZE_UNIT (gfc_charlen_type_node);
3343 : }
3344 3988 : if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
3345 : {
3346 2715 : tree type = TREE_TYPE (decl);
3347 2715 : ptr2 = gfc_conv_descriptor_data_get (decl);
3348 2715 : node2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
3349 2715 : OMP_CLAUSE_DECL (node2) = decl;
3350 2715 : OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
3351 2715 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DELETE
3352 2714 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_RELEASE
3353 2505 : || op == EXEC_OMP_TARGET_EXIT_DATA
3354 5220 : || op == EXEC_OACC_EXIT_DATA)
3355 : {
3356 392 : gomp_map_kind map_kind
3357 392 : = OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DELETE ? GOMP_MAP_DELETE
3358 391 : : GOMP_MAP_RELEASE;
3359 392 : OMP_CLAUSE_SET_MAP_KIND (node2, map_kind);
3360 392 : OMP_CLAUSE_RELEASE_DESCRIPTOR (node2) = 1;
3361 : }
3362 : else
3363 2323 : OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
3364 2715 : node3 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
3365 2715 : OMP_CLAUSE_SET_MAP_KIND (node3, ptr_kind);
3366 2715 : OMP_CLAUSE_DECL (node3) = gfc_conv_descriptor_data_get (decl);
3367 : /* This purposely does not include GOMP_MAP_ALWAYS_POINTER. The extra
3368 : cast prevents gimplify.cc from recognising it as being part of the
3369 : struct - and adding an 'alloc: for the 'desc.data' pointer, which
3370 : would break as the 'desc' (the descriptor) is also mapped
3371 : (see node4 above). */
3372 2715 : if (ptr_kind == GOMP_MAP_ATTACH_DETACH && !openmp)
3373 141 : STRIP_NOPS (OMP_CLAUSE_DECL (node3));
3374 : }
3375 : else
3376 : {
3377 1273 : if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
3378 : {
3379 1011 : tree offset;
3380 1011 : ptr2 = build_fold_addr_expr (decl);
3381 1011 : offset = fold_build2 (MINUS_EXPR, ptrdiff_type_node, ptr,
3382 : fold_convert (ptrdiff_type_node, ptr2));
3383 1011 : offset = build2 (TRUNC_DIV_EXPR, ptrdiff_type_node,
3384 : offset, fold_convert (ptrdiff_type_node, elemsz));
3385 1011 : offset = build4_loc (input_location, ARRAY_REF,
3386 1011 : TREE_TYPE (TREE_TYPE (decl)),
3387 : decl, offset, NULL_TREE, NULL_TREE);
3388 1011 : OMP_CLAUSE_DECL (node) = offset;
3389 :
3390 1011 : if (ptr_kind == GOMP_MAP_ATTACH_DETACH && openmp)
3391 145 : return;
3392 : }
3393 : else
3394 : {
3395 262 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl)));
3396 : ptr2 = decl;
3397 : }
3398 1128 : node3 = build_omp_clause (input_location,
3399 : OMP_CLAUSE_MAP);
3400 1128 : OMP_CLAUSE_SET_MAP_KIND (node3, ptr_kind);
3401 1128 : OMP_CLAUSE_DECL (node3) = decl;
3402 : }
3403 3843 : ptr2 = fold_convert (ptrdiff_type_node, ptr2);
3404 3843 : OMP_CLAUSE_SIZE (node3) = fold_build2 (MINUS_EXPR, ptrdiff_type_node,
3405 : ptr, ptr2);
3406 : }
3407 :
3408 : static tree
3409 43 : handle_iterator (gfc_namespace *ns, stmtblock_t *iter_block, tree block)
3410 : {
3411 43 : tree list = NULL_TREE;
3412 88 : for (gfc_symbol *sym = ns->omp_affinity_iterators; sym; sym = sym->tlink)
3413 : {
3414 45 : gfc_constructor *c;
3415 45 : gfc_se se;
3416 :
3417 45 : tree last = make_tree_vec (6);
3418 45 : tree iter_var = gfc_get_symbol_decl (sym);
3419 45 : tree type = TREE_TYPE (iter_var);
3420 45 : TREE_VEC_ELT (last, 0) = iter_var;
3421 45 : DECL_CHAIN (iter_var) = BLOCK_VARS (block);
3422 45 : BLOCK_VARS (block) = iter_var;
3423 :
3424 : /* begin */
3425 45 : c = gfc_constructor_first (sym->value->value.constructor);
3426 45 : gfc_init_se (&se, NULL);
3427 45 : gfc_conv_expr (&se, c->expr);
3428 45 : gfc_add_block_to_block (iter_block, &se.pre);
3429 45 : gfc_add_block_to_block (iter_block, &se.post);
3430 45 : TREE_VEC_ELT (last, 1) = fold_convert (type,
3431 : gfc_evaluate_now (se.expr,
3432 : iter_block));
3433 : /* end */
3434 45 : c = gfc_constructor_next (c);
3435 45 : gfc_init_se (&se, NULL);
3436 45 : gfc_conv_expr (&se, c->expr);
3437 45 : gfc_add_block_to_block (iter_block, &se.pre);
3438 45 : gfc_add_block_to_block (iter_block, &se.post);
3439 45 : TREE_VEC_ELT (last, 2) = fold_convert (type,
3440 : gfc_evaluate_now (se.expr,
3441 : iter_block));
3442 : /* step */
3443 45 : c = gfc_constructor_next (c);
3444 45 : tree step;
3445 45 : if (c)
3446 : {
3447 5 : gfc_init_se (&se, NULL);
3448 5 : gfc_conv_expr (&se, c->expr);
3449 5 : gfc_add_block_to_block (iter_block, &se.pre);
3450 5 : gfc_add_block_to_block (iter_block, &se.post);
3451 5 : gfc_conv_expr (&se, c->expr);
3452 5 : step = fold_convert (type,
3453 : gfc_evaluate_now (se.expr,
3454 : iter_block));
3455 : }
3456 : else
3457 40 : step = build_int_cst (type, 1);
3458 45 : TREE_VEC_ELT (last, 3) = step;
3459 : /* orig_step */
3460 45 : TREE_VEC_ELT (last, 4) = save_expr (step);
3461 45 : TREE_CHAIN (last) = list;
3462 45 : list = last;
3463 : }
3464 43 : return list;
3465 : }
3466 :
3467 : /* To alleviate quadratic behaviour in checking each entry of a
3468 : gfc_omp_namelist against every other entry, we build a hashtable indexed by
3469 : gfc_symbol pointer, which we can use in the usual case that a map
3470 : expression has a symbol as its root term. Return a namelist based on the
3471 : root symbol used by N, building a new table in SYM_ROOTED_NL using the
3472 : gfc_omp_namelist N2 (all clauses) if we haven't done so already. */
3473 :
3474 : static gfc_omp_namelist *
3475 934 : get_symbol_rooted_namelist (hash_map<gfc_symbol *,
3476 : gfc_omp_namelist *> *&sym_rooted_nl,
3477 : gfc_omp_namelist *n,
3478 : gfc_omp_namelist *n2, bool *sym_based)
3479 : {
3480 : /* Early-out if we have a NULL clause list (e.g. for OpenACC). */
3481 934 : if (!n2)
3482 : return NULL;
3483 :
3484 897 : gfc_symbol *use_sym = NULL;
3485 :
3486 : /* We're only interested in cases where we have an expression, e.g. a
3487 : component access. */
3488 897 : if (n->expr && n->expr->expr_type == EXPR_VARIABLE && n->expr->symtree)
3489 897 : use_sym = n->expr->symtree->n.sym;
3490 :
3491 897 : *sym_based = false;
3492 :
3493 897 : if (!use_sym)
3494 : return n2;
3495 :
3496 897 : if (!sym_rooted_nl)
3497 : {
3498 388 : sym_rooted_nl = new hash_map<gfc_symbol *, gfc_omp_namelist *> ();
3499 :
3500 1715 : for (; n2 != NULL; n2 = n2->next)
3501 : {
3502 1327 : if (!n2->expr
3503 1326 : || n2->expr->expr_type != EXPR_VARIABLE
3504 1326 : || !n2->expr->symtree)
3505 1 : continue;
3506 :
3507 1326 : gfc_omp_namelist *nl_copy = gfc_get_omp_namelist ();
3508 1326 : memcpy (nl_copy, n2, sizeof *nl_copy);
3509 1326 : nl_copy->u2.duplicate_of = n2;
3510 1326 : nl_copy->next = NULL;
3511 :
3512 1326 : gfc_symbol *idx_sym = n2->expr->symtree->n.sym;
3513 :
3514 1326 : bool existed;
3515 1326 : gfc_omp_namelist *&entry
3516 1326 : = sym_rooted_nl->get_or_insert (idx_sym, &existed);
3517 1326 : if (existed)
3518 881 : nl_copy->next = entry;
3519 1326 : entry = nl_copy;
3520 : }
3521 : }
3522 :
3523 897 : gfc_omp_namelist **n2_sym = sym_rooted_nl->get (use_sym);
3524 :
3525 897 : if (n2_sym)
3526 : {
3527 897 : *sym_based = true;
3528 897 : return *n2_sym;
3529 : }
3530 :
3531 : return NULL;
3532 : }
3533 :
3534 : /* Helper function for gfc_trans_omp_clauses. Adjust existing and create new
3535 : map nodes for derived-type component array descriptors. Return true if the
3536 : mapping has to be dropped. */
3537 :
3538 : static bool
3539 1191 : gfc_map_array_descriptor (
3540 : tree &node, tree &node2, tree &node3, tree &node4, tree descr, bool openacc,
3541 : location_t map_loc, stmtblock_t *block, gfc_exec_op op, gfc_omp_namelist *n,
3542 : hash_map<gfc_symbol *, gfc_omp_namelist *> *&sym_rooted_nl, gfc_se se,
3543 : gfc_omp_clauses *clauses, bool mid_desc_p)
3544 : {
3545 1191 : tree type = TREE_TYPE (descr);
3546 1191 : tree ptr = gfc_conv_descriptor_data_get (descr);
3547 1191 : ptr = build_fold_indirect_ref (ptr);
3548 1191 : OMP_CLAUSE_DECL (node) = ptr;
3549 1191 : int rank = GFC_TYPE_ARRAY_RANK (type);
3550 1191 : OMP_CLAUSE_SIZE (node) = gfc_full_array_size (block, descr, rank);
3551 1191 : tree elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
3552 :
3553 1191 : gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (node);
3554 1191 : if (GOMP_MAP_COPY_TO_P (map_kind) || map_kind == GOMP_MAP_ALLOC)
3555 : {
3556 842 : if (mid_desc_p)
3557 : {
3558 : /* For an intermediate descriptor, the pointee (i.e. the actual array
3559 : content) is mapped in a separate set of nodes. This ALLOC is only
3560 : emitted to comply with the group layout expected by the gimplifier.
3561 : */
3562 89 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALLOC);
3563 89 : OMP_CLAUSE_SIZE (node) = size_zero_node;
3564 89 : OMP_CLAUSE_MAP_GIMPLE_ONLY (node) = 1;
3565 : }
3566 : else
3567 753 : map_kind
3568 1250 : = ((GOMP_MAP_ALWAYS_P (map_kind) || gfc_expr_attr (n->expr).pointer)
3569 753 : ? GOMP_MAP_ALWAYS_TO
3570 : : GOMP_MAP_TO);
3571 : }
3572 349 : else if (n->u.map.op == OMP_MAP_RELEASE || n->u.map.op == OMP_MAP_DELETE)
3573 : ;
3574 344 : else if (op == EXEC_OMP_TARGET_EXIT_DATA || op == EXEC_OACC_EXIT_DATA)
3575 : map_kind = GOMP_MAP_RELEASE;
3576 31 : else if (mid_desc_p)
3577 : {
3578 : /* For an intermediate descriptor, the pointee (i.e. the actual array
3579 : content) is mapped in a separate set of nodes. This ALLOC is only
3580 : emitted to comply with the group layout expected by the gimplifier. */
3581 1 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALLOC);
3582 1 : OMP_CLAUSE_SIZE (node) = size_zero_node;
3583 1 : OMP_CLAUSE_MAP_GIMPLE_ONLY (node) = 1;
3584 : }
3585 : else
3586 : map_kind = GOMP_MAP_ALLOC;
3587 :
3588 1191 : if (!openacc && n->expr->ts.type == BT_CHARACTER && n->expr->ts.deferred)
3589 : {
3590 42 : gcc_assert (se.string_length);
3591 42 : tree len = fold_convert (size_type_node, se.string_length);
3592 42 : elemsz = gfc_get_char_type (n->expr->ts.kind);
3593 42 : elemsz = TYPE_SIZE_UNIT (elemsz);
3594 42 : elemsz = fold_build2 (MULT_EXPR, size_type_node, len, elemsz);
3595 42 : node4 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
3596 42 : OMP_CLAUSE_SET_MAP_KIND (node4, map_kind);
3597 42 : OMP_CLAUSE_DECL (node4) = se.string_length;
3598 42 : OMP_CLAUSE_SIZE (node4) = TYPE_SIZE_UNIT (gfc_charlen_type_node);
3599 : }
3600 1191 : elemsz = fold_convert (gfc_array_index_type, elemsz);
3601 1191 : OMP_CLAUSE_SIZE (node) = fold_build2 (MULT_EXPR, gfc_array_index_type,
3602 : OMP_CLAUSE_SIZE (node), elemsz);
3603 :
3604 1191 : node2 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
3605 1191 : if (map_kind == GOMP_MAP_RELEASE || map_kind == GOMP_MAP_DELETE)
3606 : {
3607 318 : OMP_CLAUSE_SET_MAP_KIND (node2, map_kind);
3608 318 : OMP_CLAUSE_RELEASE_DESCRIPTOR (node2) = 1;
3609 : }
3610 : else
3611 873 : OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
3612 1191 : OMP_CLAUSE_DECL (node2) = descr;
3613 1191 : OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
3614 :
3615 1191 : if (!openacc)
3616 : {
3617 1051 : if (n->expr->ts.type == BT_DERIVED
3618 18 : && n->expr->ts.u.derived->attr.alloc_comp)
3619 : {
3620 : /* Save array descriptor for use
3621 : in gfc_omp_deep_mapping{,_p,_cnt}; force
3622 : evaluate to ensure that it is
3623 : not gimplified + is a decl. */
3624 12 : tree tmp = OMP_CLAUSE_SIZE (node);
3625 12 : tree var = gfc_create_var (TREE_TYPE (tmp), NULL);
3626 12 : gfc_add_modify_loc (map_loc, block, var, tmp);
3627 12 : OMP_CLAUSE_SIZE (node) = var;
3628 12 : gfc_allocate_lang_decl (var);
3629 12 : GFC_DECL_SAVED_DESCRIPTOR (var) = descr;
3630 : }
3631 :
3632 : /* If we don't have a mapping of a smaller part
3633 : of the array -- or we can't prove that we do
3634 : statically -- set this flag. If there is a
3635 : mapping of a smaller part of the array after
3636 : all, this will turn into a no-op at
3637 : runtime. */
3638 1051 : OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (node) = 1;
3639 :
3640 1051 : bool drop_mapping = false;
3641 :
3642 1051 : if (!mid_desc_p)
3643 : {
3644 879 : gfc_omp_namelist *n2 = clauses->lists[OMP_LIST_MAP];
3645 :
3646 879 : bool sym_based;
3647 879 : n2 = get_symbol_rooted_namelist (sym_rooted_nl, n, n2, &sym_based);
3648 :
3649 3179 : for (; n2 != NULL; n2 = n2->next)
3650 : {
3651 2586 : if ((!sym_based && n == n2)
3652 2586 : || (sym_based && n == n2->u2.duplicate_of) || !n2->expr)
3653 617 : continue;
3654 :
3655 1969 : if (!gfc_omp_expr_prefix_same (n->expr, n2->expr))
3656 1683 : continue;
3657 :
3658 286 : gfc_ref *ref1 = n->expr->ref;
3659 286 : gfc_ref *ref2 = n2->expr->ref;
3660 :
3661 : /* We know ref1 and ref2 overlap. We're
3662 : interested in whether ref2 describes a
3663 : smaller part of the array than ref1, which
3664 : we already know refers to the full
3665 : array. */
3666 :
3667 644 : while (ref1->next && ref2->next)
3668 : {
3669 : ref1 = ref1->next;
3670 : ref2 = ref2->next;
3671 : }
3672 :
3673 286 : if (ref2->next
3674 286 : || (ref2->type == REF_ARRAY
3675 286 : && (ref2->u.ar.type == AR_ELEMENT
3676 286 : || (ref2->u.ar.type == AR_SECTION))))
3677 : {
3678 : drop_mapping = true;
3679 : break;
3680 : }
3681 : }
3682 879 : if (drop_mapping)
3683 286 : return true;
3684 : }
3685 : }
3686 :
3687 905 : if (mid_desc_p && GOMP_MAP_COPY_FROM_P (OMP_CLAUSE_MAP_KIND (node)))
3688 82 : node = NULL_TREE;
3689 :
3690 905 : node3 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
3691 905 : OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_ATTACH_DETACH);
3692 905 : OMP_CLAUSE_DECL (node3) = gfc_conv_descriptor_data_get (descr);
3693 : /* Similar to gfc_trans_omp_array_section (details
3694 : there), we add/keep the cast for OpenMP to prevent
3695 : that an 'alloc:' gets added for node3 ('desc.data')
3696 : as that is part of the whole descriptor (node3).
3697 : TODO: Remove once the ME handles this properly. */
3698 905 : if (!openacc)
3699 765 : OMP_CLAUSE_DECL (node3) = fold_convert (TREE_TYPE (TREE_OPERAND (ptr, 0)),
3700 : OMP_CLAUSE_DECL (node3));
3701 : else
3702 140 : STRIP_NOPS (OMP_CLAUSE_DECL (node3));
3703 905 : OMP_CLAUSE_SIZE (node3) = size_zero_node;
3704 905 : if (mid_desc_p)
3705 172 : OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (node3) = 1;
3706 :
3707 : return false;
3708 : }
3709 :
3710 : static tree
3711 31712 : gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
3712 : locus where, bool declare_simd = false,
3713 : bool openacc = false, gfc_exec_op op = EXEC_NOP)
3714 : {
3715 31712 : tree omp_clauses = NULL_TREE, prev_clauses, chunk_size, c;
3716 31712 : tree iterator = NULL_TREE;
3717 31712 : tree tree_block = NULL_TREE;
3718 31712 : stmtblock_t iter_block;
3719 31712 : int list, ifc;
3720 31712 : enum omp_clause_code clause_code;
3721 31712 : gfc_omp_namelist *prev = NULL;
3722 31712 : gfc_se se;
3723 31712 : vec<gfc_symbol *> descriptors = vNULL;
3724 :
3725 31712 : if (clauses == NULL)
3726 : return NULL_TREE;
3727 :
3728 31700 : hash_map<gfc_symbol *, gfc_omp_namelist *> *sym_rooted_nl = NULL;
3729 :
3730 1268000 : for (list = 0; list < OMP_LIST_NUM; list++)
3731 : {
3732 1236300 : gfc_omp_namelist *n = clauses->lists[list];
3733 :
3734 1236300 : if (n == NULL)
3735 1208512 : continue;
3736 27788 : switch (list)
3737 : {
3738 3847 : case OMP_LIST_REDUCTION:
3739 3847 : case OMP_LIST_REDUCTION_INSCAN:
3740 3847 : case OMP_LIST_REDUCTION_TASK:
3741 3847 : case OMP_LIST_IN_REDUCTION:
3742 3847 : case OMP_LIST_TASK_REDUCTION:
3743 : /* An OpenACC async clause indicates the need to set reduction
3744 : arguments addressable, to allow asynchronous copy-out. */
3745 3847 : omp_clauses = gfc_trans_omp_reduction_list (list, n, omp_clauses,
3746 3847 : where, clauses->async);
3747 3847 : break;
3748 6472 : case OMP_LIST_PRIVATE:
3749 6472 : clause_code = OMP_CLAUSE_PRIVATE;
3750 6472 : goto add_clause;
3751 1067 : case OMP_LIST_SHARED:
3752 1067 : clause_code = OMP_CLAUSE_SHARED;
3753 1067 : goto add_clause;
3754 1066 : case OMP_LIST_FIRSTPRIVATE:
3755 1066 : clause_code = OMP_CLAUSE_FIRSTPRIVATE;
3756 1066 : goto add_clause;
3757 1661 : case OMP_LIST_LASTPRIVATE:
3758 1661 : clause_code = OMP_CLAUSE_LASTPRIVATE;
3759 1661 : goto add_clause;
3760 96 : case OMP_LIST_COPYIN:
3761 96 : clause_code = OMP_CLAUSE_COPYIN;
3762 96 : goto add_clause;
3763 74 : case OMP_LIST_COPYPRIVATE:
3764 74 : clause_code = OMP_CLAUSE_COPYPRIVATE;
3765 74 : goto add_clause;
3766 61 : case OMP_LIST_UNIFORM:
3767 61 : clause_code = OMP_CLAUSE_UNIFORM;
3768 61 : goto add_clause;
3769 51 : case OMP_LIST_USE_DEVICE:
3770 51 : case OMP_LIST_USE_DEVICE_PTR:
3771 51 : clause_code = OMP_CLAUSE_USE_DEVICE_PTR;
3772 51 : goto add_clause;
3773 922 : case OMP_LIST_USE_DEVICE_ADDR:
3774 922 : clause_code = OMP_CLAUSE_USE_DEVICE_ADDR;
3775 922 : goto add_clause;
3776 43 : case OMP_LIST_IS_DEVICE_PTR:
3777 43 : clause_code = OMP_CLAUSE_IS_DEVICE_PTR;
3778 43 : goto add_clause;
3779 112 : case OMP_LIST_HAS_DEVICE_ADDR:
3780 112 : clause_code = OMP_CLAUSE_HAS_DEVICE_ADDR;
3781 112 : goto add_clause;
3782 2 : case OMP_LIST_NONTEMPORAL:
3783 2 : clause_code = OMP_CLAUSE_NONTEMPORAL;
3784 2 : goto add_clause;
3785 9 : case OMP_LIST_SCAN_IN:
3786 9 : clause_code = OMP_CLAUSE_INCLUSIVE;
3787 9 : goto add_clause;
3788 7 : case OMP_LIST_SCAN_EX:
3789 7 : clause_code = OMP_CLAUSE_EXCLUSIVE;
3790 7 : goto add_clause;
3791 4 : case OMP_LIST_USE:
3792 4 : clause_code = OMP_CLAUSE_USE;
3793 4 : goto add_clause;
3794 55 : case OMP_LIST_INTEROP:
3795 55 : clause_code = OMP_CLAUSE_INTEROP;
3796 55 : goto add_clause;
3797 :
3798 11702 : add_clause:
3799 11702 : omp_clauses
3800 11702 : = gfc_trans_omp_variable_list (clause_code, n, omp_clauses,
3801 : declare_simd);
3802 11702 : break;
3803 :
3804 : case OMP_LIST_DESTROY:
3805 12 : for (; n != NULL; n = n->next)
3806 9 : if (n->sym->attr.referenced)
3807 : {
3808 9 : tree t = gfc_trans_omp_variable (n->sym, declare_simd);
3809 9 : if (t != error_mark_node)
3810 : {
3811 9 : tree node
3812 9 : = build_omp_clause (input_location, OMP_CLAUSE_DESTROY);
3813 9 : OMP_CLAUSE_DECL (node) = t;
3814 9 : TREE_ADDRESSABLE (OMP_CLAUSE_DECL (node)) = 1;
3815 9 : omp_clauses = gfc_trans_add_clause (node, omp_clauses);
3816 : }
3817 : }
3818 : break;
3819 :
3820 : case OMP_LIST_INIT:
3821 : {
3822 : tree pref_type = NULL_TREE;
3823 : const char *last = NULL;
3824 32 : for (; n != NULL; n = n->next)
3825 26 : if (n->sym->attr.referenced)
3826 : {
3827 26 : tree t = gfc_trans_omp_variable (n->sym, false);
3828 26 : if (t == error_mark_node)
3829 0 : continue;
3830 26 : tree node = build_omp_clause (input_location,
3831 : OMP_CLAUSE_INIT);
3832 26 : OMP_CLAUSE_DECL (node) = t;
3833 26 : TREE_ADDRESSABLE (OMP_CLAUSE_DECL (node)) = 1;
3834 26 : if (n->u.init.target)
3835 19 : OMP_CLAUSE_INIT_TARGET (node) = 1;
3836 26 : if (n->u.init.targetsync)
3837 10 : OMP_CLAUSE_INIT_TARGETSYNC (node) = 1;
3838 26 : if (last != n->u2.init_interop)
3839 : {
3840 6 : last = n->u2.init_interop;
3841 6 : if (n->u2.init_interop == NULL)
3842 : pref_type = NULL_TREE;
3843 : else
3844 : {
3845 5 : pref_type = build_string (n->u.init.len,
3846 : n->u2.init_interop);
3847 5 : TREE_TYPE (pref_type)
3848 10 : = build_array_type_nelts (unsigned_char_type_node,
3849 5 : n->u.init.len);
3850 : }
3851 : }
3852 26 : OMP_CLAUSE_INIT_PREFER_TYPE (node) = pref_type;
3853 26 : omp_clauses = gfc_trans_add_clause (node, omp_clauses);
3854 : }
3855 : break;
3856 : }
3857 :
3858 : case OMP_LIST_ALIGNED:
3859 256 : for (; n != NULL; n = n->next)
3860 149 : if (n->sym->attr.referenced || declare_simd)
3861 : {
3862 149 : tree t = gfc_trans_omp_variable (n->sym, declare_simd);
3863 149 : if (t != error_mark_node)
3864 : {
3865 149 : tree node = build_omp_clause (input_location,
3866 : OMP_CLAUSE_ALIGNED);
3867 149 : OMP_CLAUSE_DECL (node) = t;
3868 149 : if (n->expr)
3869 : {
3870 148 : tree alignment_var;
3871 :
3872 148 : if (declare_simd)
3873 5 : alignment_var = gfc_conv_constant_to_tree (n->expr);
3874 : else
3875 : {
3876 143 : gfc_init_se (&se, NULL);
3877 143 : gfc_conv_expr (&se, n->expr);
3878 143 : gfc_add_block_to_block (block, &se.pre);
3879 143 : alignment_var = gfc_evaluate_now (se.expr, block);
3880 143 : gfc_add_block_to_block (block, &se.post);
3881 : }
3882 148 : OMP_CLAUSE_ALIGNED_ALIGNMENT (node) = alignment_var;
3883 : }
3884 149 : omp_clauses = gfc_trans_add_clause (node, omp_clauses);
3885 : }
3886 : }
3887 : break;
3888 : case OMP_LIST_ALLOCATE:
3889 : {
3890 : tree allocator_ = NULL_TREE;
3891 : gfc_expr *alloc_expr = NULL;
3892 675 : for (; n != NULL; n = n->next)
3893 427 : if (n->sym->attr.referenced)
3894 : {
3895 427 : tree t = gfc_trans_omp_variable (n->sym, false);
3896 427 : if (t != error_mark_node)
3897 : {
3898 427 : tree node = build_omp_clause (input_location,
3899 : OMP_CLAUSE_ALLOCATE);
3900 427 : OMP_CLAUSE_DECL (node) = t;
3901 427 : if (n->u2.allocator)
3902 : {
3903 292 : if (alloc_expr != n->u2.allocator)
3904 : {
3905 168 : gfc_init_se (&se, NULL);
3906 168 : gfc_conv_expr (&se, n->u2.allocator);
3907 168 : gfc_add_block_to_block (block, &se.pre);
3908 168 : allocator_ = gfc_evaluate_now (se.expr, block);
3909 168 : gfc_add_block_to_block (block, &se.post);
3910 : }
3911 292 : OMP_CLAUSE_ALLOCATE_ALLOCATOR (node) = allocator_;
3912 : }
3913 427 : alloc_expr = n->u2.allocator;
3914 427 : if (n->u.align)
3915 : {
3916 51 : tree align_;
3917 51 : gfc_init_se (&se, NULL);
3918 51 : gfc_conv_expr (&se, n->u.align);
3919 51 : gcc_assert (CONSTANT_CLASS_P (se.expr)
3920 : && se.pre.head == NULL
3921 : && se.post.head == NULL);
3922 51 : align_ = se.expr;
3923 51 : OMP_CLAUSE_ALLOCATE_ALIGN (node) = align_;
3924 : }
3925 427 : omp_clauses = gfc_trans_add_clause (node, omp_clauses);
3926 : }
3927 : }
3928 : else
3929 0 : alloc_expr = n->u2.allocator;
3930 : }
3931 : break;
3932 : case OMP_LIST_LINEAR:
3933 : {
3934 : gfc_expr *last_step_expr = NULL;
3935 : tree last_step = NULL_TREE;
3936 : bool last_step_parm = false;
3937 :
3938 1288 : for (; n != NULL; n = n->next)
3939 : {
3940 795 : if (n->expr)
3941 : {
3942 776 : last_step_expr = n->expr;
3943 776 : last_step = NULL_TREE;
3944 776 : last_step_parm = false;
3945 : }
3946 795 : if (n->sym->attr.referenced || declare_simd)
3947 : {
3948 795 : tree t = gfc_trans_omp_variable (n->sym, declare_simd);
3949 795 : if (t != error_mark_node)
3950 : {
3951 795 : tree node = build_omp_clause (input_location,
3952 : OMP_CLAUSE_LINEAR);
3953 795 : OMP_CLAUSE_DECL (node) = t;
3954 795 : omp_clause_linear_kind kind;
3955 795 : switch (n->u.linear.op)
3956 : {
3957 : case OMP_LINEAR_DEFAULT:
3958 : kind = OMP_CLAUSE_LINEAR_DEFAULT;
3959 : break;
3960 : case OMP_LINEAR_REF:
3961 : kind = OMP_CLAUSE_LINEAR_REF;
3962 : break;
3963 : case OMP_LINEAR_VAL:
3964 : kind = OMP_CLAUSE_LINEAR_VAL;
3965 : break;
3966 : case OMP_LINEAR_UVAL:
3967 : kind = OMP_CLAUSE_LINEAR_UVAL;
3968 : break;
3969 0 : default:
3970 0 : gcc_unreachable ();
3971 : }
3972 795 : OMP_CLAUSE_LINEAR_KIND (node) = kind;
3973 795 : OMP_CLAUSE_LINEAR_OLD_LINEAR_MODIFIER (node)
3974 795 : = n->u.linear.old_modifier;
3975 795 : if (last_step_expr && last_step == NULL_TREE)
3976 : {
3977 776 : if (!declare_simd)
3978 : {
3979 695 : gfc_init_se (&se, NULL);
3980 695 : gfc_conv_expr (&se, last_step_expr);
3981 695 : gfc_add_block_to_block (block, &se.pre);
3982 695 : last_step = gfc_evaluate_now (se.expr, block);
3983 695 : gfc_add_block_to_block (block, &se.post);
3984 : }
3985 81 : else if (last_step_expr->expr_type == EXPR_VARIABLE)
3986 : {
3987 2 : gfc_symbol *s = last_step_expr->symtree->n.sym;
3988 2 : last_step = gfc_trans_omp_variable (s, true);
3989 2 : last_step_parm = true;
3990 : }
3991 : else
3992 79 : last_step
3993 79 : = gfc_conv_constant_to_tree (last_step_expr);
3994 : }
3995 795 : if (last_step_parm)
3996 : {
3997 2 : OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (node) = 1;
3998 2 : OMP_CLAUSE_LINEAR_STEP (node) = last_step;
3999 : }
4000 : else
4001 : {
4002 793 : if (kind == OMP_CLAUSE_LINEAR_REF)
4003 : {
4004 34 : tree type;
4005 34 : if (n->sym->attr.flavor == FL_PROCEDURE)
4006 : {
4007 0 : type = gfc_get_function_type (n->sym);
4008 0 : type = build_pointer_type (type);
4009 : }
4010 : else
4011 34 : type = gfc_sym_type (n->sym);
4012 34 : if (POINTER_TYPE_P (type))
4013 34 : type = TREE_TYPE (type);
4014 : /* Otherwise to be determined what exactly
4015 : should be done. */
4016 34 : tree t = fold_convert (sizetype, last_step);
4017 34 : t = size_binop (MULT_EXPR, t,
4018 : TYPE_SIZE_UNIT (type));
4019 34 : OMP_CLAUSE_LINEAR_STEP (node) = t;
4020 : }
4021 : else
4022 : {
4023 759 : tree type
4024 759 : = gfc_typenode_for_spec (&n->sym->ts);
4025 759 : OMP_CLAUSE_LINEAR_STEP (node)
4026 1518 : = fold_convert (type, last_step);
4027 : }
4028 : }
4029 795 : if (n->sym->attr.dimension || n->sym->attr.allocatable)
4030 222 : OMP_CLAUSE_LINEAR_ARRAY (node) = 1;
4031 795 : omp_clauses = gfc_trans_add_clause (node, omp_clauses);
4032 : }
4033 : }
4034 : }
4035 : }
4036 : break;
4037 : case OMP_LIST_AFFINITY:
4038 : case OMP_LIST_DEPEND:
4039 : iterator = NULL_TREE;
4040 : prev = NULL;
4041 : prev_clauses = omp_clauses;
4042 1576 : for (; n != NULL; n = n->next)
4043 : {
4044 854 : if (iterator && prev->u2.ns != n->u2.ns)
4045 : {
4046 12 : BLOCK_SUBBLOCKS (tree_block) = gfc_finish_block (&iter_block);
4047 12 : TREE_VEC_ELT (iterator, 5) = tree_block;
4048 26 : for (tree c = omp_clauses; c != prev_clauses;
4049 14 : c = OMP_CLAUSE_CHAIN (c))
4050 28 : OMP_CLAUSE_DECL (c) = build_tree_list (iterator,
4051 14 : OMP_CLAUSE_DECL (c));
4052 : prev_clauses = omp_clauses;
4053 : iterator = NULL_TREE;
4054 : }
4055 854 : if (n->u2.ns && (!prev || prev->u2.ns != n->u2.ns))
4056 : {
4057 43 : gfc_init_block (&iter_block);
4058 43 : tree_block = make_node (BLOCK);
4059 43 : TREE_USED (tree_block) = 1;
4060 43 : BLOCK_VARS (tree_block) = NULL_TREE;
4061 43 : iterator = handle_iterator (n->u2.ns, block,
4062 : tree_block);
4063 : }
4064 854 : if (!iterator)
4065 802 : gfc_init_block (&iter_block);
4066 854 : prev = n;
4067 854 : if (list == OMP_LIST_DEPEND
4068 828 : && (n->u.depend_doacross_op == OMP_DOACROSS_SINK_FIRST
4069 828 : || n->u.depend_doacross_op == OMP_DEPEND_SINK_FIRST))
4070 : {
4071 228 : tree vec = NULL_TREE;
4072 228 : unsigned int i;
4073 228 : bool is_depend
4074 : = n->u.depend_doacross_op == OMP_DEPEND_SINK_FIRST;
4075 228 : for (i = 0; ; i++)
4076 : {
4077 1219 : tree addend = integer_zero_node, t;
4078 1219 : bool neg = false;
4079 1219 : if (n->sym && n->expr)
4080 : {
4081 558 : addend = gfc_conv_constant_to_tree (n->expr);
4082 558 : if (TREE_CODE (addend) == INTEGER_CST
4083 558 : && tree_int_cst_sgn (addend) == -1)
4084 : {
4085 407 : neg = true;
4086 407 : addend = const_unop (NEGATE_EXPR,
4087 407 : TREE_TYPE (addend), addend);
4088 : }
4089 : }
4090 :
4091 1219 : if (n->sym == NULL)
4092 0 : t = null_pointer_node; /* "omp_cur_iteration - 1". */
4093 : else
4094 1219 : t = gfc_trans_omp_variable (n->sym, false);
4095 1219 : if (t != error_mark_node)
4096 : {
4097 1219 : if (i < vec_safe_length (doacross_steps)
4098 426 : && !integer_zerop (addend)
4099 630 : && (*doacross_steps)[i])
4100 : {
4101 204 : tree step = (*doacross_steps)[i];
4102 204 : addend = fold_convert (TREE_TYPE (step), addend);
4103 204 : addend = build2 (TRUNC_DIV_EXPR,
4104 204 : TREE_TYPE (step), addend, step);
4105 : }
4106 1219 : vec = tree_cons (addend, t, vec);
4107 1219 : if (neg)
4108 407 : OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1;
4109 : }
4110 1219 : if (n->next == NULL
4111 1057 : || n->next->u.depend_doacross_op != OMP_DOACROSS_SINK)
4112 : break;
4113 991 : n = n->next;
4114 991 : }
4115 228 : if (vec == NULL_TREE)
4116 0 : continue;
4117 :
4118 228 : tree node = build_omp_clause (input_location,
4119 : OMP_CLAUSE_DOACROSS);
4120 228 : OMP_CLAUSE_DOACROSS_KIND (node) = OMP_CLAUSE_DOACROSS_SINK;
4121 228 : OMP_CLAUSE_DOACROSS_DEPEND (node) = is_depend;
4122 228 : OMP_CLAUSE_DECL (node) = nreverse (vec);
4123 228 : omp_clauses = gfc_trans_add_clause (node, omp_clauses);
4124 228 : continue;
4125 228 : }
4126 :
4127 626 : if (n->sym && !n->sym->attr.referenced)
4128 0 : continue;
4129 :
4130 652 : tree node = build_omp_clause (input_location,
4131 : list == OMP_LIST_DEPEND
4132 : ? OMP_CLAUSE_DEPEND
4133 : : OMP_CLAUSE_AFFINITY);
4134 626 : if (n->sym == NULL) /* omp_all_memory */
4135 9 : OMP_CLAUSE_DECL (node) = null_pointer_node;
4136 617 : else if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
4137 : {
4138 404 : tree decl = gfc_trans_omp_variable (n->sym, false);
4139 404 : if (gfc_omp_privatize_by_reference (decl))
4140 62 : decl = build_fold_indirect_ref (decl);
4141 404 : if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
4142 : {
4143 23 : decl = gfc_conv_descriptor_data_get (decl);
4144 23 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl)));
4145 23 : decl = build_fold_indirect_ref (decl);
4146 : }
4147 381 : else if (n->sym->attr.allocatable || n->sym->attr.pointer)
4148 22 : decl = build_fold_indirect_ref (decl);
4149 359 : else if (DECL_P (decl))
4150 326 : TREE_ADDRESSABLE (decl) = 1;
4151 404 : OMP_CLAUSE_DECL (node) = decl;
4152 404 : }
4153 : else
4154 : {
4155 213 : tree ptr;
4156 213 : gfc_init_se (&se, NULL);
4157 213 : if (n->expr->ref->u.ar.type == AR_ELEMENT)
4158 : {
4159 133 : gfc_conv_expr_reference (&se, n->expr);
4160 133 : ptr = se.expr;
4161 : }
4162 : else
4163 : {
4164 80 : gfc_conv_expr_descriptor (&se, n->expr);
4165 80 : ptr = gfc_conv_array_data (se.expr);
4166 : }
4167 213 : gfc_add_block_to_block (&iter_block, &se.pre);
4168 213 : gfc_add_block_to_block (&iter_block, &se.post);
4169 213 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
4170 213 : OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
4171 : }
4172 626 : if (list == OMP_LIST_DEPEND)
4173 600 : switch (n->u.depend_doacross_op)
4174 : {
4175 227 : case OMP_DEPEND_IN:
4176 227 : OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_IN;
4177 227 : break;
4178 256 : case OMP_DEPEND_OUT:
4179 256 : OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_OUT;
4180 256 : break;
4181 55 : case OMP_DEPEND_INOUT:
4182 55 : OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_INOUT;
4183 55 : break;
4184 9 : case OMP_DEPEND_INOUTSET:
4185 9 : OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_INOUTSET;
4186 9 : break;
4187 15 : case OMP_DEPEND_MUTEXINOUTSET:
4188 15 : OMP_CLAUSE_DEPEND_KIND (node)
4189 15 : = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
4190 15 : break;
4191 38 : case OMP_DEPEND_DEPOBJ:
4192 38 : OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_DEPOBJ;
4193 38 : break;
4194 0 : default:
4195 0 : gcc_unreachable ();
4196 : }
4197 626 : if (!iterator)
4198 574 : gfc_add_block_to_block (block, &iter_block);
4199 626 : omp_clauses = gfc_trans_add_clause (node, omp_clauses);
4200 : }
4201 722 : if (iterator)
4202 : {
4203 31 : BLOCK_SUBBLOCKS (tree_block) = gfc_finish_block (&iter_block);
4204 31 : TREE_VEC_ELT (iterator, 5) = tree_block;
4205 70 : for (tree c = omp_clauses; c != prev_clauses;
4206 39 : c = OMP_CLAUSE_CHAIN (c))
4207 78 : OMP_CLAUSE_DECL (c) = build_tree_list (iterator,
4208 39 : OMP_CLAUSE_DECL (c));
4209 : }
4210 : break;
4211 : case OMP_LIST_MAP:
4212 24157 : for (; n != NULL; n = n->next)
4213 : {
4214 15289 : if (!n->sym->attr.referenced
4215 15289 : || n->sym->attr.flavor == FL_PARAMETER)
4216 295 : continue;
4217 :
4218 15280 : location_t map_loc = gfc_get_location (&n->where);
4219 15280 : bool always_modifier = false;
4220 15280 : tree node = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
4221 15280 : tree node2 = NULL_TREE;
4222 15280 : tree node3 = NULL_TREE;
4223 15280 : tree node4 = NULL_TREE;
4224 15280 : tree node5 = NULL_TREE;
4225 :
4226 : /* OpenMP: automatically map pointer targets with the pointer;
4227 : hence, always update the descriptor/pointer itself. */
4228 15280 : if (!openacc
4229 15280 : && ((n->expr == NULL && n->sym->attr.pointer)
4230 14492 : || (n->expr && gfc_expr_attr (n->expr).pointer)))
4231 1393 : always_modifier = true;
4232 :
4233 15280 : if (n->u.map.readonly)
4234 22 : OMP_CLAUSE_MAP_READONLY (node) = 1;
4235 :
4236 15280 : switch (n->u.map.op)
4237 : {
4238 1079 : case OMP_MAP_ALLOC:
4239 1079 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALLOC);
4240 1079 : break;
4241 64 : case OMP_MAP_IF_PRESENT:
4242 64 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_IF_PRESENT);
4243 64 : break;
4244 62 : case OMP_MAP_ATTACH:
4245 62 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ATTACH);
4246 62 : break;
4247 4236 : case OMP_MAP_TO:
4248 4236 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TO);
4249 4236 : break;
4250 3039 : case OMP_MAP_FROM:
4251 3039 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FROM);
4252 3039 : break;
4253 4357 : case OMP_MAP_TOFROM:
4254 4357 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TOFROM);
4255 4357 : break;
4256 32 : case OMP_MAP_ALWAYS_TO:
4257 32 : always_modifier = true;
4258 32 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TO);
4259 32 : break;
4260 14 : case OMP_MAP_ALWAYS_FROM:
4261 14 : always_modifier = true;
4262 14 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_FROM);
4263 14 : break;
4264 171 : case OMP_MAP_ALWAYS_TOFROM:
4265 171 : always_modifier = true;
4266 171 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TOFROM);
4267 171 : break;
4268 8 : case OMP_MAP_PRESENT_ALLOC:
4269 8 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_PRESENT_ALLOC);
4270 8 : break;
4271 13 : case OMP_MAP_PRESENT_TO:
4272 13 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_PRESENT_TO);
4273 13 : break;
4274 4 : case OMP_MAP_PRESENT_FROM:
4275 4 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_PRESENT_FROM);
4276 4 : break;
4277 2 : case OMP_MAP_PRESENT_TOFROM:
4278 2 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_PRESENT_TOFROM);
4279 2 : break;
4280 10 : case OMP_MAP_ALWAYS_PRESENT_TO:
4281 10 : always_modifier = true;
4282 10 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_PRESENT_TO);
4283 10 : break;
4284 4 : case OMP_MAP_ALWAYS_PRESENT_FROM:
4285 4 : always_modifier = true;
4286 4 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_PRESENT_FROM);
4287 4 : break;
4288 2 : case OMP_MAP_ALWAYS_PRESENT_TOFROM:
4289 2 : always_modifier = true;
4290 2 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_PRESENT_TOFROM);
4291 2 : break;
4292 426 : case OMP_MAP_RELEASE:
4293 426 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_RELEASE);
4294 426 : break;
4295 56 : case OMP_MAP_DELETE:
4296 56 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_DELETE);
4297 56 : break;
4298 40 : case OMP_MAP_DETACH:
4299 40 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_DETACH);
4300 40 : break;
4301 64 : case OMP_MAP_FORCE_ALLOC:
4302 64 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_ALLOC);
4303 64 : break;
4304 465 : case OMP_MAP_FORCE_TO:
4305 465 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TO);
4306 465 : break;
4307 577 : case OMP_MAP_FORCE_FROM:
4308 577 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_FROM);
4309 577 : break;
4310 0 : case OMP_MAP_FORCE_TOFROM:
4311 0 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TOFROM);
4312 0 : break;
4313 545 : case OMP_MAP_FORCE_PRESENT:
4314 545 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_PRESENT);
4315 545 : break;
4316 10 : case OMP_MAP_FORCE_DEVICEPTR:
4317 10 : OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_DEVICEPTR);
4318 10 : break;
4319 0 : default:
4320 0 : gcc_unreachable ();
4321 : }
4322 :
4323 15280 : tree decl = gfc_trans_omp_variable (n->sym, false);
4324 15280 : if (DECL_P (decl))
4325 15280 : TREE_ADDRESSABLE (decl) = 1;
4326 :
4327 15280 : gfc_ref *lastref = NULL;
4328 :
4329 15280 : if (n->expr)
4330 14700 : for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
4331 9021 : if (ref->type == REF_COMPONENT || ref->type == REF_ARRAY)
4332 9021 : lastref = ref;
4333 :
4334 5679 : bool allocatable = false, pointer = false;
4335 :
4336 5679 : if (lastref && lastref->type == REF_COMPONENT)
4337 : {
4338 457 : gfc_component *c = lastref->u.c.component;
4339 :
4340 457 : if (c->ts.type == BT_CLASS)
4341 : {
4342 24 : pointer = CLASS_DATA (c)->attr.class_pointer;
4343 24 : allocatable = CLASS_DATA (c)->attr.allocatable;
4344 : }
4345 : else
4346 : {
4347 433 : pointer = c->attr.pointer;
4348 433 : allocatable = c->attr.allocatable;
4349 : }
4350 : }
4351 :
4352 15280 : if (n->expr == NULL
4353 5679 : || (n->expr->ref->type == REF_ARRAY
4354 3549 : && n->expr->ref->u.ar.type == AR_FULL))
4355 : {
4356 9601 : gomp_map_kind map_kind;
4357 9601 : tree type = TREE_TYPE (decl);
4358 9601 : if (n->sym->ts.type == BT_CHARACTER
4359 218 : && n->sym->ts.deferred
4360 92 : && (n->sym->attr.omp_declare_target
4361 84 : || n->sym->attr.omp_declare_target_link
4362 84 : || n->sym->attr.omp_declare_target_local)
4363 8 : && (always_modifier || n->sym->attr.pointer)
4364 8 : && op != EXEC_OMP_TARGET_EXIT_DATA
4365 4 : && n->u.map.op != OMP_MAP_DELETE
4366 4 : && n->u.map.op != OMP_MAP_RELEASE)
4367 : {
4368 4 : gcc_assert (n->sym->ts.u.cl->backend_decl);
4369 4 : node5 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
4370 4 : OMP_CLAUSE_SET_MAP_KIND (node5, GOMP_MAP_ALWAYS_TO);
4371 4 : OMP_CLAUSE_DECL (node5) = n->sym->ts.u.cl->backend_decl;
4372 4 : OMP_CLAUSE_SIZE (node5)
4373 8 : = TYPE_SIZE_UNIT (gfc_charlen_type_node);
4374 : }
4375 :
4376 9601 : tree present = gfc_omp_check_optional_argument (decl, true);
4377 9601 : if (openacc && n->sym->ts.type == BT_CLASS)
4378 : {
4379 60 : if (n->sym->attr.optional)
4380 0 : sorry_at (gfc_get_location (&n->where),
4381 : "optional class parameter");
4382 60 : tree ptr = gfc_class_data_get (decl);
4383 60 : ptr = build_fold_indirect_ref (ptr);
4384 60 : OMP_CLAUSE_DECL (node) = ptr;
4385 60 : OMP_CLAUSE_SIZE (node) = gfc_class_vtab_size_get (decl);
4386 60 : node2 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
4387 60 : OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_ATTACH_DETACH);
4388 60 : OMP_CLAUSE_DECL (node2) = gfc_class_data_get (decl);
4389 60 : OMP_CLAUSE_SIZE (node2) = size_int (0);
4390 60 : goto finalize_map_clause;
4391 : }
4392 9541 : else if (POINTER_TYPE_P (type)
4393 9541 : && (gfc_omp_privatize_by_reference (decl)
4394 502 : || GFC_DECL_GET_SCALAR_POINTER (decl)
4395 319 : || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
4396 84 : || GFC_DECL_CRAY_POINTEE (decl)
4397 84 : || GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type))
4398 84 : || (n->sym->ts.type == BT_DERIVED
4399 8 : && (n->sym->ts.u.derived->ts.f90_type
4400 : != BT_VOID))))
4401 : {
4402 3378 : tree orig_decl = decl;
4403 :
4404 : /* For nonallocatable, nonpointer arrays, a temporary
4405 : variable is generated, but this one is only defined if
4406 : the variable is present; hence, we now set it to NULL
4407 : to avoid accessing undefined variables. We cannot use
4408 : a temporary variable here as otherwise the replacement
4409 : of the variables in omp-low.cc will not work. */
4410 3378 : if (present && GFC_ARRAY_TYPE_P (type))
4411 : {
4412 284 : tree tmp = fold_build2_loc (input_location,
4413 : MODIFY_EXPR,
4414 : void_type_node, decl,
4415 : null_pointer_node);
4416 284 : tree cond = fold_build1_loc (input_location,
4417 : TRUTH_NOT_EXPR,
4418 : boolean_type_node,
4419 : present);
4420 284 : gfc_add_expr_to_block (block,
4421 : build3_loc (input_location,
4422 : COND_EXPR,
4423 : void_type_node,
4424 : cond, tmp,
4425 : NULL_TREE));
4426 : }
4427 : /* For descriptor types, the unmapping happens below. */
4428 3378 : if (op != EXEC_OMP_TARGET_EXIT_DATA
4429 3378 : || !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
4430 : {
4431 3378 : enum gomp_map_kind gmk = GOMP_MAP_POINTER;
4432 3378 : if (op == EXEC_OMP_TARGET_EXIT_DATA
4433 49 : && n->u.map.op == OMP_MAP_DELETE)
4434 : gmk = GOMP_MAP_DELETE;
4435 44 : else if (op == EXEC_OMP_TARGET_EXIT_DATA)
4436 44 : gmk = GOMP_MAP_RELEASE;
4437 3378 : tree size;
4438 3378 : if (gmk == GOMP_MAP_RELEASE || gmk == GOMP_MAP_DELETE)
4439 49 : size = TYPE_SIZE_UNIT (TREE_TYPE (decl));
4440 : else
4441 3329 : size = size_int (0);
4442 3378 : node4 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
4443 3378 : OMP_CLAUSE_SET_MAP_KIND (node4, gmk);
4444 3378 : OMP_CLAUSE_DECL (node4) = decl;
4445 3378 : OMP_CLAUSE_SIZE (node4) = size;
4446 : }
4447 3378 : decl = build_fold_indirect_ref (decl);
4448 3378 : if ((TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE
4449 2151 : || gfc_omp_is_optional_argument (orig_decl))
4450 4430 : && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
4451 2109 : || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
4452 : {
4453 408 : enum gomp_map_kind gmk;
4454 408 : if (op == EXEC_OMP_TARGET_EXIT_DATA
4455 8 : && n->u.map.op == OMP_MAP_DELETE)
4456 : gmk = GOMP_MAP_DELETE;
4457 6 : else if (op == EXEC_OMP_TARGET_EXIT_DATA)
4458 : gmk = GOMP_MAP_RELEASE;
4459 : else
4460 : gmk = GOMP_MAP_POINTER;
4461 408 : tree size;
4462 408 : if (gmk == GOMP_MAP_RELEASE || gmk == GOMP_MAP_DELETE)
4463 8 : size = TYPE_SIZE_UNIT (TREE_TYPE (decl));
4464 : else
4465 400 : size = size_int (0);
4466 408 : node3 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
4467 408 : OMP_CLAUSE_SET_MAP_KIND (node3, gmk);
4468 408 : OMP_CLAUSE_DECL (node3) = decl;
4469 408 : OMP_CLAUSE_SIZE (node3) = size;
4470 408 : decl = build_fold_indirect_ref (decl);
4471 : }
4472 : }
4473 9541 : if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
4474 : {
4475 1403 : tree type = TREE_TYPE (decl);
4476 1403 : tree ptr = gfc_conv_descriptor_data_get (decl);
4477 1403 : if (present)
4478 309 : ptr = gfc_build_cond_assign_expr (block, present, ptr,
4479 : null_pointer_node);
4480 1403 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
4481 1403 : ptr = build_fold_indirect_ref (ptr);
4482 1403 : OMP_CLAUSE_DECL (node) = ptr;
4483 1403 : node2 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
4484 1403 : OMP_CLAUSE_DECL (node2) = decl;
4485 1403 : OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
4486 1403 : if (n->u.map.op == OMP_MAP_DELETE)
4487 : map_kind = GOMP_MAP_DELETE;
4488 1376 : else if (op == EXEC_OMP_TARGET_EXIT_DATA
4489 1313 : || n->u.map.op == OMP_MAP_RELEASE)
4490 : map_kind = GOMP_MAP_RELEASE;
4491 : else
4492 1403 : map_kind = GOMP_MAP_TO_PSET;
4493 1403 : OMP_CLAUSE_SET_MAP_KIND (node2, map_kind);
4494 :
4495 1403 : if (op != EXEC_OMP_TARGET_EXIT_DATA
4496 1313 : && n->u.map.op != OMP_MAP_DELETE
4497 1313 : && n->u.map.op != OMP_MAP_RELEASE)
4498 : {
4499 1265 : node3 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
4500 1265 : if (present)
4501 : {
4502 309 : ptr = gfc_conv_descriptor_data_get (decl);
4503 309 : ptr = gfc_build_addr_expr (NULL, ptr);
4504 309 : ptr = gfc_build_cond_assign_expr (
4505 : block, present, ptr, null_pointer_node);
4506 309 : ptr = build_fold_indirect_ref (ptr);
4507 309 : OMP_CLAUSE_DECL (node3) = ptr;
4508 : }
4509 : else
4510 956 : OMP_CLAUSE_DECL (node3)
4511 1912 : = gfc_conv_descriptor_data_get (decl);
4512 1265 : OMP_CLAUSE_SIZE (node3) = size_int (0);
4513 :
4514 1265 : if (n->u.map.op == OMP_MAP_ATTACH)
4515 : {
4516 : /* Standalone attach clauses used with arrays with
4517 : descriptors must copy the descriptor to the
4518 : target, else they won't have anything to
4519 : perform the attachment onto (see OpenACC 2.6,
4520 : "2.6.3. Data Structures with Pointers"). */
4521 7 : OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_ATTACH);
4522 : /* We don't want to map PTR at all in this case,
4523 : so delete its node and shuffle the others
4524 : down. */
4525 7 : node = node2;
4526 7 : node2 = node3;
4527 7 : node3 = NULL;
4528 7 : goto finalize_map_clause;
4529 : }
4530 1258 : else if (n->u.map.op == OMP_MAP_DETACH)
4531 : {
4532 2 : OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_DETACH);
4533 : /* Similarly to above, we don't want to unmap PTR
4534 : here. */
4535 2 : node = node2;
4536 2 : node2 = node3;
4537 2 : node3 = NULL;
4538 2 : goto finalize_map_clause;
4539 : }
4540 : else
4541 2042 : OMP_CLAUSE_SET_MAP_KIND (node3,
4542 : always_modifier
4543 : ? GOMP_MAP_ALWAYS_POINTER
4544 : : GOMP_MAP_POINTER);
4545 : }
4546 :
4547 : /* We have to check for n->sym->attr.dimension because
4548 : of scalar coarrays. */
4549 1394 : if ((n->sym->attr.pointer || n->sym->attr.allocatable)
4550 1394 : && n->sym->attr.dimension)
4551 : {
4552 1394 : stmtblock_t cond_block;
4553 1394 : tree size
4554 1394 : = gfc_create_var (gfc_array_index_type, NULL);
4555 1394 : tree tem, then_b, else_b, zero, cond;
4556 :
4557 1394 : gfc_init_block (&cond_block);
4558 1394 : tem
4559 2788 : = gfc_full_array_size (&cond_block, decl,
4560 1394 : GFC_TYPE_ARRAY_RANK (type));
4561 1394 : tree elemsz;
4562 1394 : if (n->sym->ts.type == BT_CHARACTER
4563 52 : && n->sym->ts.deferred)
4564 : {
4565 44 : tree len = n->sym->ts.u.cl->backend_decl;
4566 44 : len = fold_convert (size_type_node, len);
4567 44 : elemsz = gfc_get_char_type (n->sym->ts.kind);
4568 44 : elemsz = TYPE_SIZE_UNIT (elemsz);
4569 44 : elemsz = fold_build2 (MULT_EXPR, size_type_node,
4570 : len, elemsz);
4571 44 : }
4572 : else
4573 1350 : elemsz
4574 1350 : = TYPE_SIZE_UNIT (gfc_get_element_type (type));
4575 1394 : elemsz = fold_convert (gfc_array_index_type, elemsz);
4576 1394 : tem = fold_build2 (MULT_EXPR, gfc_array_index_type,
4577 : tem, elemsz);
4578 1394 : gfc_add_modify (&cond_block, size, tem);
4579 1394 : then_b = gfc_finish_block (&cond_block);
4580 1394 : gfc_init_block (&cond_block);
4581 1394 : zero = build_int_cst (gfc_array_index_type, 0);
4582 1394 : gfc_add_modify (&cond_block, size, zero);
4583 1394 : else_b = gfc_finish_block (&cond_block);
4584 1394 : tem = gfc_conv_descriptor_data_get (decl);
4585 1394 : tem = fold_convert (pvoid_type_node, tem);
4586 1394 : cond = fold_build2_loc (input_location, NE_EXPR,
4587 : boolean_type_node,
4588 : tem, null_pointer_node);
4589 1394 : if (present)
4590 309 : cond = fold_build2_loc (input_location,
4591 : TRUTH_ANDIF_EXPR,
4592 : boolean_type_node,
4593 : present, cond);
4594 1394 : gfc_add_expr_to_block (block,
4595 : build3_loc (input_location,
4596 : COND_EXPR,
4597 : void_type_node,
4598 : cond, then_b,
4599 : else_b));
4600 1394 : OMP_CLAUSE_SIZE (node) = size;
4601 1394 : }
4602 0 : else if (n->sym->attr.dimension)
4603 : {
4604 0 : stmtblock_t cond_block;
4605 0 : gfc_init_block (&cond_block);
4606 0 : tree size = gfc_full_array_size (&cond_block, decl,
4607 0 : GFC_TYPE_ARRAY_RANK (type));
4608 0 : tree elemsz
4609 0 : = TYPE_SIZE_UNIT (gfc_get_element_type (type));
4610 0 : elemsz = fold_convert (gfc_array_index_type, elemsz);
4611 0 : size = fold_build2 (MULT_EXPR, gfc_array_index_type,
4612 : size, elemsz);
4613 0 : size = gfc_evaluate_now (size, &cond_block);
4614 0 : if (present)
4615 : {
4616 0 : tree var = gfc_create_var (gfc_array_index_type,
4617 : NULL);
4618 0 : gfc_add_modify (&cond_block, var, size);
4619 0 : tree cond_body = gfc_finish_block (&cond_block);
4620 0 : tree cond = build3_loc (input_location, COND_EXPR,
4621 : void_type_node, present,
4622 : cond_body, NULL_TREE);
4623 0 : gfc_add_expr_to_block (block, cond);
4624 0 : OMP_CLAUSE_SIZE (node) = var;
4625 : }
4626 : else
4627 : {
4628 0 : gfc_add_block_to_block (block, &cond_block);
4629 0 : OMP_CLAUSE_SIZE (node) = size;
4630 : }
4631 : }
4632 : }
4633 8138 : else if (present
4634 845 : && INDIRECT_REF_P (decl)
4635 8881 : && INDIRECT_REF_P (TREE_OPERAND (decl, 0)))
4636 : {
4637 : /* A single indirectref is handled by the middle end. */
4638 228 : gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
4639 228 : tree tmp = TREE_OPERAND (decl, 0);
4640 228 : tmp = gfc_build_cond_assign_expr (block, present, tmp,
4641 : null_pointer_node);
4642 228 : OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (tmp);
4643 : }
4644 : else
4645 7910 : OMP_CLAUSE_DECL (node) = decl;
4646 :
4647 9532 : if (!n->sym->attr.dimension
4648 6041 : && n->sym->ts.type == BT_CHARACTER
4649 144 : && n->sym->ts.deferred)
4650 : {
4651 48 : if (!DECL_P (decl))
4652 : {
4653 48 : gcc_assert (TREE_CODE (decl) == INDIRECT_REF);
4654 48 : decl = TREE_OPERAND (decl, 0);
4655 : }
4656 48 : tree cond = fold_build2_loc (input_location, NE_EXPR,
4657 : boolean_type_node,
4658 : decl, null_pointer_node);
4659 48 : if (present)
4660 2 : cond = fold_build2_loc (input_location,
4661 : TRUTH_ANDIF_EXPR,
4662 : boolean_type_node,
4663 : present, cond);
4664 48 : tree len = n->sym->ts.u.cl->backend_decl;
4665 48 : len = fold_convert (size_type_node, len);
4666 48 : tree size = gfc_get_char_type (n->sym->ts.kind);
4667 48 : size = TYPE_SIZE_UNIT (size);
4668 48 : size = fold_build2 (MULT_EXPR, size_type_node, len, size);
4669 48 : size = build3_loc (input_location,
4670 : COND_EXPR,
4671 : size_type_node,
4672 : cond, size,
4673 : size_zero_node);
4674 48 : size = gfc_evaluate_now (size, block);
4675 48 : OMP_CLAUSE_SIZE (node) = size;
4676 : }
4677 9532 : if ((TREE_CODE (decl) != PARM_DECL
4678 186 : || DECL_ARTIFICIAL (OMP_CLAUSE_DECL (node)))
4679 9346 : && n->sym->ts.type == BT_DERIVED
4680 10057 : && n->sym->ts.u.derived->attr.alloc_comp)
4681 : {
4682 : /* Save array descriptor for use in
4683 : gfc_omp_deep_mapping{,_p,_cnt}; force evaluate
4684 : to ensure that it is not gimplified + is a decl. */
4685 212 : tree tmp = OMP_CLAUSE_SIZE (node);
4686 212 : if (tmp == NULL_TREE)
4687 229 : tmp = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
4688 46 : : TYPE_SIZE_UNIT (TREE_TYPE (decl));
4689 212 : tree var = gfc_create_var (TREE_TYPE (tmp), NULL);
4690 212 : gfc_add_modify_loc (input_location, block, var, tmp);
4691 212 : OMP_CLAUSE_SIZE (node) = var;
4692 212 : gfc_allocate_lang_decl (var);
4693 212 : if (TREE_CODE (decl) == INDIRECT_REF)
4694 48 : decl = TREE_OPERAND (decl, 0);
4695 212 : if (TREE_CODE (decl) == INDIRECT_REF)
4696 2 : decl = TREE_OPERAND (decl, 0);
4697 212 : if (DECL_LANG_SPECIFIC (decl)
4698 212 : && GFC_DECL_SAVED_DESCRIPTOR (decl))
4699 6 : GFC_DECL_SAVED_DESCRIPTOR (var)
4700 2 : = GFC_DECL_SAVED_DESCRIPTOR (decl);
4701 : else
4702 210 : GFC_DECL_SAVED_DESCRIPTOR (var) = decl;
4703 : }
4704 : }
4705 5679 : else if (n->expr
4706 5679 : && n->expr->expr_type == EXPR_VARIABLE
4707 5679 : && n->expr->ref->type == REF_ARRAY
4708 3549 : && !n->expr->ref->next)
4709 : {
4710 : /* An array element or array section which is not part of a
4711 : derived type, etc. */
4712 3294 : bool element = n->expr->ref->u.ar.type == AR_ELEMENT;
4713 3294 : tree type = TREE_TYPE (decl);
4714 3294 : gomp_map_kind k = GOMP_MAP_POINTER;
4715 3294 : if (!openacc
4716 443 : && !GFC_DESCRIPTOR_TYPE_P (type)
4717 3682 : && !(POINTER_TYPE_P (type)
4718 256 : && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type))))
4719 : k = GOMP_MAP_FIRSTPRIVATE_POINTER;
4720 3294 : gfc_trans_omp_array_section (block, op, n, decl, element,
4721 3294 : !openacc, k, node, node2,
4722 : node3, node4);
4723 3294 : }
4724 2385 : else if (n->expr
4725 2385 : && n->expr->expr_type == EXPR_VARIABLE
4726 2385 : && (n->expr->ref->type == REF_COMPONENT
4727 : || n->expr->ref->type == REF_ARRAY)
4728 2385 : && lastref
4729 2385 : && lastref->type == REF_COMPONENT
4730 457 : && lastref->u.c.component->ts.type != BT_CLASS
4731 433 : && lastref->u.c.component->ts.type != BT_DERIVED
4732 341 : && !lastref->u.c.component->attr.dimension)
4733 : {
4734 : /* Derived type access with last component being a scalar. */
4735 341 : gfc_init_se (&se, NULL);
4736 :
4737 341 : gfc_conv_expr (&se, n->expr);
4738 341 : gfc_add_block_to_block (block, &se.pre);
4739 : /* For BT_CHARACTER a pointer is returned. */
4740 341 : OMP_CLAUSE_DECL (node)
4741 588 : = POINTER_TYPE_P (TREE_TYPE (se.expr))
4742 341 : ? build_fold_indirect_ref (se.expr) : se.expr;
4743 341 : gfc_add_block_to_block (block, &se.post);
4744 341 : if (pointer || allocatable)
4745 : {
4746 : /* If it's a bare attach/detach clause, we just want
4747 : to perform a single attach/detach operation, of the
4748 : pointer itself, not of the pointed-to object. */
4749 161 : if (openacc
4750 68 : && (n->u.map.op == OMP_MAP_ATTACH
4751 50 : || n->u.map.op == OMP_MAP_DETACH))
4752 : {
4753 36 : OMP_CLAUSE_DECL (node)
4754 36 : = build_fold_addr_expr (OMP_CLAUSE_DECL (node));
4755 36 : OMP_CLAUSE_SIZE (node) = size_zero_node;
4756 36 : goto finalize_map_clause;
4757 : }
4758 :
4759 125 : node2 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
4760 125 : OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_ATTACH_DETACH);
4761 125 : OMP_CLAUSE_DECL (node2)
4762 180 : = POINTER_TYPE_P (TREE_TYPE (se.expr))
4763 125 : ? se.expr
4764 55 : : gfc_build_addr_expr (NULL, se.expr);
4765 125 : OMP_CLAUSE_SIZE (node2) = size_int (0);
4766 125 : if (!openacc
4767 93 : && n->expr->ts.type == BT_CHARACTER
4768 54 : && n->expr->ts.deferred)
4769 : {
4770 54 : gcc_assert (se.string_length);
4771 54 : tree tmp
4772 54 : = gfc_get_char_type (n->expr->ts.kind);
4773 54 : OMP_CLAUSE_SIZE (node)
4774 54 : = fold_build2 (MULT_EXPR, size_type_node,
4775 : fold_convert (size_type_node,
4776 : se.string_length),
4777 : TYPE_SIZE_UNIT (tmp));
4778 54 : gomp_map_kind kind;
4779 54 : if (n->u.map.op == OMP_MAP_DELETE)
4780 : kind = GOMP_MAP_DELETE;
4781 54 : else if (op == EXEC_OMP_TARGET_EXIT_DATA)
4782 : kind = GOMP_MAP_RELEASE;
4783 : else
4784 48 : kind = GOMP_MAP_TO;
4785 54 : node3 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
4786 54 : OMP_CLAUSE_SET_MAP_KIND (node3, kind);
4787 54 : OMP_CLAUSE_DECL (node3) = se.string_length;
4788 54 : OMP_CLAUSE_SIZE (node3)
4789 108 : = TYPE_SIZE_UNIT (gfc_charlen_type_node);
4790 : }
4791 93 : if (!openacc
4792 93 : && n->expr->ts.type == BT_DERIVED
4793 0 : && n->expr->ts.u.derived->attr.alloc_comp)
4794 : {
4795 : /* Save array descriptor for use in
4796 : gfc_omp_deep_mapping{,_p,_cnt}; force evaluate
4797 : to ensure that it is not gimplified + is a decl. */
4798 0 : tree tmp = OMP_CLAUSE_SIZE (node);
4799 0 : if (tmp == NULL_TREE)
4800 0 : tmp = (DECL_P (se.expr)
4801 0 : ? DECL_SIZE_UNIT (se.expr)
4802 0 : : TYPE_SIZE_UNIT (TREE_TYPE (se.expr)));
4803 0 : tree var = gfc_create_var (TREE_TYPE (tmp), NULL);
4804 0 : gfc_add_modify_loc (input_location, block, var, tmp);
4805 0 : OMP_CLAUSE_SIZE (node) = var;
4806 0 : gfc_allocate_lang_decl (var);
4807 0 : if (TREE_CODE (se.expr) == INDIRECT_REF)
4808 0 : se.expr = TREE_OPERAND (se.expr, 0);
4809 0 : if (DECL_LANG_SPECIFIC (se.expr)
4810 0 : && GFC_DECL_SAVED_DESCRIPTOR (se.expr))
4811 0 : GFC_DECL_SAVED_DESCRIPTOR (var)
4812 0 : = GFC_DECL_SAVED_DESCRIPTOR (se.expr);
4813 : else
4814 0 : GFC_DECL_SAVED_DESCRIPTOR (var) = se.expr;
4815 : }
4816 : }
4817 : }
4818 2044 : else if (n->expr
4819 2044 : && n->expr->expr_type == EXPR_VARIABLE
4820 2044 : && (n->expr->ref->type == REF_COMPONENT
4821 : || n->expr->ref->type == REF_ARRAY))
4822 : {
4823 2044 : gfc_init_se (&se, NULL);
4824 2044 : se.expr = gfc_maybe_dereference_var (n->sym, decl);
4825 2044 : vec<tree> mid_descr = vNULL;
4826 2044 : vec<gfc_ref *> midref = vNULL;
4827 :
4828 7409 : for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
4829 : {
4830 5365 : if (ref->type == REF_COMPONENT)
4831 : {
4832 2705 : if (ref->u.c.sym->attr.extension)
4833 91 : conv_parent_component_references (&se, ref);
4834 :
4835 2705 : gfc_conv_component_ref (&se, ref);
4836 2705 : if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)))
4837 : {
4838 1966 : mid_descr.safe_push (se.expr);
4839 1966 : midref.safe_push (ref);
4840 : }
4841 : }
4842 2660 : else if (ref->type == REF_ARRAY)
4843 : {
4844 2660 : if (ref->u.ar.type == AR_ELEMENT && ref->next)
4845 732 : gfc_conv_array_ref (&se, &ref->u.ar, n->expr,
4846 732 : &n->expr->where);
4847 : else
4848 1928 : gcc_assert (!ref->next);
4849 : }
4850 : else
4851 0 : sorry_at (gfc_get_location (&n->where),
4852 : "unhandled expression type");
4853 : }
4854 :
4855 2044 : tree inner = se.expr;
4856 :
4857 : /* Last component is a derived type or class pointer. */
4858 2044 : if (lastref->type == REF_COMPONENT
4859 116 : && (lastref->u.c.component->ts.type == BT_DERIVED
4860 24 : || lastref->u.c.component->ts.type == BT_CLASS))
4861 : {
4862 116 : if (pointer || allocatable)
4863 : {
4864 : /* If it's a bare attach/detach clause, we just want
4865 : to perform a single attach/detach operation, of the
4866 : pointer itself, not of the pointed-to object. */
4867 67 : if (openacc
4868 49 : && (n->u.map.op == OMP_MAP_ATTACH
4869 43 : || n->u.map.op == OMP_MAP_DETACH))
4870 : {
4871 12 : OMP_CLAUSE_DECL (node)
4872 12 : = build_fold_addr_expr (inner);
4873 12 : OMP_CLAUSE_SIZE (node) = size_zero_node;
4874 18 : goto finalize_map_clause;
4875 : }
4876 :
4877 18 : gfc_omp_namelist *n2
4878 : = openacc ? NULL : clauses->lists[OMP_LIST_MAP];
4879 :
4880 55 : bool sym_based;
4881 55 : n2 = get_symbol_rooted_namelist (sym_rooted_nl, n,
4882 : n2, &sym_based);
4883 :
4884 : /* If the last reference is a pointer to a derived
4885 : type ("foo%dt_ptr"), check if any subcomponents
4886 : of the same derived type member are being mapped
4887 : elsewhere in the clause list ("foo%dt_ptr%x",
4888 : etc.). If we have such subcomponent mappings,
4889 : we only create an ALLOC node for the pointer
4890 : itself, and inhibit mapping the whole derived
4891 : type. */
4892 :
4893 103 : for (; n2 != NULL; n2 = n2->next)
4894 : {
4895 54 : if ((!sym_based && n == n2)
4896 54 : || (sym_based && n == n2->u2.duplicate_of)
4897 42 : || !n2->expr)
4898 12 : continue;
4899 :
4900 42 : if (!gfc_omp_expr_prefix_same (n->expr,
4901 : n2->expr))
4902 36 : continue;
4903 :
4904 6 : gfc_ref *ref1 = n->expr->ref;
4905 6 : gfc_ref *ref2 = n2->expr->ref;
4906 :
4907 6 : while (ref1->next && ref2->next)
4908 : {
4909 : ref1 = ref1->next;
4910 : ref2 = ref2->next;
4911 : }
4912 :
4913 6 : if (ref2->next)
4914 : {
4915 6 : inner = build_fold_addr_expr (inner);
4916 6 : OMP_CLAUSE_SET_MAP_KIND (node,
4917 : GOMP_MAP_ALLOC);
4918 6 : OMP_CLAUSE_DECL (node) = inner;
4919 6 : OMP_CLAUSE_SIZE (node)
4920 6 : = TYPE_SIZE_UNIT (TREE_TYPE (inner));
4921 6 : goto finalize_map_clause;
4922 : }
4923 : }
4924 :
4925 49 : tree data, size;
4926 :
4927 49 : if (lastref->u.c.component->ts.type == BT_CLASS)
4928 : {
4929 24 : data = gfc_class_data_get (inner);
4930 24 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (data)));
4931 24 : data = build_fold_indirect_ref (data);
4932 24 : size = gfc_class_vtab_size_get (inner);
4933 : }
4934 : else /* BT_DERIVED. */
4935 : {
4936 25 : data = inner;
4937 25 : size = TYPE_SIZE_UNIT (TREE_TYPE (inner));
4938 : }
4939 :
4940 49 : OMP_CLAUSE_DECL (node) = data;
4941 49 : OMP_CLAUSE_SIZE (node) = size;
4942 49 : node2 = build_omp_clause (map_loc, OMP_CLAUSE_MAP);
4943 49 : OMP_CLAUSE_SET_MAP_KIND (node2,
4944 : GOMP_MAP_ATTACH_DETACH);
4945 49 : OMP_CLAUSE_DECL (node2) = build_fold_addr_expr (data);
4946 49 : OMP_CLAUSE_SIZE (node2) = size_int (0);
4947 : }
4948 : else
4949 : {
4950 49 : OMP_CLAUSE_DECL (node) = inner;
4951 49 : OMP_CLAUSE_SIZE (node)
4952 98 : = TYPE_SIZE_UNIT (TREE_TYPE (inner));
4953 : }
4954 98 : if (!openacc
4955 14 : && n->expr->ts.type == BT_DERIVED
4956 14 : && n->expr->ts.u.derived->attr.alloc_comp)
4957 : {
4958 : /* Save array descriptor for use in
4959 : gfc_omp_deep_mapping{,_p,_cnt}; force evaluate
4960 : to ensure that it is not gimplified + is a decl. */
4961 8 : tree tmp = OMP_CLAUSE_SIZE (node);
4962 8 : tree var = gfc_create_var (TREE_TYPE (tmp), NULL);
4963 8 : gfc_add_modify_loc (input_location, block, var, tmp);
4964 8 : OMP_CLAUSE_SIZE (node) = var;
4965 8 : gfc_allocate_lang_decl (var);
4966 8 : if (TREE_CODE (inner) == INDIRECT_REF)
4967 6 : inner = TREE_OPERAND (inner, 0);
4968 8 : GFC_DECL_SAVED_DESCRIPTOR (var) = inner;
4969 : }
4970 : }
4971 1928 : else if (lastref->type == REF_ARRAY
4972 1928 : && lastref->u.ar.type == AR_FULL)
4973 : {
4974 : /* Bare attach and detach clauses don't want any
4975 : additional nodes. */
4976 1234 : if ((n->u.map.op == OMP_MAP_ATTACH
4977 1203 : || n->u.map.op == OMP_MAP_DETACH)
4978 1248 : && (POINTER_TYPE_P (TREE_TYPE (inner))
4979 45 : || GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (inner))))
4980 : {
4981 45 : if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (inner)))
4982 : {
4983 45 : tree ptr = gfc_conv_descriptor_data_get (inner);
4984 45 : OMP_CLAUSE_DECL (node) = ptr;
4985 : }
4986 : else
4987 0 : OMP_CLAUSE_DECL (node) = inner;
4988 45 : OMP_CLAUSE_SIZE (node) = size_zero_node;
4989 45 : goto finalize_map_clause;
4990 : }
4991 :
4992 1189 : if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (inner)))
4993 : {
4994 1019 : bool drop_mapping = gfc_map_array_descriptor (
4995 : node, node2, node3, node4, inner, openacc, map_loc,
4996 : block, op, n, sym_rooted_nl, se, clauses, false);
4997 1019 : if (drop_mapping)
4998 286 : continue;
4999 : }
5000 : else
5001 170 : OMP_CLAUSE_DECL (node) = inner;
5002 : }
5003 694 : else if (lastref->type == REF_ARRAY)
5004 : {
5005 : /* An array element or section. */
5006 694 : bool element = lastref->u.ar.type == AR_ELEMENT;
5007 694 : gomp_map_kind kind = GOMP_MAP_ATTACH_DETACH;
5008 694 : gfc_trans_omp_array_section (block, op, n, inner, element,
5009 694 : !openacc, kind, node, node2,
5010 : node3, node4);
5011 : }
5012 : else
5013 0 : gcc_unreachable ();
5014 :
5015 : /* Map intermediate array descriptors. */
5016 1611 : if (!openacc && !mid_descr.is_empty ())
5017 2255 : for (size_t i = 0; i < mid_descr.length (); i++)
5018 1300 : if (mid_descr[i] != inner
5019 1300 : && !descriptors.contains (midref[i]->u.c.sym))
5020 : {
5021 172 : descriptors.safe_push (midref[i]->u.c.sym);
5022 172 : tree node1 = copy_node (node);
5023 172 : tree node2 = NULL_TREE;
5024 172 : tree node3 = NULL_TREE;
5025 172 : tree node4 = NULL_TREE;
5026 344 : gfc_map_array_descriptor (node1, node2, node3, node4,
5027 172 : mid_descr[i], openacc,
5028 : map_loc, block, op, n,
5029 : sym_rooted_nl, se, clauses,
5030 : true);
5031 :
5032 172 : if (node1 != NULL_TREE)
5033 90 : omp_clauses
5034 90 : = gfc_trans_add_clause (node1, omp_clauses);
5035 172 : if (node2 != NULL_TREE)
5036 172 : omp_clauses
5037 172 : = gfc_trans_add_clause (node2, omp_clauses);
5038 172 : if (node3 != NULL_TREE)
5039 172 : omp_clauses
5040 172 : = gfc_trans_add_clause (node3, omp_clauses);
5041 172 : if (node4 != NULL_TREE)
5042 0 : omp_clauses
5043 0 : = gfc_trans_add_clause (node4, omp_clauses);
5044 : }
5045 1695 : }
5046 : else
5047 0 : sorry_at (gfc_get_location (&n->where), "unhandled expression");
5048 :
5049 14994 : finalize_map_clause:
5050 :
5051 14994 : omp_clauses = gfc_trans_add_clause (node, omp_clauses);
5052 14994 : if (node2)
5053 5085 : omp_clauses = gfc_trans_add_clause (node2, omp_clauses);
5054 14994 : if (node3)
5055 6294 : omp_clauses = gfc_trans_add_clause (node3, omp_clauses);
5056 14994 : if (node4)
5057 3498 : omp_clauses = gfc_trans_add_clause (node4, omp_clauses);
5058 14994 : if (node5)
5059 4 : omp_clauses = gfc_trans_add_clause (node5, omp_clauses);
5060 : }
5061 : break;
5062 : case OMP_LIST_TO:
5063 : case OMP_LIST_FROM:
5064 : case OMP_LIST_CACHE:
5065 3637 : for (; n != NULL; n = n->next)
5066 : {
5067 1862 : if (!n->sym->attr.referenced
5068 0 : && n->sym->attr.flavor != FL_PARAMETER)
5069 0 : continue;
5070 :
5071 1862 : switch (list)
5072 : {
5073 : case OMP_LIST_TO:
5074 : clause_code = OMP_CLAUSE_TO;
5075 : break;
5076 1030 : case OMP_LIST_FROM:
5077 1030 : clause_code = OMP_CLAUSE_FROM;
5078 1030 : break;
5079 84 : case OMP_LIST_CACHE:
5080 84 : clause_code = OMP_CLAUSE__CACHE_;
5081 84 : break;
5082 0 : default:
5083 0 : gcc_unreachable ();
5084 : }
5085 1862 : tree node = build_omp_clause (gfc_get_location (&n->where),
5086 : clause_code);
5087 1862 : if (n->expr == NULL
5088 128 : || (n->expr->ref->type == REF_ARRAY
5089 116 : && n->expr->ref->u.ar.type == AR_FULL
5090 0 : && n->expr->ref->next == NULL))
5091 : {
5092 1734 : tree decl = gfc_trans_omp_variable (n->sym, false);
5093 1734 : if (gfc_omp_privatize_by_reference (decl))
5094 : {
5095 1047 : if (gfc_omp_is_allocatable_or_ptr (decl))
5096 240 : decl = build_fold_indirect_ref (decl);
5097 1047 : decl = build_fold_indirect_ref (decl);
5098 : }
5099 687 : else if (DECL_P (decl))
5100 687 : TREE_ADDRESSABLE (decl) = 1;
5101 1734 : if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
5102 : {
5103 597 : tree type = TREE_TYPE (decl);
5104 597 : tree ptr = gfc_conv_descriptor_data_get (decl);
5105 597 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
5106 597 : ptr = build_fold_indirect_ref (ptr);
5107 597 : OMP_CLAUSE_DECL (node) = ptr;
5108 597 : OMP_CLAUSE_SIZE (node)
5109 597 : = gfc_full_array_size (block, decl,
5110 597 : GFC_TYPE_ARRAY_RANK (type));
5111 597 : tree elemsz
5112 597 : = TYPE_SIZE_UNIT (gfc_get_element_type (type));
5113 597 : elemsz = fold_convert (gfc_array_index_type, elemsz);
5114 1194 : OMP_CLAUSE_SIZE (node)
5115 1194 : = fold_build2 (MULT_EXPR, gfc_array_index_type,
5116 : OMP_CLAUSE_SIZE (node), elemsz);
5117 : }
5118 : else
5119 : {
5120 1137 : OMP_CLAUSE_DECL (node) = decl;
5121 1137 : if (gfc_omp_is_allocatable_or_ptr (decl))
5122 120 : OMP_CLAUSE_SIZE (node)
5123 240 : = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)));
5124 : }
5125 : }
5126 : else
5127 : {
5128 128 : tree ptr;
5129 128 : gfc_init_se (&se, NULL);
5130 128 : if (n->expr->rank == 0)
5131 : {
5132 5 : gfc_conv_expr_reference (&se, n->expr);
5133 5 : ptr = se.expr;
5134 5 : gfc_add_block_to_block (block, &se.pre);
5135 5 : OMP_CLAUSE_SIZE (node)
5136 10 : = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ptr)));
5137 : }
5138 : else
5139 : {
5140 123 : gfc_conv_expr_descriptor (&se, n->expr);
5141 123 : ptr = gfc_conv_array_data (se.expr);
5142 123 : tree type = TREE_TYPE (se.expr);
5143 123 : gfc_add_block_to_block (block, &se.pre);
5144 123 : OMP_CLAUSE_SIZE (node)
5145 123 : = gfc_full_array_size (block, se.expr,
5146 123 : GFC_TYPE_ARRAY_RANK (type));
5147 123 : tree elemsz
5148 123 : = TYPE_SIZE_UNIT (gfc_get_element_type (type));
5149 123 : elemsz = fold_convert (gfc_array_index_type, elemsz);
5150 246 : OMP_CLAUSE_SIZE (node)
5151 246 : = fold_build2 (MULT_EXPR, gfc_array_index_type,
5152 : OMP_CLAUSE_SIZE (node), elemsz);
5153 : }
5154 128 : gfc_add_block_to_block (block, &se.post);
5155 128 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
5156 128 : OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
5157 : }
5158 1862 : if (n->u.present_modifier)
5159 5 : OMP_CLAUSE_MOTION_PRESENT (node) = 1;
5160 1862 : if (list == OMP_LIST_CACHE && n->u.map.readonly)
5161 16 : OMP_CLAUSE__CACHE__READONLY (node) = 1;
5162 1862 : omp_clauses = gfc_trans_add_clause (node, omp_clauses);
5163 : }
5164 : break;
5165 : case OMP_LIST_USES_ALLOCATORS:
5166 : /* Ignore omp_null_allocator and pre-defined allocators as no
5167 : special treatment is needed. */
5168 37 : for (; n != NULL; n = n->next)
5169 34 : if (n->sym->attr.flavor == FL_VARIABLE)
5170 : break;
5171 17 : if (n != NULL)
5172 14 : sorry_at (input_location, "%<uses_allocators%> clause with traits "
5173 : "and memory spaces");
5174 : break;
5175 : default:
5176 : break;
5177 : }
5178 : }
5179 :
5180 : /* Free hashmap if we built it. */
5181 31700 : if (sym_rooted_nl)
5182 : {
5183 388 : typedef hash_map<gfc_symbol *, gfc_omp_namelist *>::iterator hti;
5184 1278 : for (hti it = sym_rooted_nl->begin (); it != sym_rooted_nl->end (); ++it)
5185 : {
5186 445 : gfc_omp_namelist *&nl = (*it).second;
5187 1771 : while (nl)
5188 : {
5189 1326 : gfc_omp_namelist *next = nl->next;
5190 1326 : free (nl);
5191 1326 : nl = next;
5192 : }
5193 : }
5194 388 : delete sym_rooted_nl;
5195 : }
5196 :
5197 31700 : if (clauses->if_expr)
5198 : {
5199 1112 : tree if_var;
5200 :
5201 1112 : gfc_init_se (&se, NULL);
5202 1112 : gfc_conv_expr (&se, clauses->if_expr);
5203 1112 : gfc_add_block_to_block (block, &se.pre);
5204 1112 : if_var = gfc_evaluate_now (se.expr, block);
5205 1112 : gfc_add_block_to_block (block, &se.post);
5206 :
5207 1112 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF);
5208 1112 : OMP_CLAUSE_IF_MODIFIER (c) = ERROR_MARK;
5209 1112 : OMP_CLAUSE_IF_EXPR (c) = if_var;
5210 1112 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5211 : }
5212 :
5213 348700 : for (ifc = 0; ifc < OMP_IF_LAST; ifc++)
5214 317000 : if (clauses->if_exprs[ifc])
5215 : {
5216 123 : tree if_var;
5217 :
5218 123 : gfc_init_se (&se, NULL);
5219 123 : gfc_conv_expr (&se, clauses->if_exprs[ifc]);
5220 123 : gfc_add_block_to_block (block, &se.pre);
5221 123 : if_var = gfc_evaluate_now (se.expr, block);
5222 123 : gfc_add_block_to_block (block, &se.post);
5223 :
5224 123 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF);
5225 123 : switch (ifc)
5226 : {
5227 0 : case OMP_IF_CANCEL:
5228 0 : OMP_CLAUSE_IF_MODIFIER (c) = VOID_CST;
5229 0 : break;
5230 40 : case OMP_IF_PARALLEL:
5231 40 : OMP_CLAUSE_IF_MODIFIER (c) = OMP_PARALLEL;
5232 40 : break;
5233 39 : case OMP_IF_SIMD:
5234 39 : OMP_CLAUSE_IF_MODIFIER (c) = OMP_SIMD;
5235 39 : break;
5236 1 : case OMP_IF_TASK:
5237 1 : OMP_CLAUSE_IF_MODIFIER (c) = OMP_TASK;
5238 1 : break;
5239 23 : case OMP_IF_TASKLOOP:
5240 23 : OMP_CLAUSE_IF_MODIFIER (c) = OMP_TASKLOOP;
5241 23 : break;
5242 16 : case OMP_IF_TARGET:
5243 16 : OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET;
5244 16 : break;
5245 1 : case OMP_IF_TARGET_DATA:
5246 1 : OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_DATA;
5247 1 : break;
5248 1 : case OMP_IF_TARGET_UPDATE:
5249 1 : OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_UPDATE;
5250 1 : break;
5251 1 : case OMP_IF_TARGET_ENTER_DATA:
5252 1 : OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_ENTER_DATA;
5253 1 : break;
5254 1 : case OMP_IF_TARGET_EXIT_DATA:
5255 1 : OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_EXIT_DATA;
5256 1 : break;
5257 : default:
5258 : gcc_unreachable ();
5259 : }
5260 123 : OMP_CLAUSE_IF_EXPR (c) = if_var;
5261 123 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5262 : }
5263 :
5264 31700 : if (clauses->self_expr)
5265 : {
5266 159 : tree self_var;
5267 :
5268 159 : gfc_init_se (&se, NULL);
5269 159 : gfc_conv_expr (&se, clauses->self_expr);
5270 159 : gfc_add_block_to_block (block, &se.pre);
5271 159 : self_var = gfc_evaluate_now (se.expr, block);
5272 159 : gfc_add_block_to_block (block, &se.post);
5273 :
5274 159 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SELF);
5275 159 : OMP_CLAUSE_SELF_EXPR (c) = self_var;
5276 159 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5277 : }
5278 :
5279 31700 : if (clauses->final_expr)
5280 : {
5281 64 : tree final_var;
5282 :
5283 64 : gfc_init_se (&se, NULL);
5284 64 : gfc_conv_expr (&se, clauses->final_expr);
5285 64 : gfc_add_block_to_block (block, &se.pre);
5286 64 : final_var = gfc_evaluate_now (se.expr, block);
5287 64 : gfc_add_block_to_block (block, &se.post);
5288 :
5289 64 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FINAL);
5290 64 : OMP_CLAUSE_FINAL_EXPR (c) = final_var;
5291 64 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5292 : }
5293 :
5294 31700 : if (clauses->novariants)
5295 : {
5296 8 : tree novariants_var;
5297 :
5298 8 : gfc_init_se (&se, NULL);
5299 8 : gfc_conv_expr (&se, clauses->novariants);
5300 8 : gfc_add_block_to_block (block, &se.pre);
5301 8 : novariants_var = gfc_evaluate_now (se.expr, block);
5302 8 : gfc_add_block_to_block (block, &se.post);
5303 :
5304 8 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOVARIANTS);
5305 8 : OMP_CLAUSE_NOVARIANTS_EXPR (c) = novariants_var;
5306 8 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5307 : }
5308 :
5309 31700 : if (clauses->nocontext)
5310 : {
5311 9 : tree nocontext_var;
5312 :
5313 9 : gfc_init_se (&se, NULL);
5314 9 : gfc_conv_expr (&se, clauses->nocontext);
5315 9 : gfc_add_block_to_block (block, &se.pre);
5316 9 : nocontext_var = gfc_evaluate_now (se.expr, block);
5317 9 : gfc_add_block_to_block (block, &se.post);
5318 :
5319 9 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOCONTEXT);
5320 9 : OMP_CLAUSE_NOCONTEXT_EXPR (c) = nocontext_var;
5321 9 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5322 : }
5323 :
5324 31700 : if (clauses->num_threads)
5325 : {
5326 943 : tree num_threads;
5327 :
5328 943 : gfc_init_se (&se, NULL);
5329 943 : gfc_conv_expr (&se, clauses->num_threads);
5330 943 : gfc_add_block_to_block (block, &se.pre);
5331 943 : num_threads = gfc_evaluate_now (se.expr, block);
5332 943 : gfc_add_block_to_block (block, &se.post);
5333 :
5334 943 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_THREADS);
5335 943 : OMP_CLAUSE_NUM_THREADS_EXPR (c) = num_threads;
5336 943 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5337 : }
5338 :
5339 31700 : if (clauses->device_type != OMP_DEVICE_TYPE_UNSET)
5340 : {
5341 3 : enum omp_clause_device_type_kind type;
5342 3 : switch (clauses->device_type)
5343 : {
5344 : case OMP_DEVICE_TYPE_HOST:
5345 : type = OMP_CLAUSE_DEVICE_TYPE_HOST;
5346 : break;
5347 : case OMP_DEVICE_TYPE_NOHOST:
5348 : type = OMP_CLAUSE_DEVICE_TYPE_NOHOST;
5349 : break;
5350 : case OMP_DEVICE_TYPE_ANY:
5351 : type = OMP_CLAUSE_DEVICE_TYPE_ANY;
5352 : break;
5353 0 : case OMP_DEVICE_TYPE_UNSET:
5354 0 : default:
5355 0 : gcc_unreachable ();
5356 : }
5357 3 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEVICE_TYPE);
5358 3 : OMP_CLAUSE_DEVICE_TYPE_KIND (c) = type;
5359 3 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5360 : }
5361 :
5362 31700 : if (clauses->dyn_groupprivate)
5363 : {
5364 5 : gfc_init_se (&se, NULL);
5365 5 : gfc_conv_expr (&se, clauses->dyn_groupprivate);
5366 5 : gfc_add_block_to_block (block, &se.pre);
5367 5 : tree expr = (CONSTANT_CLASS_P (se.expr) || DECL_P (se.expr)
5368 5 : ? se.expr : gfc_evaluate_now (se.expr, block));
5369 5 : gfc_add_block_to_block (block, &se.post);
5370 :
5371 5 : enum omp_clause_fallback_kind kind = OMP_CLAUSE_FALLBACK_UNSPECIFIED;
5372 5 : switch (clauses->fallback)
5373 : {
5374 : case OMP_FALLBACK_ABORT:
5375 : kind = OMP_CLAUSE_FALLBACK_ABORT;
5376 : break;
5377 : case OMP_FALLBACK_DEFAULT_MEM:
5378 : kind = OMP_CLAUSE_FALLBACK_DEFAULT_MEM;
5379 : break;
5380 : case OMP_FALLBACK_NULL:
5381 : kind = OMP_CLAUSE_FALLBACK_NULL;
5382 : break;
5383 : case OMP_FALLBACK_NONE:
5384 : break;
5385 : }
5386 5 : c = build_omp_clause (gfc_get_location (&where),
5387 : OMP_CLAUSE_DYN_GROUPPRIVATE);
5388 5 : OMP_CLAUSE_DYN_GROUPPRIVATE_KIND (c) = kind;
5389 5 : OMP_CLAUSE_DYN_GROUPPRIVATE_EXPR (c) = expr;
5390 5 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5391 : }
5392 :
5393 31700 : chunk_size = NULL_TREE;
5394 31700 : if (clauses->chunk_size)
5395 : {
5396 493 : gfc_init_se (&se, NULL);
5397 493 : gfc_conv_expr (&se, clauses->chunk_size);
5398 493 : gfc_add_block_to_block (block, &se.pre);
5399 493 : chunk_size = gfc_evaluate_now (se.expr, block);
5400 493 : gfc_add_block_to_block (block, &se.post);
5401 : }
5402 :
5403 31700 : if (clauses->sched_kind != OMP_SCHED_NONE)
5404 : {
5405 782 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SCHEDULE);
5406 782 : OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
5407 782 : switch (clauses->sched_kind)
5408 : {
5409 407 : case OMP_SCHED_STATIC:
5410 407 : OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
5411 407 : break;
5412 159 : case OMP_SCHED_DYNAMIC:
5413 159 : OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
5414 159 : break;
5415 125 : case OMP_SCHED_GUIDED:
5416 125 : OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
5417 125 : break;
5418 84 : case OMP_SCHED_RUNTIME:
5419 84 : OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
5420 84 : break;
5421 7 : case OMP_SCHED_AUTO:
5422 7 : OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
5423 7 : break;
5424 0 : default:
5425 0 : gcc_unreachable ();
5426 : }
5427 782 : if (clauses->sched_monotonic)
5428 54 : OMP_CLAUSE_SCHEDULE_KIND (c)
5429 27 : = (omp_clause_schedule_kind) (OMP_CLAUSE_SCHEDULE_KIND (c)
5430 : | OMP_CLAUSE_SCHEDULE_MONOTONIC);
5431 755 : else if (clauses->sched_nonmonotonic)
5432 46 : OMP_CLAUSE_SCHEDULE_KIND (c)
5433 23 : = (omp_clause_schedule_kind) (OMP_CLAUSE_SCHEDULE_KIND (c)
5434 : | OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
5435 782 : if (clauses->sched_simd)
5436 17 : OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
5437 782 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5438 : }
5439 :
5440 31700 : if (clauses->default_sharing != OMP_DEFAULT_UNKNOWN)
5441 : {
5442 1075 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEFAULT);
5443 1075 : switch (clauses->default_sharing)
5444 : {
5445 665 : case OMP_DEFAULT_NONE:
5446 665 : OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_NONE;
5447 665 : break;
5448 183 : case OMP_DEFAULT_SHARED:
5449 183 : OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_SHARED;
5450 183 : break;
5451 24 : case OMP_DEFAULT_PRIVATE:
5452 24 : OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRIVATE;
5453 24 : break;
5454 8 : case OMP_DEFAULT_FIRSTPRIVATE:
5455 8 : OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
5456 8 : break;
5457 195 : case OMP_DEFAULT_PRESENT:
5458 195 : OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRESENT;
5459 195 : break;
5460 0 : default:
5461 0 : gcc_unreachable ();
5462 : }
5463 1075 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5464 : }
5465 :
5466 31700 : if (clauses->nowait)
5467 : {
5468 2061 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOWAIT);
5469 2061 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5470 : }
5471 :
5472 31700 : if (clauses->full)
5473 : {
5474 47 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FULL);
5475 47 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5476 : }
5477 :
5478 31700 : if (clauses->partial)
5479 : {
5480 259 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PARTIAL);
5481 259 : OMP_CLAUSE_PARTIAL_EXPR (c)
5482 518 : = (clauses->partial > 0
5483 259 : ? build_int_cst (integer_type_node, clauses->partial)
5484 : : NULL_TREE);
5485 259 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5486 : }
5487 :
5488 31700 : if (clauses->sizes_list)
5489 : {
5490 : tree list = NULL_TREE;
5491 344 : for (gfc_expr_list *el = clauses->sizes_list; el; el = el->next)
5492 224 : list = tree_cons (NULL_TREE, gfc_convert_expr_to_tree (block, el->expr),
5493 : list);
5494 :
5495 120 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIZES);
5496 120 : OMP_CLAUSE_SIZES_LIST (c) = nreverse (list);
5497 120 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5498 : }
5499 :
5500 31700 : if (clauses->ordered)
5501 : {
5502 315 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ORDERED);
5503 315 : OMP_CLAUSE_ORDERED_EXPR (c)
5504 315 : = clauses->orderedc ? build_int_cst (integer_type_node,
5505 134 : clauses->orderedc) : NULL_TREE;
5506 315 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5507 : }
5508 :
5509 31700 : if (clauses->order_concurrent)
5510 : {
5511 303 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ORDER);
5512 303 : OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = clauses->order_unconstrained;
5513 303 : OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = clauses->order_reproducible;
5514 303 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5515 : }
5516 :
5517 31700 : if (clauses->untied)
5518 : {
5519 141 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_UNTIED);
5520 141 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5521 : }
5522 :
5523 31700 : if (clauses->mergeable)
5524 : {
5525 32 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_MERGEABLE);
5526 32 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5527 : }
5528 :
5529 31700 : if (clauses->collapse)
5530 : {
5531 1645 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_COLLAPSE);
5532 1645 : OMP_CLAUSE_COLLAPSE_EXPR (c)
5533 1645 : = build_int_cst (integer_type_node, clauses->collapse);
5534 1645 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5535 : }
5536 :
5537 31700 : if (clauses->inbranch)
5538 : {
5539 18 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_INBRANCH);
5540 18 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5541 : }
5542 :
5543 31700 : if (clauses->notinbranch)
5544 : {
5545 23 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOTINBRANCH);
5546 23 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5547 : }
5548 :
5549 31700 : switch (clauses->cancel)
5550 : {
5551 : case OMP_CANCEL_UNKNOWN:
5552 : break;
5553 0 : case OMP_CANCEL_PARALLEL:
5554 0 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PARALLEL);
5555 0 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5556 0 : break;
5557 0 : case OMP_CANCEL_SECTIONS:
5558 0 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SECTIONS);
5559 0 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5560 0 : break;
5561 0 : case OMP_CANCEL_DO:
5562 0 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FOR);
5563 0 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5564 0 : break;
5565 0 : case OMP_CANCEL_TASKGROUP:
5566 0 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_TASKGROUP);
5567 0 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5568 0 : break;
5569 : }
5570 :
5571 31700 : if (clauses->proc_bind != OMP_PROC_BIND_UNKNOWN)
5572 : {
5573 64 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PROC_BIND);
5574 64 : switch (clauses->proc_bind)
5575 : {
5576 1 : case OMP_PROC_BIND_PRIMARY:
5577 1 : OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_PRIMARY;
5578 1 : break;
5579 9 : case OMP_PROC_BIND_MASTER:
5580 9 : OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_MASTER;
5581 9 : break;
5582 53 : case OMP_PROC_BIND_SPREAD:
5583 53 : OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_SPREAD;
5584 53 : break;
5585 1 : case OMP_PROC_BIND_CLOSE:
5586 1 : OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_CLOSE;
5587 1 : break;
5588 0 : default:
5589 0 : gcc_unreachable ();
5590 : }
5591 64 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5592 : }
5593 :
5594 31700 : if (clauses->safelen_expr)
5595 : {
5596 89 : tree safelen_var;
5597 :
5598 89 : gfc_init_se (&se, NULL);
5599 89 : gfc_conv_expr (&se, clauses->safelen_expr);
5600 89 : gfc_add_block_to_block (block, &se.pre);
5601 89 : safelen_var = gfc_evaluate_now (se.expr, block);
5602 89 : gfc_add_block_to_block (block, &se.post);
5603 :
5604 89 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SAFELEN);
5605 89 : OMP_CLAUSE_SAFELEN_EXPR (c) = safelen_var;
5606 89 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5607 : }
5608 :
5609 31700 : if (clauses->simdlen_expr)
5610 : {
5611 110 : if (declare_simd)
5612 : {
5613 65 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMDLEN);
5614 65 : OMP_CLAUSE_SIMDLEN_EXPR (c)
5615 65 : = gfc_conv_constant_to_tree (clauses->simdlen_expr);
5616 65 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5617 : }
5618 : else
5619 : {
5620 45 : tree simdlen_var;
5621 :
5622 45 : gfc_init_se (&se, NULL);
5623 45 : gfc_conv_expr (&se, clauses->simdlen_expr);
5624 45 : gfc_add_block_to_block (block, &se.pre);
5625 45 : simdlen_var = gfc_evaluate_now (se.expr, block);
5626 45 : gfc_add_block_to_block (block, &se.post);
5627 :
5628 45 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMDLEN);
5629 45 : OMP_CLAUSE_SIMDLEN_EXPR (c) = simdlen_var;
5630 45 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5631 : }
5632 : }
5633 :
5634 31700 : if (clauses->num_teams_upper)
5635 : {
5636 111 : tree num_teams_lower = NULL_TREE, num_teams_upper;
5637 :
5638 111 : gfc_init_se (&se, NULL);
5639 111 : gfc_conv_expr (&se, clauses->num_teams_upper);
5640 111 : gfc_add_block_to_block (block, &se.pre);
5641 111 : num_teams_upper = gfc_evaluate_now (se.expr, block);
5642 111 : gfc_add_block_to_block (block, &se.post);
5643 :
5644 111 : if (clauses->num_teams_lower)
5645 : {
5646 21 : gfc_init_se (&se, NULL);
5647 21 : gfc_conv_expr (&se, clauses->num_teams_lower);
5648 21 : gfc_add_block_to_block (block, &se.pre);
5649 21 : num_teams_lower = gfc_evaluate_now (se.expr, block);
5650 21 : gfc_add_block_to_block (block, &se.post);
5651 : }
5652 111 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_TEAMS);
5653 111 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = num_teams_lower;
5654 111 : OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = num_teams_upper;
5655 111 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5656 : }
5657 :
5658 31700 : if (clauses->device)
5659 : {
5660 295 : tree device;
5661 :
5662 295 : gfc_init_se (&se, NULL);
5663 295 : gfc_conv_expr (&se, clauses->device);
5664 295 : gfc_add_block_to_block (block, &se.pre);
5665 295 : device = gfc_evaluate_now (se.expr, block);
5666 295 : gfc_add_block_to_block (block, &se.post);
5667 :
5668 295 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEVICE);
5669 295 : OMP_CLAUSE_DEVICE_ID (c) = device;
5670 :
5671 295 : if (clauses->ancestor)
5672 39 : OMP_CLAUSE_DEVICE_ANCESTOR (c) = 1;
5673 :
5674 295 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5675 : }
5676 :
5677 31700 : if (clauses->thread_limit)
5678 : {
5679 105 : tree thread_limit;
5680 :
5681 105 : gfc_init_se (&se, NULL);
5682 105 : gfc_conv_expr (&se, clauses->thread_limit);
5683 105 : gfc_add_block_to_block (block, &se.pre);
5684 105 : thread_limit = gfc_evaluate_now (se.expr, block);
5685 105 : gfc_add_block_to_block (block, &se.post);
5686 :
5687 105 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_THREAD_LIMIT);
5688 105 : OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = thread_limit;
5689 105 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5690 : }
5691 :
5692 31700 : chunk_size = NULL_TREE;
5693 31700 : if (clauses->dist_chunk_size)
5694 : {
5695 81 : gfc_init_se (&se, NULL);
5696 81 : gfc_conv_expr (&se, clauses->dist_chunk_size);
5697 81 : gfc_add_block_to_block (block, &se.pre);
5698 81 : chunk_size = gfc_evaluate_now (se.expr, block);
5699 81 : gfc_add_block_to_block (block, &se.post);
5700 : }
5701 :
5702 31700 : if (clauses->dist_sched_kind != OMP_SCHED_NONE)
5703 : {
5704 94 : c = build_omp_clause (gfc_get_location (&where),
5705 : OMP_CLAUSE_DIST_SCHEDULE);
5706 94 : OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
5707 94 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5708 : }
5709 :
5710 31700 : if (clauses->grainsize)
5711 : {
5712 33 : tree grainsize;
5713 :
5714 33 : gfc_init_se (&se, NULL);
5715 33 : gfc_conv_expr (&se, clauses->grainsize);
5716 33 : gfc_add_block_to_block (block, &se.pre);
5717 33 : grainsize = gfc_evaluate_now (se.expr, block);
5718 33 : gfc_add_block_to_block (block, &se.post);
5719 :
5720 33 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_GRAINSIZE);
5721 33 : OMP_CLAUSE_GRAINSIZE_EXPR (c) = grainsize;
5722 33 : if (clauses->grainsize_strict)
5723 1 : OMP_CLAUSE_GRAINSIZE_STRICT (c) = 1;
5724 33 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5725 : }
5726 :
5727 31700 : if (clauses->num_tasks)
5728 : {
5729 25 : tree num_tasks;
5730 :
5731 25 : gfc_init_se (&se, NULL);
5732 25 : gfc_conv_expr (&se, clauses->num_tasks);
5733 25 : gfc_add_block_to_block (block, &se.pre);
5734 25 : num_tasks = gfc_evaluate_now (se.expr, block);
5735 25 : gfc_add_block_to_block (block, &se.post);
5736 :
5737 25 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_TASKS);
5738 25 : OMP_CLAUSE_NUM_TASKS_EXPR (c) = num_tasks;
5739 25 : if (clauses->num_tasks_strict)
5740 1 : OMP_CLAUSE_NUM_TASKS_STRICT (c) = 1;
5741 25 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5742 : }
5743 :
5744 31700 : if (clauses->priority)
5745 : {
5746 34 : tree priority;
5747 :
5748 34 : gfc_init_se (&se, NULL);
5749 34 : gfc_conv_expr (&se, clauses->priority);
5750 34 : gfc_add_block_to_block (block, &se.pre);
5751 34 : priority = gfc_evaluate_now (se.expr, block);
5752 34 : gfc_add_block_to_block (block, &se.post);
5753 :
5754 34 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PRIORITY);
5755 34 : OMP_CLAUSE_PRIORITY_EXPR (c) = priority;
5756 34 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5757 : }
5758 :
5759 31700 : if (clauses->detach)
5760 : {
5761 116 : tree detach;
5762 :
5763 116 : gfc_init_se (&se, NULL);
5764 116 : gfc_conv_expr (&se, clauses->detach);
5765 116 : gfc_add_block_to_block (block, &se.pre);
5766 116 : detach = se.expr;
5767 116 : gfc_add_block_to_block (block, &se.post);
5768 :
5769 116 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DETACH);
5770 116 : TREE_ADDRESSABLE (detach) = 1;
5771 116 : OMP_CLAUSE_DECL (c) = detach;
5772 116 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5773 : }
5774 :
5775 31700 : if (clauses->filter)
5776 : {
5777 31 : tree filter;
5778 :
5779 31 : gfc_init_se (&se, NULL);
5780 31 : gfc_conv_expr (&se, clauses->filter);
5781 31 : gfc_add_block_to_block (block, &se.pre);
5782 31 : filter = gfc_evaluate_now (se.expr, block);
5783 31 : gfc_add_block_to_block (block, &se.post);
5784 :
5785 31 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FILTER);
5786 31 : OMP_CLAUSE_FILTER_EXPR (c) = filter;
5787 31 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5788 : }
5789 :
5790 31700 : if (clauses->hint)
5791 : {
5792 8 : tree hint;
5793 :
5794 8 : gfc_init_se (&se, NULL);
5795 8 : gfc_conv_expr (&se, clauses->hint);
5796 8 : gfc_add_block_to_block (block, &se.pre);
5797 8 : hint = gfc_evaluate_now (se.expr, block);
5798 8 : gfc_add_block_to_block (block, &se.post);
5799 :
5800 8 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_HINT);
5801 8 : OMP_CLAUSE_HINT_EXPR (c) = hint;
5802 8 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5803 : }
5804 :
5805 31700 : if (clauses->simd)
5806 : {
5807 22 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMD);
5808 22 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5809 : }
5810 31700 : if (clauses->threads)
5811 : {
5812 11 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_THREADS);
5813 11 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5814 : }
5815 31700 : if (clauses->nogroup)
5816 : {
5817 13 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOGROUP);
5818 13 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5819 : }
5820 :
5821 221900 : for (int i = 0; i < OMP_DEFAULTMAP_CAT_NUM; i++)
5822 : {
5823 190200 : if (clauses->defaultmap[i] == OMP_DEFAULTMAP_UNSET)
5824 190049 : continue;
5825 151 : enum omp_clause_defaultmap_kind behavior, category;
5826 151 : switch ((gfc_omp_defaultmap_category) i)
5827 : {
5828 : case OMP_DEFAULTMAP_CAT_UNCATEGORIZED:
5829 : category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
5830 : break;
5831 : case OMP_DEFAULTMAP_CAT_ALL:
5832 : category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL;
5833 : break;
5834 : case OMP_DEFAULTMAP_CAT_SCALAR:
5835 : category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR;
5836 : break;
5837 : case OMP_DEFAULTMAP_CAT_AGGREGATE:
5838 : category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE;
5839 : break;
5840 : case OMP_DEFAULTMAP_CAT_ALLOCATABLE:
5841 : category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALLOCATABLE;
5842 : break;
5843 : case OMP_DEFAULTMAP_CAT_POINTER:
5844 : category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER;
5845 : break;
5846 : default: gcc_unreachable ();
5847 : }
5848 151 : switch (clauses->defaultmap[i])
5849 : {
5850 : case OMP_DEFAULTMAP_ALLOC:
5851 : behavior = OMP_CLAUSE_DEFAULTMAP_ALLOC;
5852 : break;
5853 : case OMP_DEFAULTMAP_TO: behavior = OMP_CLAUSE_DEFAULTMAP_TO; break;
5854 : case OMP_DEFAULTMAP_FROM: behavior = OMP_CLAUSE_DEFAULTMAP_FROM; break;
5855 : case OMP_DEFAULTMAP_TOFROM:
5856 : behavior = OMP_CLAUSE_DEFAULTMAP_TOFROM;
5857 : break;
5858 : case OMP_DEFAULTMAP_FIRSTPRIVATE:
5859 : behavior = OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
5860 : break;
5861 : case OMP_DEFAULTMAP_PRESENT:
5862 : behavior = OMP_CLAUSE_DEFAULTMAP_PRESENT;
5863 : break;
5864 : case OMP_DEFAULTMAP_NONE: behavior = OMP_CLAUSE_DEFAULTMAP_NONE; break;
5865 : case OMP_DEFAULTMAP_DEFAULT:
5866 : behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
5867 : break;
5868 0 : default: gcc_unreachable ();
5869 : }
5870 151 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEFAULTMAP);
5871 151 : OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, behavior, category);
5872 151 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5873 : }
5874 :
5875 31700 : if (clauses->doacross_source)
5876 : {
5877 132 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DOACROSS);
5878 132 : OMP_CLAUSE_DOACROSS_KIND (c) = OMP_CLAUSE_DOACROSS_SOURCE;
5879 132 : OMP_CLAUSE_DOACROSS_DEPEND (c) = clauses->depend_source;
5880 132 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5881 : }
5882 :
5883 31700 : if (clauses->async)
5884 : {
5885 549 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ASYNC);
5886 549 : if (clauses->async_expr)
5887 549 : OMP_CLAUSE_ASYNC_EXPR (c)
5888 1098 : = gfc_convert_expr_to_tree (block, clauses->async_expr);
5889 : else
5890 0 : OMP_CLAUSE_ASYNC_EXPR (c) = NULL;
5891 549 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5892 : }
5893 31700 : if (clauses->seq)
5894 : {
5895 140 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SEQ);
5896 140 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5897 : }
5898 31700 : if (clauses->par_auto)
5899 : {
5900 62 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_AUTO);
5901 62 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5902 : }
5903 31700 : if (clauses->if_present)
5904 : {
5905 23 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF_PRESENT);
5906 23 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5907 : }
5908 31700 : if (clauses->finalize)
5909 : {
5910 23 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FINALIZE);
5911 23 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5912 : }
5913 31700 : if (clauses->independent)
5914 : {
5915 239 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_INDEPENDENT);
5916 239 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5917 : }
5918 31700 : if (clauses->wait_list)
5919 : {
5920 : gfc_expr_list *el;
5921 :
5922 317 : for (el = clauses->wait_list; el; el = el->next)
5923 : {
5924 172 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_WAIT);
5925 172 : OMP_CLAUSE_DECL (c) = gfc_convert_expr_to_tree (block, el->expr);
5926 172 : OMP_CLAUSE_CHAIN (c) = omp_clauses;
5927 172 : omp_clauses = c;
5928 : }
5929 : }
5930 31700 : if (clauses->num_gangs_expr)
5931 : {
5932 666 : tree num_gangs_var
5933 666 : = gfc_convert_expr_to_tree (block, clauses->num_gangs_expr);
5934 666 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_GANGS);
5935 666 : OMP_CLAUSE_NUM_GANGS_EXPR (c) = num_gangs_var;
5936 666 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5937 : }
5938 31700 : if (clauses->num_workers_expr)
5939 : {
5940 583 : tree num_workers_var
5941 583 : = gfc_convert_expr_to_tree (block, clauses->num_workers_expr);
5942 583 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_WORKERS);
5943 583 : OMP_CLAUSE_NUM_WORKERS_EXPR (c) = num_workers_var;
5944 583 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5945 : }
5946 31700 : if (clauses->vector_length_expr)
5947 : {
5948 553 : tree vector_length_var
5949 553 : = gfc_convert_expr_to_tree (block, clauses->vector_length_expr);
5950 553 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_VECTOR_LENGTH);
5951 553 : OMP_CLAUSE_VECTOR_LENGTH_EXPR (c) = vector_length_var;
5952 553 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5953 : }
5954 31700 : if (clauses->tile_list)
5955 : {
5956 : tree list = NULL_TREE;
5957 174 : for (gfc_expr_list *el = clauses->tile_list; el; el = el->next)
5958 114 : list = tree_cons (NULL_TREE, gfc_convert_expr_to_tree (block, el->expr),
5959 : list);
5960 :
5961 60 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_TILE);
5962 60 : OMP_CLAUSE_TILE_LIST (c) = nreverse (list);
5963 60 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5964 : }
5965 31700 : if (clauses->vector)
5966 : {
5967 835 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_VECTOR);
5968 835 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5969 :
5970 835 : if (clauses->vector_expr)
5971 : {
5972 119 : tree vector_var
5973 119 : = gfc_convert_expr_to_tree (block, clauses->vector_expr);
5974 119 : OMP_CLAUSE_VECTOR_EXPR (c) = vector_var;
5975 :
5976 : /* TODO: We're not capturing location information for individual
5977 : clauses. However, if we have an expression attached to the
5978 : clause, that one provides better location information. */
5979 238 : OMP_CLAUSE_LOCATION (c)
5980 119 : = gfc_get_location (&clauses->vector_expr->where);
5981 : }
5982 : }
5983 31700 : if (clauses->worker)
5984 : {
5985 730 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_WORKER);
5986 730 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
5987 :
5988 730 : if (clauses->worker_expr)
5989 : {
5990 89 : tree worker_var
5991 89 : = gfc_convert_expr_to_tree (block, clauses->worker_expr);
5992 89 : OMP_CLAUSE_WORKER_EXPR (c) = worker_var;
5993 :
5994 : /* TODO: We're not capturing location information for individual
5995 : clauses. However, if we have an expression attached to the
5996 : clause, that one provides better location information. */
5997 178 : OMP_CLAUSE_LOCATION (c)
5998 89 : = gfc_get_location (&clauses->worker_expr->where);
5999 : }
6000 : }
6001 31700 : if (clauses->gang)
6002 : {
6003 1010 : tree arg;
6004 1010 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_GANG);
6005 1010 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
6006 :
6007 1010 : if (clauses->gang_num_expr)
6008 : {
6009 101 : arg = gfc_convert_expr_to_tree (block, clauses->gang_num_expr);
6010 101 : OMP_CLAUSE_GANG_EXPR (c) = arg;
6011 :
6012 : /* TODO: We're not capturing location information for individual
6013 : clauses. However, if we have an expression attached to the
6014 : clause, that one provides better location information. */
6015 202 : OMP_CLAUSE_LOCATION (c)
6016 101 : = gfc_get_location (&clauses->gang_num_expr->where);
6017 : }
6018 :
6019 1010 : if (clauses->gang_static)
6020 : {
6021 15 : arg = clauses->gang_static_expr
6022 104 : ? gfc_convert_expr_to_tree (block, clauses->gang_static_expr)
6023 : : integer_minus_one_node;
6024 104 : OMP_CLAUSE_GANG_STATIC_EXPR (c) = arg;
6025 : }
6026 : }
6027 31700 : if (clauses->bind != OMP_BIND_UNSET)
6028 : {
6029 30 : c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_BIND);
6030 30 : omp_clauses = gfc_trans_add_clause (c, omp_clauses);
6031 30 : switch (clauses->bind)
6032 : {
6033 10 : case OMP_BIND_TEAMS:
6034 10 : OMP_CLAUSE_BIND_KIND (c) = OMP_CLAUSE_BIND_TEAMS;
6035 10 : break;
6036 15 : case OMP_BIND_PARALLEL:
6037 15 : OMP_CLAUSE_BIND_KIND (c) = OMP_CLAUSE_BIND_PARALLEL;
6038 15 : break;
6039 5 : case OMP_BIND_THREAD:
6040 5 : OMP_CLAUSE_BIND_KIND (c) = OMP_CLAUSE_BIND_THREAD;
6041 5 : break;
6042 0 : default:
6043 0 : gcc_unreachable ();
6044 : }
6045 : }
6046 : /* OpenACC 'nohost' clauses cannot appear here. */
6047 31700 : gcc_checking_assert (!clauses->nohost);
6048 :
6049 31700 : return nreverse (omp_clauses);
6050 : }
6051 :
6052 : /* Like gfc_trans_code, but force creation of a BIND_EXPR around it. */
6053 :
6054 : static tree
6055 21061 : gfc_trans_omp_code (gfc_code *code, bool force_empty)
6056 : {
6057 21061 : tree stmt;
6058 :
6059 21061 : pushlevel ();
6060 21061 : stmt = gfc_trans_code (code);
6061 21061 : if (TREE_CODE (stmt) != BIND_EXPR)
6062 : {
6063 18801 : if (!IS_EMPTY_STMT (stmt) || force_empty)
6064 : {
6065 18711 : tree block = poplevel (1, 0);
6066 18711 : stmt = build3_v (BIND_EXPR, NULL, stmt, block);
6067 : }
6068 : else
6069 90 : poplevel (0, 0);
6070 : }
6071 : else
6072 2260 : poplevel (0, 0);
6073 21061 : return stmt;
6074 : }
6075 :
6076 : /* Translate OpenACC 'parallel', 'kernels', 'serial', 'data', 'host_data'
6077 : construct. */
6078 :
6079 : static tree
6080 4187 : gfc_trans_oacc_construct (gfc_code *code)
6081 : {
6082 4187 : stmtblock_t block;
6083 4187 : tree stmt, oacc_clauses;
6084 4187 : enum tree_code construct_code;
6085 :
6086 4187 : switch (code->op)
6087 : {
6088 : case EXEC_OACC_PARALLEL:
6089 : construct_code = OACC_PARALLEL;
6090 : break;
6091 : case EXEC_OACC_KERNELS:
6092 : construct_code = OACC_KERNELS;
6093 : break;
6094 : case EXEC_OACC_SERIAL:
6095 : construct_code = OACC_SERIAL;
6096 : break;
6097 : case EXEC_OACC_DATA:
6098 : construct_code = OACC_DATA;
6099 : break;
6100 : case EXEC_OACC_HOST_DATA:
6101 : construct_code = OACC_HOST_DATA;
6102 : break;
6103 0 : default:
6104 0 : gcc_unreachable ();
6105 : }
6106 :
6107 4187 : gfc_start_block (&block);
6108 4187 : oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
6109 : code->loc, false, true);
6110 4187 : pushlevel ();
6111 4187 : stmt = gfc_trans_omp_code (code->block->next, true);
6112 4187 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6113 4187 : stmt = build2_loc (gfc_get_location (&code->loc), construct_code,
6114 : void_type_node, stmt, oacc_clauses);
6115 4187 : gfc_add_expr_to_block (&block, stmt);
6116 4187 : return gfc_finish_block (&block);
6117 : }
6118 :
6119 : /* update, enter_data, exit_data, cache. */
6120 : static tree
6121 2126 : gfc_trans_oacc_executable_directive (gfc_code *code)
6122 : {
6123 2126 : stmtblock_t block;
6124 2126 : tree stmt, oacc_clauses;
6125 2126 : enum tree_code construct_code;
6126 :
6127 2126 : switch (code->op)
6128 : {
6129 : case EXEC_OACC_UPDATE:
6130 : construct_code = OACC_UPDATE;
6131 : break;
6132 785 : case EXEC_OACC_ENTER_DATA:
6133 785 : construct_code = OACC_ENTER_DATA;
6134 785 : break;
6135 573 : case EXEC_OACC_EXIT_DATA:
6136 573 : construct_code = OACC_EXIT_DATA;
6137 573 : break;
6138 76 : case EXEC_OACC_CACHE:
6139 76 : construct_code = OACC_CACHE;
6140 76 : break;
6141 0 : default:
6142 0 : gcc_unreachable ();
6143 : }
6144 :
6145 2126 : gfc_start_block (&block);
6146 2126 : oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
6147 : code->loc, false, true, code->op);
6148 2126 : stmt = build1_loc (input_location, construct_code, void_type_node,
6149 : oacc_clauses);
6150 2126 : gfc_add_expr_to_block (&block, stmt);
6151 2126 : return gfc_finish_block (&block);
6152 : }
6153 :
6154 : static tree
6155 173 : gfc_trans_oacc_wait_directive (gfc_code *code)
6156 : {
6157 173 : stmtblock_t block;
6158 173 : tree stmt, t;
6159 173 : vec<tree, va_gc> *args;
6160 173 : int nparms = 0;
6161 173 : gfc_expr_list *el;
6162 173 : gfc_omp_clauses *clauses = code->ext.omp_clauses;
6163 173 : location_t loc = input_location;
6164 :
6165 303 : for (el = clauses->wait_list; el; el = el->next)
6166 130 : nparms++;
6167 :
6168 173 : vec_alloc (args, nparms + 2);
6169 173 : stmt = builtin_decl_explicit (BUILT_IN_GOACC_WAIT);
6170 :
6171 173 : gfc_start_block (&block);
6172 :
6173 173 : if (clauses->async_expr)
6174 3 : t = gfc_convert_expr_to_tree (&block, clauses->async_expr);
6175 : else
6176 170 : t = build_int_cst (integer_type_node, -2);
6177 :
6178 173 : args->quick_push (t);
6179 173 : args->quick_push (build_int_cst (integer_type_node, nparms));
6180 :
6181 303 : for (el = clauses->wait_list; el; el = el->next)
6182 130 : args->quick_push (gfc_convert_expr_to_tree (&block, el->expr));
6183 :
6184 173 : stmt = build_call_expr_loc_vec (loc, stmt, args);
6185 173 : if (clauses->if_expr)
6186 6 : stmt = build3_loc (input_location, COND_EXPR, void_type_node,
6187 : gfc_convert_expr_to_tree (&block, clauses->if_expr),
6188 : stmt, NULL_TREE);
6189 173 : gfc_add_expr_to_block (&block, stmt);
6190 :
6191 173 : vec_free (args);
6192 :
6193 173 : return gfc_finish_block (&block);
6194 : }
6195 :
6196 : static tree gfc_trans_omp_sections (gfc_code *, gfc_omp_clauses *);
6197 : static tree gfc_trans_omp_workshare (gfc_code *, gfc_omp_clauses *);
6198 :
6199 : static tree
6200 35 : gfc_trans_omp_allocators (gfc_code *code)
6201 : {
6202 35 : static bool warned = false;
6203 35 : gfc_omp_namelist *omp_allocate
6204 35 : = code->ext.omp_clauses->lists[OMP_LIST_ALLOCATE];
6205 35 : if (!flag_openmp_allocators && !warned)
6206 : {
6207 3 : omp_allocate = NULL;
6208 3 : gfc_error ("%<!$OMP %s%> at %L requires %<-fopenmp-allocators%>",
6209 3 : code->op == EXEC_OMP_ALLOCATE ? "ALLOCATE" : "ALLOCATORS",
6210 : &code->loc);
6211 3 : warning (0, "All files that might deallocate such a variable must be "
6212 : "compiled with %<-fopenmp-allocators%>");
6213 3 : inform (UNKNOWN_LOCATION,
6214 : "This includes explicit DEALLOCATE, reallocation on intrinsic "
6215 : "assignment, INTENT(OUT) for allocatable dummy arguments, and "
6216 : "reallocation of allocatable components allocated with an "
6217 : "OpenMP allocator");
6218 3 : warned = true;
6219 : }
6220 35 : return gfc_trans_allocate (code->block->next, omp_allocate);
6221 : }
6222 :
6223 : static tree
6224 10 : gfc_trans_omp_assume (gfc_code *code)
6225 : {
6226 10 : stmtblock_t block;
6227 10 : gfc_init_block (&block);
6228 10 : gfc_omp_assumptions *assume = code->ext.omp_clauses->assume;
6229 10 : if (assume)
6230 19 : for (gfc_expr_list *el = assume->holds; el; el = el->next)
6231 : {
6232 9 : location_t loc = gfc_get_location (&el->expr->where);
6233 9 : gfc_se se;
6234 9 : gfc_init_se (&se, NULL);
6235 9 : gfc_conv_expr (&se, el->expr);
6236 9 : tree t;
6237 9 : if (se.pre.head == NULL_TREE && se.post.head == NULL_TREE)
6238 8 : t = se.expr;
6239 : else
6240 : {
6241 1 : tree var = create_tmp_var_raw (boolean_type_node);
6242 1 : DECL_CONTEXT (var) = current_function_decl;
6243 1 : stmtblock_t block2;
6244 1 : gfc_init_block (&block2);
6245 1 : gfc_add_block_to_block (&block2, &se.pre);
6246 1 : gfc_add_modify_loc (loc, &block2, var,
6247 : fold_convert_loc (loc, boolean_type_node,
6248 : se.expr));
6249 1 : gfc_add_block_to_block (&block2, &se.post);
6250 1 : t = gfc_finish_block (&block2);
6251 1 : t = build4 (TARGET_EXPR, boolean_type_node, var, t, NULL, NULL);
6252 : }
6253 9 : t = build_call_expr_internal_loc (loc, IFN_ASSUME,
6254 : void_type_node, 1, t);
6255 9 : gfc_add_expr_to_block (&block, t);
6256 : }
6257 10 : gfc_add_expr_to_block (&block, gfc_trans_omp_code (code->block->next, true));
6258 10 : return gfc_finish_block (&block);
6259 : }
6260 :
6261 : static tree
6262 2596 : gfc_trans_omp_atomic (gfc_code *code)
6263 : {
6264 2596 : gfc_code *atomic_code = code->block;
6265 2596 : gfc_se lse;
6266 2596 : gfc_se rse;
6267 2596 : gfc_se vse;
6268 2596 : gfc_expr *expr1, *expr2, *e, *capture_expr1 = NULL, *capture_expr2 = NULL;
6269 2596 : gfc_symbol *var;
6270 2596 : stmtblock_t block;
6271 2596 : tree lhsaddr, type, rhs, x, compare = NULL_TREE, comp_tgt = NULL_TREE;
6272 2596 : enum tree_code op = ERROR_MARK;
6273 2596 : enum tree_code aop = OMP_ATOMIC;
6274 2596 : bool var_on_left = false, else_branch = false;
6275 2596 : enum omp_memory_order mo, fail_mo;
6276 2596 : switch (atomic_code->ext.omp_clauses->memorder)
6277 : {
6278 : case OMP_MEMORDER_UNSET: mo = OMP_MEMORY_ORDER_UNSPECIFIED; break;
6279 : case OMP_MEMORDER_ACQ_REL: mo = OMP_MEMORY_ORDER_ACQ_REL; break;
6280 : case OMP_MEMORDER_ACQUIRE: mo = OMP_MEMORY_ORDER_ACQUIRE; break;
6281 : case OMP_MEMORDER_RELAXED: mo = OMP_MEMORY_ORDER_RELAXED; break;
6282 : case OMP_MEMORDER_RELEASE: mo = OMP_MEMORY_ORDER_RELEASE; break;
6283 : case OMP_MEMORDER_SEQ_CST: mo = OMP_MEMORY_ORDER_SEQ_CST; break;
6284 0 : default: gcc_unreachable ();
6285 : }
6286 2596 : switch (atomic_code->ext.omp_clauses->fail)
6287 : {
6288 : case OMP_MEMORDER_UNSET: fail_mo = OMP_FAIL_MEMORY_ORDER_UNSPECIFIED; break;
6289 14 : case OMP_MEMORDER_ACQUIRE: fail_mo = OMP_FAIL_MEMORY_ORDER_ACQUIRE; break;
6290 26 : case OMP_MEMORDER_RELAXED: fail_mo = OMP_FAIL_MEMORY_ORDER_RELAXED; break;
6291 2 : case OMP_MEMORDER_SEQ_CST: fail_mo = OMP_FAIL_MEMORY_ORDER_SEQ_CST; break;
6292 0 : default: gcc_unreachable ();
6293 : }
6294 2596 : mo = (omp_memory_order) (mo | fail_mo);
6295 :
6296 2596 : code = code->block->next;
6297 2596 : if (atomic_code->ext.omp_clauses->compare)
6298 : {
6299 144 : gfc_expr *comp_expr;
6300 144 : if (code->op == EXEC_IF)
6301 : {
6302 125 : comp_expr = code->block->expr1;
6303 125 : gcc_assert (code->block->next->op == EXEC_ASSIGN);
6304 125 : expr1 = code->block->next->expr1;
6305 125 : expr2 = code->block->next->expr2;
6306 125 : if (code->block->block)
6307 : {
6308 64 : gcc_assert (atomic_code->ext.omp_clauses->capture
6309 : && code->block->block->next->op == EXEC_ASSIGN);
6310 64 : else_branch = true;
6311 64 : aop = OMP_ATOMIC_CAPTURE_OLD;
6312 64 : capture_expr1 = code->block->block->next->expr1;
6313 64 : capture_expr2 = code->block->block->next->expr2;
6314 : }
6315 61 : else if (atomic_code->ext.omp_clauses->capture)
6316 : {
6317 19 : gcc_assert (code->next->op == EXEC_ASSIGN);
6318 19 : aop = OMP_ATOMIC_CAPTURE_NEW;
6319 19 : capture_expr1 = code->next->expr1;
6320 19 : capture_expr2 = code->next->expr2;
6321 : }
6322 : }
6323 : else
6324 : {
6325 19 : gcc_assert (atomic_code->ext.omp_clauses->capture
6326 : && code->op == EXEC_ASSIGN
6327 : && code->next->op == EXEC_IF);
6328 19 : aop = OMP_ATOMIC_CAPTURE_OLD;
6329 19 : capture_expr1 = code->expr1;
6330 19 : capture_expr2 = code->expr2;
6331 19 : expr1 = code->next->block->next->expr1;
6332 19 : expr2 = code->next->block->next->expr2;
6333 19 : comp_expr = code->next->block->expr1;
6334 : }
6335 144 : gfc_init_se (&lse, NULL);
6336 144 : gfc_conv_expr (&lse, comp_expr->value.op.op2);
6337 144 : gfc_add_block_to_block (&block, &lse.pre);
6338 144 : compare = lse.expr;
6339 144 : var = expr1->symtree->n.sym;
6340 : }
6341 : else
6342 : {
6343 2452 : gcc_assert (code->op == EXEC_ASSIGN);
6344 2452 : expr1 = code->expr1;
6345 2452 : expr2 = code->expr2;
6346 2452 : if (atomic_code->ext.omp_clauses->capture
6347 463 : && (expr2->expr_type == EXPR_VARIABLE
6348 245 : || (expr2->expr_type == EXPR_FUNCTION
6349 113 : && expr2->value.function.isym
6350 113 : && expr2->value.function.isym->id == GFC_ISYM_CONVERSION
6351 41 : && (expr2->value.function.actual->expr->expr_type
6352 : == EXPR_VARIABLE))))
6353 : {
6354 235 : capture_expr1 = expr1;
6355 235 : capture_expr2 = expr2;
6356 235 : expr1 = code->next->expr1;
6357 235 : expr2 = code->next->expr2;
6358 235 : aop = OMP_ATOMIC_CAPTURE_OLD;
6359 : }
6360 2217 : else if (atomic_code->ext.omp_clauses->capture)
6361 : {
6362 228 : aop = OMP_ATOMIC_CAPTURE_NEW;
6363 228 : capture_expr1 = code->next->expr1;
6364 228 : capture_expr2 = code->next->expr2;
6365 : }
6366 2452 : var = expr1->symtree->n.sym;
6367 : }
6368 :
6369 2596 : gfc_init_se (&lse, NULL);
6370 2596 : gfc_init_se (&rse, NULL);
6371 2596 : gfc_init_se (&vse, NULL);
6372 2596 : gfc_start_block (&block);
6373 :
6374 2596 : if (((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
6375 : != GFC_OMP_ATOMIC_WRITE)
6376 2190 : && expr2->expr_type == EXPR_FUNCTION
6377 472 : && expr2->value.function.isym
6378 472 : && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
6379 139 : expr2 = expr2->value.function.actual->expr;
6380 :
6381 2596 : if ((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
6382 : == GFC_OMP_ATOMIC_READ)
6383 : {
6384 494 : gfc_conv_expr (&vse, expr1);
6385 494 : gfc_add_block_to_block (&block, &vse.pre);
6386 :
6387 494 : gfc_conv_expr (&lse, expr2);
6388 494 : gfc_add_block_to_block (&block, &lse.pre);
6389 494 : type = TREE_TYPE (lse.expr);
6390 494 : lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
6391 :
6392 494 : x = build1 (OMP_ATOMIC_READ, type, lhsaddr);
6393 494 : OMP_ATOMIC_MEMORY_ORDER (x) = mo;
6394 494 : x = convert (TREE_TYPE (vse.expr), x);
6395 494 : gfc_add_modify (&block, vse.expr, x);
6396 :
6397 494 : gfc_add_block_to_block (&block, &lse.pre);
6398 494 : gfc_add_block_to_block (&block, &rse.pre);
6399 :
6400 494 : return gfc_finish_block (&block);
6401 : }
6402 :
6403 2102 : if (capture_expr2
6404 565 : && capture_expr2->expr_type == EXPR_FUNCTION
6405 21 : && capture_expr2->value.function.isym
6406 21 : && capture_expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
6407 21 : capture_expr2 = capture_expr2->value.function.actual->expr;
6408 565 : gcc_assert (!capture_expr2 || capture_expr2->expr_type == EXPR_VARIABLE);
6409 :
6410 2102 : if (aop == OMP_ATOMIC_CAPTURE_OLD)
6411 : {
6412 318 : gfc_conv_expr (&vse, capture_expr1);
6413 318 : gfc_add_block_to_block (&block, &vse.pre);
6414 318 : gfc_conv_expr (&lse, capture_expr2);
6415 318 : gfc_add_block_to_block (&block, &lse.pre);
6416 318 : gfc_init_se (&lse, NULL);
6417 : }
6418 :
6419 2102 : gfc_conv_expr (&lse, expr1);
6420 2102 : gfc_add_block_to_block (&block, &lse.pre);
6421 2102 : type = TREE_TYPE (lse.expr);
6422 2102 : lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
6423 :
6424 2102 : if (((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
6425 : == GFC_OMP_ATOMIC_WRITE)
6426 1696 : || (atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_SWAP)
6427 1674 : || compare)
6428 : {
6429 572 : gfc_conv_expr (&rse, expr2);
6430 572 : gfc_add_block_to_block (&block, &rse.pre);
6431 : }
6432 1530 : else if (expr2->expr_type == EXPR_OP)
6433 : {
6434 1184 : gfc_expr *e;
6435 1184 : switch (expr2->value.op.op)
6436 : {
6437 : case INTRINSIC_PLUS:
6438 : op = PLUS_EXPR;
6439 : break;
6440 91 : case INTRINSIC_TIMES:
6441 91 : op = MULT_EXPR;
6442 91 : break;
6443 113 : case INTRINSIC_MINUS:
6444 113 : op = MINUS_EXPR;
6445 113 : break;
6446 91 : case INTRINSIC_DIVIDE:
6447 91 : if (expr2->ts.type == BT_INTEGER)
6448 : op = TRUNC_DIV_EXPR;
6449 : else
6450 74 : op = RDIV_EXPR;
6451 : break;
6452 43 : case INTRINSIC_AND:
6453 43 : op = TRUTH_ANDIF_EXPR;
6454 43 : break;
6455 49 : case INTRINSIC_OR:
6456 49 : op = TRUTH_ORIF_EXPR;
6457 49 : break;
6458 43 : case INTRINSIC_EQV:
6459 43 : op = EQ_EXPR;
6460 43 : break;
6461 43 : case INTRINSIC_NEQV:
6462 43 : op = NE_EXPR;
6463 43 : break;
6464 0 : default:
6465 0 : gcc_unreachable ();
6466 : }
6467 1184 : e = expr2->value.op.op1;
6468 1184 : if (e->expr_type == EXPR_FUNCTION
6469 48 : && e->value.function.isym
6470 48 : && e->value.function.isym->id == GFC_ISYM_CONVERSION)
6471 48 : e = e->value.function.actual->expr;
6472 1184 : if (e->expr_type == EXPR_VARIABLE
6473 925 : && e->symtree != NULL
6474 925 : && e->symtree->n.sym == var)
6475 : {
6476 910 : expr2 = expr2->value.op.op2;
6477 910 : var_on_left = true;
6478 : }
6479 : else
6480 : {
6481 274 : e = expr2->value.op.op2;
6482 274 : if (e->expr_type == EXPR_FUNCTION
6483 48 : && e->value.function.isym
6484 48 : && e->value.function.isym->id == GFC_ISYM_CONVERSION)
6485 48 : e = e->value.function.actual->expr;
6486 274 : gcc_assert (e->expr_type == EXPR_VARIABLE
6487 : && e->symtree != NULL
6488 : && e->symtree->n.sym == var);
6489 : expr2 = expr2->value.op.op1;
6490 : var_on_left = false;
6491 : }
6492 1184 : gfc_conv_expr (&rse, expr2);
6493 1184 : gfc_add_block_to_block (&block, &rse.pre);
6494 : }
6495 : else
6496 : {
6497 346 : gcc_assert (expr2->expr_type == EXPR_FUNCTION);
6498 346 : switch (expr2->value.function.isym->id)
6499 : {
6500 : case GFC_ISYM_MIN:
6501 : op = MIN_EXPR;
6502 : break;
6503 114 : case GFC_ISYM_MAX:
6504 114 : op = MAX_EXPR;
6505 114 : break;
6506 47 : case GFC_ISYM_IAND:
6507 47 : op = BIT_AND_EXPR;
6508 47 : break;
6509 49 : case GFC_ISYM_IOR:
6510 49 : op = BIT_IOR_EXPR;
6511 49 : break;
6512 45 : case GFC_ISYM_IEOR:
6513 45 : op = BIT_XOR_EXPR;
6514 45 : break;
6515 0 : default:
6516 0 : gcc_unreachable ();
6517 : }
6518 346 : e = expr2->value.function.actual->expr;
6519 346 : if (e->expr_type == EXPR_FUNCTION
6520 13 : && e->value.function.isym
6521 13 : && e->value.function.isym->id == GFC_ISYM_CONVERSION)
6522 13 : e = e->value.function.actual->expr;
6523 346 : gcc_assert (e->expr_type == EXPR_VARIABLE
6524 : && e->symtree != NULL
6525 : && e->symtree->n.sym == var);
6526 :
6527 346 : gfc_conv_expr (&rse, expr2->value.function.actual->next->expr);
6528 346 : gfc_add_block_to_block (&block, &rse.pre);
6529 346 : if (expr2->value.function.actual->next->next != NULL)
6530 : {
6531 26 : tree accum = gfc_create_var (TREE_TYPE (rse.expr), NULL);
6532 26 : gfc_actual_arglist *arg;
6533 :
6534 26 : gfc_add_modify (&block, accum, rse.expr);
6535 64 : for (arg = expr2->value.function.actual->next->next; arg;
6536 38 : arg = arg->next)
6537 : {
6538 38 : gfc_init_block (&rse.pre);
6539 38 : gfc_conv_expr (&rse, arg->expr);
6540 38 : gfc_add_block_to_block (&block, &rse.pre);
6541 38 : x = fold_build2_loc (input_location, op, TREE_TYPE (accum),
6542 : accum, rse.expr);
6543 38 : gfc_add_modify (&block, accum, x);
6544 : }
6545 :
6546 26 : rse.expr = accum;
6547 : }
6548 :
6549 346 : expr2 = expr2->value.function.actual->next->expr;
6550 : }
6551 :
6552 2102 : lhsaddr = save_expr (lhsaddr);
6553 2102 : if (TREE_CODE (lhsaddr) != SAVE_EXPR
6554 2102 : && (TREE_CODE (lhsaddr) != ADDR_EXPR
6555 1642 : || !VAR_P (TREE_OPERAND (lhsaddr, 0))))
6556 : {
6557 : /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
6558 : it even after unsharing function body. */
6559 44 : tree var = create_tmp_var_raw (TREE_TYPE (lhsaddr));
6560 44 : DECL_CONTEXT (var) = current_function_decl;
6561 44 : lhsaddr = build4 (TARGET_EXPR, TREE_TYPE (lhsaddr), var, lhsaddr,
6562 : NULL_TREE, NULL_TREE);
6563 : }
6564 :
6565 2102 : if (compare)
6566 : {
6567 144 : tree var = create_tmp_var_raw (TREE_TYPE (lhsaddr));
6568 144 : DECL_CONTEXT (var) = current_function_decl;
6569 144 : lhsaddr = build4 (TARGET_EXPR, TREE_TYPE (lhsaddr), var, lhsaddr, NULL,
6570 : NULL);
6571 144 : lse.expr = build_fold_indirect_ref_loc (input_location, lhsaddr);
6572 144 : compare = convert (TREE_TYPE (lse.expr), compare);
6573 144 : compare = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
6574 : lse.expr, compare);
6575 : }
6576 :
6577 2102 : if (expr2->expr_type == EXPR_VARIABLE || compare)
6578 460 : rhs = rse.expr;
6579 : else
6580 1642 : rhs = gfc_evaluate_now (rse.expr, &block);
6581 :
6582 2102 : if (((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
6583 : == GFC_OMP_ATOMIC_WRITE)
6584 1696 : || (atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_SWAP)
6585 1674 : || compare)
6586 : x = rhs;
6587 : else
6588 : {
6589 1530 : x = convert (TREE_TYPE (rhs),
6590 : build_fold_indirect_ref_loc (input_location, lhsaddr));
6591 1530 : if (var_on_left)
6592 910 : x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), x, rhs);
6593 : else
6594 620 : x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), rhs, x);
6595 : }
6596 :
6597 2102 : if (TREE_CODE (TREE_TYPE (rhs)) == COMPLEX_TYPE
6598 2102 : && TREE_CODE (type) != COMPLEX_TYPE)
6599 0 : x = fold_build1_loc (input_location, REALPART_EXPR,
6600 0 : TREE_TYPE (TREE_TYPE (rhs)), x);
6601 :
6602 2102 : gfc_add_block_to_block (&block, &lse.pre);
6603 2102 : gfc_add_block_to_block (&block, &rse.pre);
6604 :
6605 2102 : if (aop == OMP_ATOMIC_CAPTURE_NEW)
6606 : {
6607 247 : gfc_conv_expr (&vse, capture_expr1);
6608 247 : gfc_add_block_to_block (&block, &vse.pre);
6609 247 : gfc_add_block_to_block (&block, &lse.pre);
6610 : }
6611 :
6612 2102 : if (compare && else_branch)
6613 : {
6614 64 : tree var2 = create_tmp_var_raw (boolean_type_node);
6615 64 : DECL_CONTEXT (var2) = current_function_decl;
6616 64 : comp_tgt = build4 (TARGET_EXPR, boolean_type_node, var2,
6617 : boolean_false_node, NULL, NULL);
6618 64 : compare = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (var2),
6619 : var2, compare);
6620 64 : TREE_OPERAND (compare, 0) = comp_tgt;
6621 64 : compare = omit_one_operand_loc (input_location, boolean_type_node,
6622 : compare, comp_tgt);
6623 : }
6624 :
6625 2102 : if (compare)
6626 144 : x = build3_loc (input_location, COND_EXPR, type, compare,
6627 : convert (type, x), lse.expr);
6628 :
6629 2102 : if (aop == OMP_ATOMIC)
6630 : {
6631 1537 : x = build2_v (OMP_ATOMIC, lhsaddr, convert (type, x));
6632 1537 : OMP_ATOMIC_MEMORY_ORDER (x) = mo;
6633 1537 : OMP_ATOMIC_WEAK (x) = atomic_code->ext.omp_clauses->weak;
6634 1537 : gfc_add_expr_to_block (&block, x);
6635 : }
6636 : else
6637 : {
6638 565 : x = build2 (aop, type, lhsaddr, convert (type, x));
6639 565 : OMP_ATOMIC_MEMORY_ORDER (x) = mo;
6640 565 : OMP_ATOMIC_WEAK (x) = atomic_code->ext.omp_clauses->weak;
6641 565 : if (compare && else_branch)
6642 : {
6643 64 : tree vtmp = create_tmp_var_raw (TREE_TYPE (x));
6644 64 : DECL_CONTEXT (vtmp) = current_function_decl;
6645 64 : x = fold_build2_loc (input_location, MODIFY_EXPR,
6646 64 : TREE_TYPE (vtmp), vtmp, x);
6647 64 : vtmp = build4 (TARGET_EXPR, TREE_TYPE (vtmp), vtmp,
6648 64 : build_zero_cst (TREE_TYPE (vtmp)), NULL, NULL);
6649 64 : TREE_OPERAND (x, 0) = vtmp;
6650 64 : tree x2 = convert (TREE_TYPE (vse.expr), vtmp);
6651 64 : x2 = fold_build2_loc (input_location, MODIFY_EXPR,
6652 64 : TREE_TYPE (vse.expr), vse.expr, x2);
6653 64 : x2 = build3_loc (input_location, COND_EXPR, void_type_node, comp_tgt,
6654 : void_node, x2);
6655 64 : x = omit_one_operand_loc (input_location, TREE_TYPE (x2), x2, x);
6656 64 : gfc_add_expr_to_block (&block, x);
6657 : }
6658 : else
6659 : {
6660 501 : x = convert (TREE_TYPE (vse.expr), x);
6661 501 : gfc_add_modify (&block, vse.expr, x);
6662 : }
6663 : }
6664 :
6665 2102 : return gfc_finish_block (&block);
6666 : }
6667 :
6668 : static tree
6669 604 : gfc_trans_omp_barrier (void)
6670 : {
6671 604 : tree decl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
6672 604 : return build_call_expr_loc (input_location, decl, 0);
6673 : }
6674 :
6675 : static tree
6676 310 : gfc_trans_omp_cancel (gfc_code *code)
6677 : {
6678 310 : int mask = 0;
6679 310 : tree ifc = boolean_true_node;
6680 310 : stmtblock_t block;
6681 310 : switch (code->ext.omp_clauses->cancel)
6682 : {
6683 : case OMP_CANCEL_PARALLEL: mask = 1; break;
6684 : case OMP_CANCEL_DO: mask = 2; break;
6685 : case OMP_CANCEL_SECTIONS: mask = 4; break;
6686 : case OMP_CANCEL_TASKGROUP: mask = 8; break;
6687 0 : default: gcc_unreachable ();
6688 : }
6689 310 : gfc_start_block (&block);
6690 310 : if (code->ext.omp_clauses->if_expr
6691 219 : || code->ext.omp_clauses->if_exprs[OMP_IF_CANCEL])
6692 : {
6693 99 : gfc_se se;
6694 99 : tree if_var;
6695 :
6696 99 : gcc_assert ((code->ext.omp_clauses->if_expr == NULL)
6697 : ^ (code->ext.omp_clauses->if_exprs[OMP_IF_CANCEL] == NULL));
6698 99 : gfc_init_se (&se, NULL);
6699 99 : gfc_conv_expr (&se, code->ext.omp_clauses->if_expr != NULL
6700 : ? code->ext.omp_clauses->if_expr
6701 : : code->ext.omp_clauses->if_exprs[OMP_IF_CANCEL]);
6702 99 : gfc_add_block_to_block (&block, &se.pre);
6703 99 : if_var = gfc_evaluate_now (se.expr, &block);
6704 99 : gfc_add_block_to_block (&block, &se.post);
6705 99 : tree type = TREE_TYPE (if_var);
6706 99 : ifc = fold_build2_loc (input_location, NE_EXPR,
6707 : boolean_type_node, if_var,
6708 : build_zero_cst (type));
6709 : }
6710 310 : tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
6711 310 : tree c_bool_type = TREE_TYPE (TREE_TYPE (decl));
6712 310 : ifc = fold_convert (c_bool_type, ifc);
6713 310 : gfc_add_expr_to_block (&block,
6714 : build_call_expr_loc (input_location, decl, 2,
6715 : build_int_cst (integer_type_node,
6716 310 : mask), ifc));
6717 310 : return gfc_finish_block (&block);
6718 : }
6719 :
6720 : static tree
6721 170 : gfc_trans_omp_cancellation_point (gfc_code *code)
6722 : {
6723 170 : int mask = 0;
6724 170 : switch (code->ext.omp_clauses->cancel)
6725 : {
6726 : case OMP_CANCEL_PARALLEL: mask = 1; break;
6727 : case OMP_CANCEL_DO: mask = 2; break;
6728 : case OMP_CANCEL_SECTIONS: mask = 4; break;
6729 : case OMP_CANCEL_TASKGROUP: mask = 8; break;
6730 0 : default: gcc_unreachable ();
6731 : }
6732 170 : tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCELLATION_POINT);
6733 170 : return build_call_expr_loc (input_location, decl, 1,
6734 340 : build_int_cst (integer_type_node, mask));
6735 : }
6736 :
6737 : static tree
6738 143 : gfc_trans_omp_critical (gfc_code *code)
6739 : {
6740 143 : stmtblock_t block;
6741 143 : tree stmt, name = NULL_TREE;
6742 143 : if (code->ext.omp_clauses->critical_name != NULL)
6743 36 : name = get_identifier (code->ext.omp_clauses->critical_name);
6744 143 : gfc_start_block (&block);
6745 143 : stmt = make_node (OMP_CRITICAL);
6746 143 : SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
6747 143 : TREE_TYPE (stmt) = void_type_node;
6748 143 : OMP_CRITICAL_BODY (stmt) = gfc_trans_code (code->block->next);
6749 143 : OMP_CRITICAL_NAME (stmt) = name;
6750 143 : OMP_CRITICAL_CLAUSES (stmt) = gfc_trans_omp_clauses (&block,
6751 : code->ext.omp_clauses,
6752 : code->loc);
6753 143 : gfc_add_expr_to_block (&block, stmt);
6754 143 : return gfc_finish_block (&block);
6755 : }
6756 :
6757 : typedef struct dovar_init_d {
6758 : gfc_symbol *sym;
6759 : tree var;
6760 : tree init;
6761 : bool non_unit_iter;
6762 : } dovar_init;
6763 :
6764 : static bool
6765 2884 : gfc_nonrect_loop_expr (stmtblock_t *pblock, gfc_se *sep, int loop_n,
6766 : gfc_code *code, gfc_expr *expr, vec<dovar_init> *inits,
6767 : int simple, gfc_expr *curr_loop_var)
6768 : {
6769 2884 : int i;
6770 4771 : for (i = 0; i < loop_n; i++)
6771 : {
6772 2441 : gcc_assert (code->ext.iterator->var->expr_type == EXPR_VARIABLE);
6773 2441 : if (gfc_find_sym_in_expr (code->ext.iterator->var->symtree->n.sym, expr))
6774 : break;
6775 1887 : code = code->block->next;
6776 : }
6777 2884 : if (i >= loop_n)
6778 : return false;
6779 :
6780 : /* Canonical format: TREE_VEC with [var, multiplier, offset]. */
6781 554 : gfc_symbol *var = code->ext.iterator->var->symtree->n.sym;
6782 :
6783 554 : tree tree_var = NULL_TREE;
6784 554 : tree a1 = integer_one_node;
6785 554 : tree a2 = integer_zero_node;
6786 :
6787 554 : if (!simple)
6788 : {
6789 : /* FIXME: Handle non-const iter steps, cf. PR fortran/110735. */
6790 6 : sorry_at (gfc_get_location (&curr_loop_var->where),
6791 : "non-rectangular loop nest with non-constant step for %qs",
6792 3 : curr_loop_var->symtree->n.sym->name);
6793 3 : return false;
6794 : }
6795 :
6796 : dovar_init *di;
6797 : unsigned ix;
6798 551 : FOR_EACH_VEC_ELT (*inits, ix, di)
6799 18 : if (di->sym == var)
6800 : {
6801 18 : if (!di->non_unit_iter)
6802 : {
6803 16 : tree_var = di->init;
6804 16 : gcc_assert (DECL_P (tree_var));
6805 : break;
6806 : }
6807 : else
6808 : {
6809 : /* FIXME: Handle non-const iter steps, cf. PR fortran/110735. */
6810 2 : sorry_at (gfc_get_location (&code->loc),
6811 : "non-rectangular loop nest with non-constant step "
6812 : "for %qs", var->name);
6813 2 : inform (gfc_get_location (&expr->where), "Used here");
6814 2 : return false;
6815 : }
6816 : }
6817 533 : if (tree_var == NULL_TREE)
6818 533 : tree_var = var->backend_decl;
6819 :
6820 549 : if (expr->expr_type == EXPR_VARIABLE)
6821 54 : gcc_assert (expr->symtree->n.sym == var);
6822 495 : else if (expr->expr_type != EXPR_OP
6823 495 : || (expr->value.op.op != INTRINSIC_TIMES
6824 479 : && expr->value.op.op != INTRINSIC_PLUS
6825 359 : && expr->value.op.op != INTRINSIC_MINUS))
6826 0 : gcc_unreachable ();
6827 : else
6828 : {
6829 495 : gfc_se se;
6830 495 : gfc_expr *et = NULL, *eo = NULL, *e = expr;
6831 495 : if (expr->value.op.op != INTRINSIC_TIMES)
6832 : {
6833 479 : if (gfc_find_sym_in_expr (var, expr->value.op.op1))
6834 : {
6835 431 : e = expr->value.op.op1;
6836 431 : eo = expr->value.op.op2;
6837 : }
6838 : else
6839 : {
6840 48 : eo = expr->value.op.op1;
6841 48 : e = expr->value.op.op2;
6842 : }
6843 : }
6844 495 : if (e->value.op.op == INTRINSIC_TIMES)
6845 : {
6846 91 : if (e->value.op.op1->expr_type == EXPR_VARIABLE
6847 91 : && e->value.op.op1->symtree->n.sym == var)
6848 51 : et = e->value.op.op2;
6849 : else
6850 : {
6851 40 : et = e->value.op.op1;
6852 40 : gcc_assert (e->value.op.op2->expr_type == EXPR_VARIABLE
6853 : && e->value.op.op2->symtree->n.sym == var);
6854 : }
6855 : }
6856 : else
6857 404 : gcc_assert (e->expr_type == EXPR_VARIABLE && e->symtree->n.sym == var);
6858 91 : if (et != NULL)
6859 : {
6860 91 : gfc_init_se (&se, NULL);
6861 91 : gfc_conv_expr_val (&se, et);
6862 91 : gfc_add_block_to_block (pblock, &se.pre);
6863 91 : a1 = se.expr;
6864 : }
6865 495 : if (eo != NULL)
6866 : {
6867 479 : gfc_init_se (&se, NULL);
6868 479 : gfc_conv_expr_val (&se, eo);
6869 479 : gfc_add_block_to_block (pblock, &se.pre);
6870 479 : a2 = se.expr;
6871 479 : if (expr->value.op.op == INTRINSIC_MINUS && expr->value.op.op2 == eo)
6872 : /* outer-var - a2. */
6873 335 : a2 = fold_build1 (NEGATE_EXPR, TREE_TYPE (a2), a2);
6874 144 : else if (expr->value.op.op == INTRINSIC_MINUS)
6875 : /* a2 - outer-var. */
6876 24 : a1 = fold_build1 (NEGATE_EXPR, TREE_TYPE (a1), a1);
6877 : }
6878 495 : a1 = DECL_P (a1) ? a1 : gfc_evaluate_now (a1, pblock);
6879 495 : a2 = DECL_P (a2) ? a2 : gfc_evaluate_now (a2, pblock);
6880 : }
6881 :
6882 549 : gfc_init_se (sep, NULL);
6883 549 : sep->expr = make_tree_vec (3);
6884 549 : TREE_VEC_ELT (sep->expr, 0) = tree_var;
6885 549 : TREE_VEC_ELT (sep->expr, 1) = fold_convert (TREE_TYPE (tree_var), a1);
6886 549 : TREE_VEC_ELT (sep->expr, 2) = fold_convert (TREE_TYPE (tree_var), a2);
6887 :
6888 549 : return true;
6889 : }
6890 :
6891 : int
6892 708 : gfc_expr_list_len (gfc_expr_list *list)
6893 : {
6894 708 : unsigned len = 0;
6895 2092 : for (; list; list = list->next)
6896 1384 : len++;
6897 :
6898 708 : return len;
6899 : }
6900 :
6901 : static tree
6902 9528 : gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
6903 : gfc_omp_clauses *do_clauses, tree par_clauses)
6904 : {
6905 9528 : gfc_se se;
6906 9528 : tree dovar, stmt, from, to, step, type, init, cond, incr, orig_decls;
6907 9528 : tree local_dovar = NULL_TREE, cycle_label, tmp, omp_clauses;
6908 9528 : stmtblock_t block;
6909 9528 : stmtblock_t body;
6910 9528 : gfc_omp_clauses *clauses = code->ext.omp_clauses;
6911 9528 : int i, collapse = clauses->collapse;
6912 9528 : vec<dovar_init> inits = vNULL;
6913 9528 : dovar_init *di;
6914 9528 : unsigned ix;
6915 9528 : vec<tree, va_heap, vl_embed> *saved_doacross_steps = doacross_steps;
6916 19056 : gfc_expr_list *oacc_tile
6917 9528 : = do_clauses ? do_clauses->tile_list : clauses->tile_list;
6918 9528 : gfc_expr_list *sizes
6919 : = do_clauses ? do_clauses->sizes_list : clauses->sizes_list;
6920 9528 : gfc_code *orig_code = code;
6921 :
6922 : /* Both collapsed and tiled loops are lowered the same way. In
6923 : OpenACC, those clauses are not compatible, so prioritize the tile
6924 : clause, if present. */
6925 9528 : if (oacc_tile)
6926 60 : collapse = gfc_expr_list_len (oacc_tile);
6927 9468 : else if (sizes)
6928 120 : collapse = gfc_expr_list_len (sizes);
6929 :
6930 9528 : doacross_steps = NULL;
6931 9528 : if (clauses->orderedc)
6932 134 : collapse = clauses->orderedc;
6933 9528 : if (collapse <= 0)
6934 : collapse = 1;
6935 :
6936 9528 : code = code->block->next;
6937 :
6938 9528 : init = make_tree_vec (collapse);
6939 9528 : cond = make_tree_vec (collapse);
6940 9528 : incr = make_tree_vec (collapse);
6941 9528 : orig_decls = clauses->ordered ? make_tree_vec (collapse) : NULL_TREE;
6942 :
6943 9528 : if (pblock == NULL)
6944 : {
6945 6033 : gfc_start_block (&block);
6946 6033 : pblock = █
6947 : }
6948 :
6949 : /* simd schedule modifier is only useful for composite do simd and other
6950 : constructs including that, where gfc_trans_omp_do is only called
6951 : on the simd construct and DO's clauses are translated elsewhere. */
6952 9528 : do_clauses->sched_simd = false;
6953 :
6954 9528 : omp_clauses = gfc_trans_omp_clauses (pblock, do_clauses, code->loc);
6955 :
6956 21547 : for (i = 0; i < collapse; i++)
6957 : {
6958 12019 : int simple = 0;
6959 12019 : int dovar_found = 0;
6960 12019 : tree dovar_decl;
6961 :
6962 12019 : if (code->op == EXEC_OMP_TILE || code->op == EXEC_OMP_UNROLL)
6963 : {
6964 320 : TREE_VEC_ELT (init, i) = NULL_TREE;
6965 320 : TREE_VEC_ELT (cond, i) = NULL_TREE;
6966 320 : TREE_VEC_ELT (incr, i) = NULL_TREE;
6967 320 : TREE_VEC_ELT (incr, i) = NULL_TREE;
6968 320 : if (orig_decls)
6969 2 : TREE_VEC_ELT (orig_decls, i) = NULL_TREE;
6970 320 : continue;
6971 : }
6972 11699 : gcc_assert (code->op == EXEC_DO);
6973 11699 : if (clauses)
6974 : {
6975 11699 : gfc_omp_namelist *n = NULL;
6976 11699 : if (op == EXEC_OMP_SIMD && collapse == 1)
6977 936 : for (n = clauses->lists[OMP_LIST_LINEAR];
6978 1236 : n != NULL; n = n->next)
6979 443 : if (code->ext.iterator->var->symtree->n.sym == n->sym)
6980 : {
6981 : dovar_found = 3;
6982 : break;
6983 : }
6984 11699 : if (n == NULL && op != EXEC_OMP_DISTRIBUTE)
6985 11462 : for (n = clauses->lists[OMP_LIST_LASTPRIVATE];
6986 13521 : n != NULL; n = n->next)
6987 3436 : if (code->ext.iterator->var->symtree->n.sym == n->sym)
6988 : {
6989 : dovar_found = 2;
6990 : break;
6991 : }
6992 11699 : if (n == NULL)
6993 11435 : for (n = clauses->lists[OMP_LIST_PRIVATE]; n != NULL; n = n->next)
6994 6990 : if (code->ext.iterator->var->symtree->n.sym == n->sym)
6995 : {
6996 : dovar_found = 1;
6997 : break;
6998 : }
6999 : }
7000 :
7001 : /* Evaluate all the expressions in the iterator. */
7002 11699 : gfc_init_se (&se, NULL);
7003 11699 : gfc_conv_expr_lhs (&se, code->ext.iterator->var);
7004 11699 : gfc_add_block_to_block (pblock, &se.pre);
7005 11699 : local_dovar = dovar_decl = dovar = se.expr;
7006 11699 : type = TREE_TYPE (dovar);
7007 11699 : gcc_assert (TREE_CODE (type) == INTEGER_TYPE);
7008 :
7009 11699 : gfc_init_se (&se, NULL);
7010 11699 : gfc_conv_expr_val (&se, code->ext.iterator->step);
7011 11699 : gfc_add_block_to_block (pblock, &se.pre);
7012 11699 : step = gfc_evaluate_now (se.expr, pblock);
7013 :
7014 11699 : if (TREE_CODE (step) == INTEGER_CST)
7015 11108 : simple = tree_int_cst_sgn (step);
7016 :
7017 11699 : gfc_init_se (&se, NULL);
7018 11699 : if (!clauses->non_rectangular
7019 13141 : || !gfc_nonrect_loop_expr (pblock, &se, i, orig_code->block->next,
7020 : code->ext.iterator->start, &inits, simple,
7021 1442 : code->ext.iterator->var))
7022 : {
7023 11383 : gfc_conv_expr_val (&se, code->ext.iterator->start);
7024 11383 : gfc_add_block_to_block (pblock, &se.pre);
7025 11383 : if (!DECL_P (se.expr))
7026 10985 : se.expr = gfc_evaluate_now (se.expr, pblock);
7027 : }
7028 11699 : from = se.expr;
7029 :
7030 11699 : gfc_init_se (&se, NULL);
7031 11699 : if (!clauses->non_rectangular
7032 13141 : || !gfc_nonrect_loop_expr (pblock, &se, i, orig_code->block->next,
7033 : code->ext.iterator->end, &inits, simple,
7034 1442 : code->ext.iterator->var))
7035 : {
7036 11466 : gfc_conv_expr_val (&se, code->ext.iterator->end);
7037 11466 : gfc_add_block_to_block (pblock, &se.pre);
7038 11466 : if (!DECL_P (se.expr))
7039 10231 : se.expr = gfc_evaluate_now (se.expr, pblock);
7040 : }
7041 11699 : to = se.expr;
7042 :
7043 11699 : if (!DECL_P (dovar))
7044 38 : dovar_decl
7045 38 : = gfc_trans_omp_variable (code->ext.iterator->var->symtree->n.sym,
7046 : false);
7047 11699 : if (simple && !DECL_P (dovar))
7048 : {
7049 38 : const char *name = code->ext.iterator->var->symtree->n.sym->name;
7050 38 : local_dovar = gfc_create_var (type, name);
7051 38 : dovar_init e = {code->ext.iterator->var->symtree->n.sym,
7052 38 : dovar, local_dovar, false};
7053 38 : inits.safe_push (e);
7054 : }
7055 : /* Loop body. */
7056 11699 : if (simple)
7057 : {
7058 11108 : TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, local_dovar, from);
7059 : /* The condition should not be folded. */
7060 11660 : TREE_VEC_ELT (cond, i) = build2_loc (input_location, simple > 0
7061 : ? LE_EXPR : GE_EXPR,
7062 : logical_type_node, local_dovar,
7063 : to);
7064 11108 : TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR,
7065 : type, local_dovar, step);
7066 11108 : TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location,
7067 : MODIFY_EXPR,
7068 : type, local_dovar,
7069 11108 : TREE_VEC_ELT (incr, i));
7070 11108 : if (orig_decls && !clauses->orderedc)
7071 : orig_decls = NULL;
7072 383 : else if (orig_decls)
7073 383 : TREE_VEC_ELT (orig_decls, i) = dovar_decl;
7074 : }
7075 : else
7076 : {
7077 : /* STEP is not 1 or -1. Use:
7078 : for (count = 0; count < (to + step - from) / step; count++)
7079 : {
7080 : dovar = from + count * step;
7081 : body;
7082 : cycle_label:;
7083 : } */
7084 591 : tmp = fold_build2_loc (input_location, MINUS_EXPR, type, step, from);
7085 591 : tmp = fold_build2_loc (input_location, PLUS_EXPR, type, to, tmp);
7086 591 : tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, type, tmp,
7087 : step);
7088 591 : tmp = gfc_evaluate_now (tmp, pblock);
7089 591 : local_dovar = gfc_create_var (type, "count");
7090 591 : TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, local_dovar,
7091 : build_int_cst (type, 0));
7092 : /* The condition should not be folded. */
7093 591 : TREE_VEC_ELT (cond, i) = build2_loc (input_location, LT_EXPR,
7094 : logical_type_node,
7095 : local_dovar, tmp);
7096 591 : TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR,
7097 : type, local_dovar,
7098 : build_int_cst (type, 1));
7099 591 : TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location,
7100 : MODIFY_EXPR, type,
7101 : local_dovar,
7102 591 : TREE_VEC_ELT (incr, i));
7103 :
7104 : /* Initialize DOVAR. */
7105 591 : tmp = fold_build2_loc (input_location, MULT_EXPR, type, local_dovar,
7106 : step);
7107 591 : tmp = fold_build2_loc (input_location, PLUS_EXPR, type, from, tmp);
7108 591 : dovar_init e = {code->ext.iterator->var->symtree->n.sym,
7109 591 : dovar, tmp, true};
7110 591 : inits.safe_push (e);
7111 591 : if (clauses->orderedc)
7112 : {
7113 192 : if (doacross_steps == NULL)
7114 47 : vec_safe_grow_cleared (doacross_steps, clauses->orderedc, true);
7115 192 : (*doacross_steps)[i] = step;
7116 : }
7117 591 : if (orig_decls)
7118 198 : TREE_VEC_ELT (orig_decls, i) = dovar_decl;
7119 : }
7120 :
7121 11699 : if (dovar_found == 3
7122 11699 : && op == EXEC_OMP_SIMD
7123 143 : && collapse == 1
7124 143 : && local_dovar != dovar)
7125 : {
7126 120 : for (tmp = omp_clauses; tmp; tmp = OMP_CLAUSE_CHAIN (tmp))
7127 120 : if (OMP_CLAUSE_CODE (tmp) == OMP_CLAUSE_LINEAR
7128 120 : && OMP_CLAUSE_DECL (tmp) == dovar)
7129 : {
7130 30 : OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
7131 30 : break;
7132 : }
7133 : }
7134 11699 : if (!dovar_found && op == EXEC_OMP_SIMD)
7135 : {
7136 1356 : if (collapse == 1)
7137 : {
7138 783 : tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
7139 783 : OMP_CLAUSE_LINEAR_STEP (tmp) = step;
7140 783 : OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
7141 783 : OMP_CLAUSE_DECL (tmp) = dovar_decl;
7142 783 : omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
7143 783 : if (local_dovar != dovar)
7144 : dovar_found = 3;
7145 : }
7146 : }
7147 10343 : else if (!dovar_found && local_dovar != dovar)
7148 : {
7149 260 : tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
7150 260 : OMP_CLAUSE_DECL (tmp) = dovar_decl;
7151 260 : omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
7152 : }
7153 11669 : if (dovar_found > 1)
7154 : {
7155 1550 : tree c = NULL;
7156 :
7157 1550 : tmp = NULL;
7158 1550 : if (local_dovar != dovar)
7159 : {
7160 : /* If dovar is lastprivate, but different counter is used,
7161 : dovar += step needs to be added to
7162 : OMP_CLAUSE_LASTPRIVATE_STMT, otherwise the copied dovar
7163 : will have the value on entry of the last loop, rather
7164 : than value after iterator increment. */
7165 243 : if (clauses->orderedc)
7166 : {
7167 60 : if (clauses->collapse <= 1 || i >= clauses->collapse)
7168 : tmp = local_dovar;
7169 : else
7170 36 : tmp = fold_build2_loc (input_location, PLUS_EXPR,
7171 : type, local_dovar,
7172 : build_one_cst (type));
7173 60 : tmp = fold_build2_loc (input_location, MULT_EXPR, type,
7174 : tmp, step);
7175 60 : tmp = fold_build2_loc (input_location, PLUS_EXPR, type,
7176 : from, tmp);
7177 : }
7178 : else
7179 183 : tmp = fold_build2_loc (input_location, PLUS_EXPR, type,
7180 : dovar, step);
7181 243 : tmp = fold_build2_loc (input_location, MODIFY_EXPR, type,
7182 : dovar, tmp);
7183 934 : for (c = omp_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
7184 613 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7185 613 : && OMP_CLAUSE_DECL (c) == dovar_decl)
7186 : {
7187 105 : OMP_CLAUSE_LASTPRIVATE_STMT (c) = tmp;
7188 105 : break;
7189 : }
7190 508 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
7191 508 : && OMP_CLAUSE_DECL (c) == dovar_decl)
7192 : {
7193 60 : OMP_CLAUSE_LINEAR_STMT (c) = tmp;
7194 60 : break;
7195 : }
7196 : }
7197 1550 : if (c == NULL && op == EXEC_OMP_DO && par_clauses != NULL)
7198 : {
7199 892 : for (c = par_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
7200 892 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7201 892 : && OMP_CLAUSE_DECL (c) == dovar_decl)
7202 : {
7203 406 : tree l = build_omp_clause (input_location,
7204 : OMP_CLAUSE_LASTPRIVATE);
7205 406 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
7206 4 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (l) = 1;
7207 406 : OMP_CLAUSE_DECL (l) = dovar_decl;
7208 406 : OMP_CLAUSE_CHAIN (l) = omp_clauses;
7209 406 : OMP_CLAUSE_LASTPRIVATE_STMT (l) = tmp;
7210 406 : omp_clauses = l;
7211 406 : OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_SHARED);
7212 406 : break;
7213 : }
7214 : }
7215 1550 : gcc_assert (local_dovar == dovar || c != NULL);
7216 : }
7217 11699 : if (local_dovar != dovar)
7218 : {
7219 629 : if (op != EXEC_OMP_SIMD || dovar_found == 1)
7220 550 : tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
7221 79 : else if (collapse == 1)
7222 : {
7223 60 : tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
7224 60 : OMP_CLAUSE_LINEAR_STEP (tmp) = build_int_cst (type, 1);
7225 60 : OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
7226 60 : OMP_CLAUSE_LINEAR_NO_COPYOUT (tmp) = 1;
7227 : }
7228 : else
7229 19 : tmp = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
7230 629 : OMP_CLAUSE_DECL (tmp) = local_dovar;
7231 629 : omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
7232 : }
7233 :
7234 11699 : if (i + 1 < collapse)
7235 2463 : code = code->block->next;
7236 : }
7237 :
7238 9528 : if (pblock != &block)
7239 : {
7240 3495 : pushlevel ();
7241 3495 : gfc_start_block (&block);
7242 : }
7243 :
7244 9528 : gfc_start_block (&body);
7245 :
7246 19685 : FOR_EACH_VEC_ELT (inits, ix, di)
7247 629 : gfc_add_modify (&body, di->var, di->init);
7248 9528 : inits.release ();
7249 :
7250 : /* Cycle statement is implemented with a goto. Exit statement must not be
7251 : present for this loop. */
7252 9528 : cycle_label = gfc_build_label_decl (NULL_TREE);
7253 :
7254 : /* Put these labels where they can be found later. */
7255 :
7256 9528 : code->cycle_label = cycle_label;
7257 9528 : code->exit_label = NULL_TREE;
7258 :
7259 : /* Main loop body. */
7260 9528 : if (clauses->lists[OMP_LIST_REDUCTION_INSCAN])
7261 : {
7262 16 : gfc_code *code1, *scan, *code2, *tmpcode;
7263 16 : code1 = tmpcode = code->block->next;
7264 16 : if (tmpcode && tmpcode->op != EXEC_OMP_SCAN)
7265 18 : while (tmpcode && tmpcode->next && tmpcode->next->op != EXEC_OMP_SCAN)
7266 : tmpcode = tmpcode->next;
7267 16 : scan = tmpcode->op == EXEC_OMP_SCAN ? tmpcode : tmpcode->next;
7268 16 : if (code1 != scan)
7269 16 : tmpcode->next = NULL;
7270 16 : code2 = scan->next;
7271 16 : gcc_assert (scan->op == EXEC_OMP_SCAN);
7272 16 : location_t loc = gfc_get_location (&scan->loc);
7273 :
7274 16 : tmp = code1 != scan ? gfc_trans_code (code1) : build_empty_stmt (loc);
7275 16 : tmp = build2 (OMP_SCAN, void_type_node, tmp, NULL_TREE);
7276 16 : SET_EXPR_LOCATION (tmp, loc);
7277 16 : gfc_add_expr_to_block (&body, tmp);
7278 16 : input_location = loc;
7279 16 : tree c = gfc_trans_omp_clauses (&body, scan->ext.omp_clauses, scan->loc);
7280 16 : tmp = code2 ? gfc_trans_code (code2) : build_empty_stmt (loc);
7281 16 : tmp = build2 (OMP_SCAN, void_type_node, tmp, c);
7282 16 : SET_EXPR_LOCATION (tmp, loc);
7283 16 : if (code1 != scan)
7284 16 : tmpcode->next = scan;
7285 : }
7286 9512 : else if (code->op == EXEC_OMP_TILE || code->op == EXEC_OMP_UNROLL)
7287 292 : tmp = gfc_trans_omp_code (code, true);
7288 : else
7289 9220 : tmp = gfc_trans_omp_code (code->block->next, true);
7290 9528 : gfc_add_expr_to_block (&body, tmp);
7291 :
7292 : /* Label for cycle statements (if needed). */
7293 9528 : if (TREE_USED (cycle_label))
7294 : {
7295 9528 : tmp = build1_v (LABEL_EXPR, cycle_label);
7296 9528 : gfc_add_expr_to_block (&body, tmp);
7297 : }
7298 :
7299 : /* End of loop body. */
7300 9528 : switch (op)
7301 : {
7302 1455 : case EXEC_OMP_SIMD: stmt = make_node (OMP_SIMD); break;
7303 2413 : case EXEC_OMP_DO: stmt = make_node (OMP_FOR); break;
7304 80 : case EXEC_OMP_DISTRIBUTE: stmt = make_node (OMP_DISTRIBUTE); break;
7305 113 : case EXEC_OMP_LOOP: stmt = make_node (OMP_LOOP); break;
7306 94 : case EXEC_OMP_TASKLOOP: stmt = make_node (OMP_TASKLOOP); break;
7307 4931 : case EXEC_OACC_LOOP: stmt = make_node (OACC_LOOP); break;
7308 120 : case EXEC_OMP_TILE: stmt = make_node (OMP_TILE); break;
7309 322 : case EXEC_OMP_UNROLL: stmt = make_node (OMP_UNROLL); break;
7310 0 : default: gcc_unreachable ();
7311 : }
7312 :
7313 9528 : SET_EXPR_LOCATION (stmt, gfc_get_location (&orig_code->loc));
7314 9528 : TREE_TYPE (stmt) = void_type_node;
7315 9528 : OMP_FOR_BODY (stmt) = gfc_finish_block (&body);
7316 9528 : OMP_FOR_CLAUSES (stmt) = omp_clauses;
7317 9528 : OMP_FOR_INIT (stmt) = init;
7318 9528 : OMP_FOR_COND (stmt) = cond;
7319 9528 : OMP_FOR_INCR (stmt) = incr;
7320 9528 : if (orig_decls)
7321 140 : OMP_FOR_ORIG_DECLS (stmt) = orig_decls;
7322 9528 : OMP_FOR_NON_RECTANGULAR (stmt) = clauses->non_rectangular;
7323 9528 : gfc_add_expr_to_block (&block, stmt);
7324 :
7325 9528 : vec_free (doacross_steps);
7326 9528 : doacross_steps = saved_doacross_steps;
7327 :
7328 9528 : return gfc_finish_block (&block);
7329 : }
7330 :
7331 : /* Translate combined OpenACC 'parallel loop', 'kernels loop', 'serial loop'
7332 : construct. */
7333 :
7334 : static tree
7335 1556 : gfc_trans_oacc_combined_directive (gfc_code *code)
7336 : {
7337 1556 : stmtblock_t block, *pblock = NULL;
7338 1556 : gfc_omp_clauses construct_clauses, loop_clauses;
7339 1556 : tree stmt, oacc_clauses = NULL_TREE;
7340 1556 : enum tree_code construct_code;
7341 1556 : location_t loc = input_location;
7342 :
7343 1556 : switch (code->op)
7344 : {
7345 : case EXEC_OACC_PARALLEL_LOOP:
7346 : construct_code = OACC_PARALLEL;
7347 : break;
7348 : case EXEC_OACC_KERNELS_LOOP:
7349 : construct_code = OACC_KERNELS;
7350 : break;
7351 : case EXEC_OACC_SERIAL_LOOP:
7352 : construct_code = OACC_SERIAL;
7353 : break;
7354 0 : default:
7355 0 : gcc_unreachable ();
7356 : }
7357 :
7358 1556 : gfc_start_block (&block);
7359 :
7360 1556 : memset (&loop_clauses, 0, sizeof (loop_clauses));
7361 1556 : if (code->ext.omp_clauses != NULL)
7362 : {
7363 1556 : memcpy (&construct_clauses, code->ext.omp_clauses,
7364 : sizeof (construct_clauses));
7365 1556 : loop_clauses.collapse = construct_clauses.collapse;
7366 1556 : loop_clauses.gang = construct_clauses.gang;
7367 1556 : loop_clauses.gang_static = construct_clauses.gang_static;
7368 1556 : loop_clauses.gang_num_expr = construct_clauses.gang_num_expr;
7369 1556 : loop_clauses.gang_static_expr = construct_clauses.gang_static_expr;
7370 1556 : loop_clauses.vector = construct_clauses.vector;
7371 1556 : loop_clauses.vector_expr = construct_clauses.vector_expr;
7372 1556 : loop_clauses.worker = construct_clauses.worker;
7373 1556 : loop_clauses.worker_expr = construct_clauses.worker_expr;
7374 1556 : loop_clauses.seq = construct_clauses.seq;
7375 1556 : loop_clauses.par_auto = construct_clauses.par_auto;
7376 1556 : loop_clauses.independent = construct_clauses.independent;
7377 1556 : loop_clauses.tile_list = construct_clauses.tile_list;
7378 1556 : loop_clauses.lists[OMP_LIST_PRIVATE]
7379 1556 : = construct_clauses.lists[OMP_LIST_PRIVATE];
7380 1556 : loop_clauses.lists[OMP_LIST_REDUCTION]
7381 1556 : = construct_clauses.lists[OMP_LIST_REDUCTION];
7382 1556 : construct_clauses.gang = false;
7383 1556 : construct_clauses.gang_static = false;
7384 1556 : construct_clauses.gang_num_expr = NULL;
7385 1556 : construct_clauses.gang_static_expr = NULL;
7386 1556 : construct_clauses.vector = false;
7387 1556 : construct_clauses.vector_expr = NULL;
7388 1556 : construct_clauses.worker = false;
7389 1556 : construct_clauses.worker_expr = NULL;
7390 1556 : construct_clauses.seq = false;
7391 1556 : construct_clauses.par_auto = false;
7392 1556 : construct_clauses.independent = false;
7393 1556 : construct_clauses.independent = false;
7394 1556 : construct_clauses.tile_list = NULL;
7395 1556 : construct_clauses.lists[OMP_LIST_PRIVATE] = NULL;
7396 1556 : if (construct_code == OACC_KERNELS)
7397 87 : construct_clauses.lists[OMP_LIST_REDUCTION] = NULL;
7398 1556 : oacc_clauses = gfc_trans_omp_clauses (&block, &construct_clauses,
7399 : code->loc, false, true);
7400 : }
7401 1556 : if (!loop_clauses.seq)
7402 : pblock = █
7403 : else
7404 54 : pushlevel ();
7405 1556 : stmt = gfc_trans_omp_do (code, EXEC_OACC_LOOP, pblock, &loop_clauses, NULL);
7406 1556 : protected_set_expr_location (stmt, loc);
7407 1556 : if (TREE_CODE (stmt) != BIND_EXPR)
7408 1556 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7409 : else
7410 0 : poplevel (0, 0);
7411 1556 : stmt = build2_loc (loc, construct_code, void_type_node, stmt, oacc_clauses);
7412 1556 : gfc_add_expr_to_block (&block, stmt);
7413 1556 : return gfc_finish_block (&block);
7414 : }
7415 :
7416 : static tree
7417 108 : gfc_trans_omp_depobj (gfc_code *code)
7418 : {
7419 108 : stmtblock_t block;
7420 108 : gfc_se se;
7421 108 : gfc_init_se (&se, NULL);
7422 108 : gfc_init_block (&block);
7423 108 : gfc_conv_expr (&se, code->ext.omp_clauses->depobj);
7424 108 : gcc_assert (se.pre.head == NULL && se.post.head == NULL);
7425 108 : tree depobj = se.expr;
7426 108 : location_t loc = EXPR_LOCATION (depobj);
7427 108 : if (!POINTER_TYPE_P (TREE_TYPE (depobj)))
7428 108 : depobj = gfc_build_addr_expr (NULL, depobj);
7429 108 : depobj = fold_convert (build_pointer_type_for_mode (ptr_type_node,
7430 : TYPE_MODE (ptr_type_node),
7431 : true), depobj);
7432 108 : gfc_omp_namelist *n = code->ext.omp_clauses->lists[OMP_LIST_DEPEND];
7433 108 : if (n)
7434 : {
7435 83 : tree var;
7436 83 : if (!n->sym) /* omp_all_memory. */
7437 3 : var = null_pointer_node;
7438 80 : else if (n->expr && n->expr->ref->u.ar.type != AR_FULL)
7439 : {
7440 18 : gfc_init_se (&se, NULL);
7441 18 : if (n->expr->ref->u.ar.type == AR_ELEMENT)
7442 : {
7443 18 : gfc_conv_expr_reference (&se, n->expr);
7444 18 : var = se.expr;
7445 : }
7446 : else
7447 : {
7448 0 : gfc_conv_expr_descriptor (&se, n->expr);
7449 0 : var = gfc_conv_array_data (se.expr);
7450 : }
7451 18 : gfc_add_block_to_block (&block, &se.pre);
7452 18 : gfc_add_block_to_block (&block, &se.post);
7453 18 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (var)));
7454 : }
7455 : else
7456 : {
7457 62 : var = gfc_get_symbol_decl (n->sym);
7458 99 : if (POINTER_TYPE_P (TREE_TYPE (var))
7459 72 : && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (var))))
7460 8 : var = build_fold_indirect_ref (var);
7461 62 : if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (var)))
7462 : {
7463 12 : var = gfc_conv_descriptor_data_get (var);
7464 12 : gcc_assert (POINTER_TYPE_P (TREE_TYPE (var)));
7465 : }
7466 50 : else if ((n->sym->attr.allocatable || n->sym->attr.pointer)
7467 13 : && n->sym->attr.dummy)
7468 8 : var = build_fold_indirect_ref (var);
7469 67 : else if (!POINTER_TYPE_P (TREE_TYPE (var))
7470 44 : || (n->sym->ts.f90_type == BT_VOID
7471 12 : && !POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (var)))
7472 8 : && !GFC_ARRAY_TYPE_P (TREE_TYPE (TREE_TYPE (var)))))
7473 : {
7474 29 : TREE_ADDRESSABLE (var) = 1;
7475 29 : var = gfc_build_addr_expr (NULL, var);
7476 : }
7477 : }
7478 83 : depobj = save_expr (depobj);
7479 83 : tree r = build_fold_indirect_ref_loc (loc, depobj);
7480 83 : gfc_add_expr_to_block (&block,
7481 : build2 (MODIFY_EXPR, void_type_node, r, var));
7482 : }
7483 :
7484 : /* Only one may be set. */
7485 108 : gcc_assert (((int)(n != NULL) + (int)(code->ext.omp_clauses->destroy)
7486 : + (int)(code->ext.omp_clauses->depobj_update != OMP_DEPEND_UNSET))
7487 : == 1);
7488 108 : int k = -1; /* omp_clauses->destroy */
7489 108 : if (!code->ext.omp_clauses->destroy)
7490 92 : switch (code->ext.omp_clauses->depobj_update != OMP_DEPEND_UNSET
7491 92 : ? code->ext.omp_clauses->depobj_update : n->u.depend_doacross_op)
7492 : {
7493 : case OMP_DEPEND_IN: k = GOMP_DEPEND_IN; break;
7494 : case OMP_DEPEND_OUT: k = GOMP_DEPEND_OUT; break;
7495 : case OMP_DEPEND_INOUT: k = GOMP_DEPEND_INOUT; break;
7496 : case OMP_DEPEND_INOUTSET: k = GOMP_DEPEND_INOUTSET; break;
7497 : case OMP_DEPEND_MUTEXINOUTSET: k = GOMP_DEPEND_MUTEXINOUTSET; break;
7498 0 : default: gcc_unreachable ();
7499 : }
7500 108 : tree t = build_int_cst (ptr_type_node, k);
7501 108 : depobj = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (depobj), depobj,
7502 108 : TYPE_SIZE_UNIT (ptr_type_node));
7503 108 : depobj = build_fold_indirect_ref_loc (loc, depobj);
7504 108 : gfc_add_expr_to_block (&block, build2 (MODIFY_EXPR, void_type_node, depobj, t));
7505 :
7506 108 : return gfc_finish_block (&block);
7507 : }
7508 :
7509 : /* Callback for walk_tree to find an OMP dispatch call and wrap it into an
7510 : * IFN_GOMP_DISPATCH. */
7511 :
7512 : static tree
7513 2066 : replace_omp_dispatch_call (tree *tp, int *, void *decls_p)
7514 : {
7515 2066 : tree t = *tp;
7516 2066 : tree decls = (tree) decls_p;
7517 2066 : tree orig_fn_decl = TREE_PURPOSE (decls);
7518 2066 : tree dup_fn_decl = TREE_VALUE (decls);
7519 2066 : if (TREE_CODE (t) == CALL_EXPR)
7520 : {
7521 141 : if (CALL_EXPR_FN (t) == dup_fn_decl)
7522 1 : CALL_EXPR_FN (t) = orig_fn_decl;
7523 140 : else if (TREE_CODE (CALL_EXPR_FN (t)) == ADDR_EXPR
7524 140 : && TREE_OPERAND (CALL_EXPR_FN (t), 0) == dup_fn_decl)
7525 127 : TREE_OPERAND (CALL_EXPR_FN (t), 0) = dup_fn_decl;
7526 : else
7527 : return NULL_TREE;
7528 128 : *tp = build_call_expr_internal_loc (input_location, IFN_GOMP_DISPATCH,
7529 128 : TREE_TYPE (t), 1, t);
7530 128 : return *tp;
7531 : }
7532 :
7533 : return NULL_TREE;
7534 : }
7535 :
7536 : static tree
7537 128 : gfc_trans_omp_dispatch (gfc_code *code)
7538 : {
7539 128 : stmtblock_t block;
7540 128 : gfc_code *next = code->block->next;
7541 : // assume ill-formed "function dispatch structured
7542 : // block" have already been rejected by resolve_omp_dispatch
7543 128 : gcc_assert (next->op == EXEC_CALL || next->op == EXEC_ASSIGN);
7544 :
7545 : // Make duplicate decl for dispatch function call to make it easy to spot
7546 : // after translation
7547 128 : gfc_symbol *orig_fn_sym;
7548 128 : gfc_expr *call_expr = next->op == EXEC_CALL ? next->expr1 : next->expr2;
7549 128 : if (call_expr != NULL) // function
7550 : {
7551 71 : if (call_expr->value.function.isym != NULL) // dig into convert intrinsics
7552 4 : call_expr = call_expr->value.function.actual->expr;
7553 71 : gcc_assert (call_expr->expr_type == EXPR_FUNCTION);
7554 71 : orig_fn_sym = call_expr->value.function.esym
7555 71 : ? call_expr->value.function.esym
7556 0 : : call_expr->symtree->n.sym;
7557 : }
7558 : else // subroutine
7559 : {
7560 57 : orig_fn_sym = next->resolved_sym;
7561 : }
7562 128 : if (!orig_fn_sym->backend_decl)
7563 25 : gfc_get_symbol_decl (orig_fn_sym);
7564 128 : gfc_symbol dup_fn_sym = *orig_fn_sym;
7565 128 : dup_fn_sym.backend_decl = copy_node (orig_fn_sym->backend_decl);
7566 128 : if (call_expr != NULL)
7567 71 : call_expr->value.function.esym = &dup_fn_sym;
7568 : else
7569 57 : next->resolved_sym = &dup_fn_sym;
7570 :
7571 128 : tree body = gfc_trans_code (next);
7572 :
7573 : // Walk the tree to find the duplicate decl, wrap IFN call and replace
7574 : // dup decl with original
7575 128 : tree fn_decls
7576 128 : = build_tree_list (orig_fn_sym->backend_decl, dup_fn_sym.backend_decl);
7577 128 : tree dispatch_call
7578 128 : = walk_tree (&body, replace_omp_dispatch_call, fn_decls, NULL);
7579 128 : gcc_assert (dispatch_call != NULL_TREE);
7580 :
7581 128 : gfc_start_block (&block);
7582 128 : tree omp_clauses
7583 128 : = gfc_trans_omp_clauses (&block, code->ext.omp_clauses, code->loc);
7584 :
7585 : // Extract depend clauses and create taskwait
7586 128 : tree depend_clauses = NULL_TREE;
7587 128 : tree *depend_clauses_ptr = &depend_clauses;
7588 333 : for (tree c = omp_clauses; c; c = OMP_CLAUSE_CHAIN (c))
7589 : {
7590 205 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
7591 : {
7592 8 : *depend_clauses_ptr = c;
7593 8 : depend_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
7594 : }
7595 : }
7596 128 : if (depend_clauses != NULL_TREE)
7597 : {
7598 4 : tree stmt = make_node (OMP_TASK);
7599 4 : TREE_TYPE (stmt) = void_node;
7600 4 : OMP_TASK_CLAUSES (stmt) = depend_clauses;
7601 4 : OMP_TASK_BODY (stmt) = NULL_TREE;
7602 4 : SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
7603 4 : gfc_add_expr_to_block (&block, stmt);
7604 : }
7605 :
7606 128 : tree stmt = make_node (OMP_DISPATCH);
7607 128 : SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
7608 128 : TREE_TYPE (stmt) = void_type_node;
7609 128 : OMP_DISPATCH_BODY (stmt) = body;
7610 128 : OMP_DISPATCH_CLAUSES (stmt) = omp_clauses;
7611 :
7612 128 : gfc_add_expr_to_block (&block, stmt);
7613 128 : return gfc_finish_block (&block);
7614 : }
7615 :
7616 : static tree
7617 29 : gfc_trans_omp_error (gfc_code *code)
7618 : {
7619 29 : stmtblock_t block;
7620 29 : gfc_se se;
7621 29 : tree len, message;
7622 29 : bool fatal = code->ext.omp_clauses->severity == OMP_SEVERITY_FATAL;
7623 42 : tree fndecl = builtin_decl_explicit (fatal ? BUILT_IN_GOMP_ERROR
7624 : : BUILT_IN_GOMP_WARNING);
7625 29 : gfc_start_block (&block);
7626 29 : gfc_init_se (&se, NULL );
7627 29 : if (!code->ext.omp_clauses->message)
7628 : {
7629 3 : message = null_pointer_node;
7630 3 : len = build_int_cst (size_type_node, 0);
7631 : }
7632 : else
7633 : {
7634 26 : gfc_conv_expr (&se, code->ext.omp_clauses->message);
7635 26 : message = se.expr;
7636 26 : if (!POINTER_TYPE_P (TREE_TYPE (message)))
7637 : /* To ensure an ARRAY_TYPE is not passed as such. */
7638 17 : message = gfc_build_addr_expr (NULL, message);
7639 26 : len = se.string_length;
7640 : }
7641 29 : gfc_add_block_to_block (&block, &se.pre);
7642 29 : gfc_add_expr_to_block (&block, build_call_expr_loc (input_location, fndecl,
7643 : 2, message, len));
7644 29 : gfc_add_block_to_block (&block, &se.post);
7645 29 : return gfc_finish_block (&block);
7646 : }
7647 :
7648 : static tree
7649 70 : gfc_trans_omp_flush (gfc_code *code)
7650 : {
7651 70 : tree call;
7652 70 : if (!code->ext.omp_clauses
7653 4 : || code->ext.omp_clauses->memorder == OMP_MEMORDER_UNSET
7654 4 : || code->ext.omp_clauses->memorder == OMP_MEMORDER_SEQ_CST)
7655 : {
7656 67 : call = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
7657 67 : call = build_call_expr_loc (input_location, call, 0);
7658 : }
7659 : else
7660 : {
7661 3 : enum memmodel mo = MEMMODEL_LAST;
7662 3 : switch (code->ext.omp_clauses->memorder)
7663 : {
7664 : case OMP_MEMORDER_ACQ_REL: mo = MEMMODEL_ACQ_REL; break;
7665 : case OMP_MEMORDER_RELEASE: mo = MEMMODEL_RELEASE; break;
7666 : case OMP_MEMORDER_ACQUIRE: mo = MEMMODEL_ACQUIRE; break;
7667 0 : default: gcc_unreachable (); break;
7668 : }
7669 3 : call = builtin_decl_explicit (BUILT_IN_ATOMIC_THREAD_FENCE);
7670 3 : call = build_call_expr_loc (input_location, call, 1,
7671 3 : build_int_cst (integer_type_node, mo));
7672 : }
7673 70 : return call;
7674 : }
7675 :
7676 : static tree
7677 116 : gfc_trans_omp_master (gfc_code *code)
7678 : {
7679 116 : tree stmt = gfc_trans_code (code->block->next);
7680 116 : if (IS_EMPTY_STMT (stmt))
7681 : return stmt;
7682 110 : return build1_v (OMP_MASTER, stmt);
7683 : }
7684 :
7685 : static tree
7686 49 : gfc_trans_omp_masked (gfc_code *code, gfc_omp_clauses *clauses)
7687 : {
7688 49 : stmtblock_t block;
7689 49 : tree body = gfc_trans_code (code->block->next);
7690 49 : if (IS_EMPTY_STMT (body))
7691 : return body;
7692 40 : if (!clauses)
7693 33 : clauses = code->ext.omp_clauses;
7694 40 : gfc_start_block (&block);
7695 40 : tree omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
7696 40 : tree stmt = make_node (OMP_MASKED);
7697 40 : SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
7698 40 : TREE_TYPE (stmt) = void_type_node;
7699 40 : OMP_MASKED_BODY (stmt) = body;
7700 40 : OMP_MASKED_CLAUSES (stmt) = omp_clauses;
7701 40 : gfc_add_expr_to_block (&block, stmt);
7702 40 : return gfc_finish_block (&block);
7703 : }
7704 :
7705 :
7706 : static tree
7707 521 : gfc_trans_omp_ordered (gfc_code *code)
7708 : {
7709 521 : if (!flag_openmp)
7710 : {
7711 5 : if (!code->ext.omp_clauses->simd)
7712 3 : return gfc_trans_code (code->block ? code->block->next : NULL);
7713 2 : code->ext.omp_clauses->threads = 0;
7714 : }
7715 518 : tree omp_clauses = gfc_trans_omp_clauses (NULL, code->ext.omp_clauses,
7716 : code->loc);
7717 518 : return build2_loc (input_location, OMP_ORDERED, void_type_node,
7718 518 : code->block ? gfc_trans_code (code->block->next)
7719 518 : : NULL_TREE, omp_clauses);
7720 : }
7721 :
7722 : static tree
7723 1869 : gfc_trans_omp_parallel (gfc_code *code)
7724 : {
7725 1869 : stmtblock_t block;
7726 1869 : tree stmt, omp_clauses;
7727 :
7728 1869 : gfc_start_block (&block);
7729 1869 : omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
7730 : code->loc);
7731 1869 : pushlevel ();
7732 1869 : stmt = gfc_trans_omp_code (code->block->next, true);
7733 1869 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7734 1869 : stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
7735 : omp_clauses);
7736 1869 : gfc_add_expr_to_block (&block, stmt);
7737 1869 : return gfc_finish_block (&block);
7738 : }
7739 :
7740 : enum
7741 : {
7742 : GFC_OMP_SPLIT_SIMD,
7743 : GFC_OMP_SPLIT_DO,
7744 : GFC_OMP_SPLIT_PARALLEL,
7745 : GFC_OMP_SPLIT_DISTRIBUTE,
7746 : GFC_OMP_SPLIT_TEAMS,
7747 : GFC_OMP_SPLIT_TARGET,
7748 : GFC_OMP_SPLIT_TASKLOOP,
7749 : GFC_OMP_SPLIT_MASKED,
7750 : GFC_OMP_SPLIT_NUM
7751 : };
7752 :
7753 : enum
7754 : {
7755 : GFC_OMP_MASK_SIMD = (1 << GFC_OMP_SPLIT_SIMD),
7756 : GFC_OMP_MASK_DO = (1 << GFC_OMP_SPLIT_DO),
7757 : GFC_OMP_MASK_PARALLEL = (1 << GFC_OMP_SPLIT_PARALLEL),
7758 : GFC_OMP_MASK_DISTRIBUTE = (1 << GFC_OMP_SPLIT_DISTRIBUTE),
7759 : GFC_OMP_MASK_TEAMS = (1 << GFC_OMP_SPLIT_TEAMS),
7760 : GFC_OMP_MASK_TARGET = (1 << GFC_OMP_SPLIT_TARGET),
7761 : GFC_OMP_MASK_TASKLOOP = (1 << GFC_OMP_SPLIT_TASKLOOP),
7762 : GFC_OMP_MASK_MASKED = (1 << GFC_OMP_SPLIT_MASKED)
7763 : };
7764 :
7765 : /* If a var is in lastprivate/firstprivate/reduction but not in a
7766 : data mapping/sharing clause, add it to 'map(tofrom:' if is_target
7767 : and to 'shared' otherwise. */
7768 : static void
7769 2528 : gfc_add_clause_implicitly (gfc_omp_clauses *clauses_out,
7770 : gfc_omp_clauses *clauses_in,
7771 : bool is_target, bool is_parallel_do)
7772 : {
7773 2528 : int clauselist_to_add = is_target ? OMP_LIST_MAP : OMP_LIST_SHARED;
7774 2528 : gfc_omp_namelist *tail = NULL;
7775 15168 : for (int i = 0; i < 5; ++i)
7776 : {
7777 12640 : gfc_omp_namelist *n;
7778 12640 : switch (i)
7779 : {
7780 2528 : case 0: n = clauses_in->lists[OMP_LIST_FIRSTPRIVATE]; break;
7781 2528 : case 1: n = clauses_in->lists[OMP_LIST_LASTPRIVATE]; break;
7782 2528 : case 2: n = clauses_in->lists[OMP_LIST_REDUCTION]; break;
7783 2528 : case 3: n = clauses_in->lists[OMP_LIST_REDUCTION_INSCAN]; break;
7784 2528 : case 4: n = clauses_in->lists[OMP_LIST_REDUCTION_TASK]; break;
7785 : default: gcc_unreachable ();
7786 : }
7787 15980 : for (; n != NULL; n = n->next)
7788 : {
7789 : gfc_omp_namelist *n2, **n_firstp = NULL, **n_lastp = NULL;
7790 20670 : for (int j = 0; j < 6; ++j)
7791 : {
7792 18201 : gfc_omp_namelist **n2ref = NULL, *prev2 = NULL;
7793 18201 : switch (j)
7794 : {
7795 3340 : case 0:
7796 3340 : n2ref = &clauses_out->lists[clauselist_to_add];
7797 3340 : break;
7798 3303 : case 1:
7799 3303 : n2ref = &clauses_out->lists[OMP_LIST_FIRSTPRIVATE];
7800 3303 : break;
7801 3303 : case 2:
7802 3303 : if (is_target)
7803 255 : n2ref = &clauses_in->lists[OMP_LIST_LASTPRIVATE];
7804 : else
7805 3048 : n2ref = &clauses_out->lists[OMP_LIST_LASTPRIVATE];
7806 : break;
7807 3303 : case 3: n2ref = &clauses_out->lists[OMP_LIST_REDUCTION]; break;
7808 2476 : case 4:
7809 2476 : n2ref = &clauses_out->lists[OMP_LIST_REDUCTION_INSCAN];
7810 2476 : break;
7811 2476 : case 5:
7812 2476 : n2ref = &clauses_out->lists[OMP_LIST_REDUCTION_TASK];
7813 2476 : break;
7814 : default: gcc_unreachable ();
7815 : }
7816 28475 : for (n2 = *n2ref; n2 != NULL; prev2 = n2, n2 = n2->next)
7817 13539 : if (n2->sym == n->sym)
7818 : break;
7819 18201 : if (n2)
7820 : {
7821 3265 : if (j == 0 /* clauselist_to_add */)
7822 : break; /* Already present. */
7823 3228 : if (j == 1 /* OMP_LIST_FIRSTPRIVATE */)
7824 : {
7825 1128 : n_firstp = prev2 ? &prev2->next : n2ref;
7826 1128 : continue;
7827 : }
7828 2100 : if (j == 2 /* OMP_LIST_LASTPRIVATE */)
7829 : {
7830 1266 : n_lastp = prev2 ? &prev2->next : n2ref;
7831 1266 : continue;
7832 : }
7833 : break;
7834 : }
7835 : }
7836 3340 : if (n_firstp && n_lastp)
7837 : {
7838 : /* For parallel do, GCC puts firstprivate/lastprivate
7839 : on the parallel. */
7840 283 : if (is_parallel_do)
7841 280 : continue;
7842 3 : *n_firstp = (*n_firstp)->next;
7843 3 : if (!is_target)
7844 0 : *n_lastp = (*n_lastp)->next;
7845 : }
7846 3057 : else if (is_target && n_lastp)
7847 : ;
7848 3002 : else if (n2 || n_firstp || n_lastp)
7849 2644 : continue;
7850 416 : if (clauses_out->lists[clauselist_to_add]
7851 305 : && (clauses_out->lists[clauselist_to_add]
7852 305 : == clauses_in->lists[clauselist_to_add]))
7853 : {
7854 : gfc_omp_namelist *p = NULL;
7855 421 : for (n2 = clauses_in->lists[clauselist_to_add]; n2; n2 = n2->next)
7856 : {
7857 273 : if (p)
7858 : {
7859 125 : p->next = gfc_get_omp_namelist ();
7860 125 : p = p->next;
7861 : }
7862 : else
7863 : {
7864 148 : p = gfc_get_omp_namelist ();
7865 148 : clauses_out->lists[clauselist_to_add] = p;
7866 : }
7867 273 : *p = *n2;
7868 : }
7869 : }
7870 416 : if (!tail)
7871 : {
7872 287 : tail = clauses_out->lists[clauselist_to_add];
7873 412 : for (; tail && tail->next; tail = tail->next)
7874 : ;
7875 : }
7876 416 : n2 = gfc_get_omp_namelist ();
7877 416 : n2->where = n->where;
7878 416 : n2->sym = n->sym;
7879 416 : if (is_target)
7880 119 : n2->u.map.op = OMP_MAP_TOFROM;
7881 416 : if (tail)
7882 : {
7883 305 : tail->next = n2;
7884 305 : tail = n2;
7885 : }
7886 : else
7887 111 : clauses_out->lists[clauselist_to_add] = n2;
7888 : }
7889 : }
7890 2528 : }
7891 :
7892 : /* Kind of opposite to above, add firstprivate to CLAUSES_OUT if it is mapped
7893 : in CLAUSES_IN's FIRSTPRIVATE list but not its MAP list. */
7894 :
7895 : static void
7896 340 : gfc_add_firstprivate_if_unmapped (gfc_omp_clauses *clauses_out,
7897 : gfc_omp_clauses *clauses_in)
7898 : {
7899 340 : gfc_omp_namelist *n = clauses_in->lists[OMP_LIST_FIRSTPRIVATE];
7900 340 : gfc_omp_namelist **tail = NULL;
7901 :
7902 490 : for (; n != NULL; n = n->next)
7903 : {
7904 150 : gfc_omp_namelist *n2 = clauses_out->lists[OMP_LIST_MAP];
7905 192 : for (; n2 != NULL; n2 = n2->next)
7906 53 : if (n->sym == n2->sym)
7907 : break;
7908 150 : if (n2 == NULL)
7909 : {
7910 139 : gfc_omp_namelist *dup = gfc_get_omp_namelist ();
7911 139 : *dup = *n;
7912 139 : dup->next = NULL;
7913 139 : if (!tail)
7914 : {
7915 76 : tail = &clauses_out->lists[OMP_LIST_FIRSTPRIVATE];
7916 76 : while (*tail && (*tail)->next)
7917 0 : tail = &(*tail)->next;
7918 : }
7919 139 : *tail = dup;
7920 139 : tail = &(*tail)->next;
7921 : }
7922 : }
7923 340 : }
7924 :
7925 : static void
7926 4172 : gfc_free_split_omp_clauses (gfc_code *code, gfc_omp_clauses *clausesa)
7927 : {
7928 37548 : for (int i = 0; i < GFC_OMP_SPLIT_NUM; ++i)
7929 1335040 : for (int j = 0; j < OMP_LIST_NUM; ++j)
7930 1301664 : if (clausesa[i].lists[j] && clausesa[i].lists[j] != code->ext.omp_clauses->lists[j])
7931 1397 : for (gfc_omp_namelist *n = clausesa[i].lists[j]; n;)
7932 : {
7933 956 : gfc_omp_namelist *p = n;
7934 956 : n = n->next;
7935 956 : free (p);
7936 : }
7937 4172 : }
7938 :
7939 : static void
7940 4172 : gfc_split_omp_clauses (gfc_code *code,
7941 : gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM])
7942 : {
7943 4172 : int mask = 0, innermost = 0;
7944 4172 : bool is_loop = false;
7945 4172 : memset (clausesa, 0, GFC_OMP_SPLIT_NUM * sizeof (gfc_omp_clauses));
7946 4172 : switch (code->op)
7947 : {
7948 : case EXEC_OMP_DISTRIBUTE:
7949 : innermost = GFC_OMP_SPLIT_DISTRIBUTE;
7950 : break;
7951 38 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
7952 38 : mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
7953 38 : innermost = GFC_OMP_SPLIT_DO;
7954 38 : break;
7955 28 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
7956 28 : mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL
7957 : | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
7958 28 : innermost = GFC_OMP_SPLIT_SIMD;
7959 28 : break;
7960 47 : case EXEC_OMP_DISTRIBUTE_SIMD:
7961 47 : mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
7962 47 : innermost = GFC_OMP_SPLIT_SIMD;
7963 47 : break;
7964 0 : case EXEC_OMP_DO:
7965 0 : case EXEC_OMP_LOOP:
7966 0 : innermost = GFC_OMP_SPLIT_DO;
7967 0 : break;
7968 126 : case EXEC_OMP_DO_SIMD:
7969 126 : mask = GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
7970 126 : innermost = GFC_OMP_SPLIT_SIMD;
7971 126 : break;
7972 0 : case EXEC_OMP_PARALLEL:
7973 0 : innermost = GFC_OMP_SPLIT_PARALLEL;
7974 0 : break;
7975 1106 : case EXEC_OMP_PARALLEL_DO:
7976 1106 : case EXEC_OMP_PARALLEL_LOOP:
7977 1106 : mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
7978 1106 : innermost = GFC_OMP_SPLIT_DO;
7979 1106 : break;
7980 285 : case EXEC_OMP_PARALLEL_DO_SIMD:
7981 285 : mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
7982 285 : innermost = GFC_OMP_SPLIT_SIMD;
7983 285 : break;
7984 11 : case EXEC_OMP_PARALLEL_MASKED:
7985 11 : mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_MASKED;
7986 11 : innermost = GFC_OMP_SPLIT_MASKED;
7987 11 : break;
7988 14 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
7989 14 : mask = (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_MASKED
7990 : | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD);
7991 14 : innermost = GFC_OMP_SPLIT_TASKLOOP;
7992 14 : break;
7993 20 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
7994 20 : mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
7995 20 : innermost = GFC_OMP_SPLIT_TASKLOOP;
7996 20 : break;
7997 24 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
7998 24 : mask = (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_MASKED
7999 : | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD);
8000 24 : innermost = GFC_OMP_SPLIT_SIMD;
8001 24 : break;
8002 28 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
8003 28 : mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
8004 28 : innermost = GFC_OMP_SPLIT_SIMD;
8005 28 : break;
8006 0 : case EXEC_OMP_SIMD:
8007 0 : innermost = GFC_OMP_SPLIT_SIMD;
8008 0 : break;
8009 1759 : case EXEC_OMP_TARGET:
8010 1759 : innermost = GFC_OMP_SPLIT_TARGET;
8011 1759 : break;
8012 20 : case EXEC_OMP_TARGET_PARALLEL:
8013 20 : mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL;
8014 20 : innermost = GFC_OMP_SPLIT_PARALLEL;
8015 20 : break;
8016 80 : case EXEC_OMP_TARGET_PARALLEL_DO:
8017 80 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
8018 80 : mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
8019 80 : innermost = GFC_OMP_SPLIT_DO;
8020 80 : break;
8021 15 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
8022 15 : mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO
8023 : | GFC_OMP_MASK_SIMD;
8024 15 : innermost = GFC_OMP_SPLIT_SIMD;
8025 15 : break;
8026 26 : case EXEC_OMP_TARGET_SIMD:
8027 26 : mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_SIMD;
8028 26 : innermost = GFC_OMP_SPLIT_SIMD;
8029 26 : break;
8030 69 : case EXEC_OMP_TARGET_TEAMS:
8031 69 : mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS;
8032 69 : innermost = GFC_OMP_SPLIT_TEAMS;
8033 69 : break;
8034 14 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
8035 14 : mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS
8036 : | GFC_OMP_MASK_DISTRIBUTE;
8037 14 : innermost = GFC_OMP_SPLIT_DISTRIBUTE;
8038 14 : break;
8039 58 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
8040 58 : mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
8041 : | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
8042 58 : innermost = GFC_OMP_SPLIT_DO;
8043 58 : break;
8044 29 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
8045 29 : mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
8046 : | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
8047 29 : innermost = GFC_OMP_SPLIT_SIMD;
8048 29 : break;
8049 16 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
8050 16 : mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS
8051 : | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
8052 16 : innermost = GFC_OMP_SPLIT_SIMD;
8053 16 : break;
8054 13 : case EXEC_OMP_TARGET_TEAMS_LOOP:
8055 13 : mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DO;
8056 13 : innermost = GFC_OMP_SPLIT_DO;
8057 13 : break;
8058 8 : case EXEC_OMP_MASKED_TASKLOOP:
8059 8 : mask = GFC_OMP_MASK_MASKED | GFC_OMP_MASK_TASKLOOP;
8060 8 : innermost = GFC_OMP_SPLIT_TASKLOOP;
8061 8 : break;
8062 0 : case EXEC_OMP_MASTER_TASKLOOP:
8063 0 : case EXEC_OMP_TASKLOOP:
8064 0 : innermost = GFC_OMP_SPLIT_TASKLOOP;
8065 0 : break;
8066 24 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
8067 24 : mask = GFC_OMP_MASK_MASKED | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
8068 24 : innermost = GFC_OMP_SPLIT_SIMD;
8069 24 : break;
8070 45 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
8071 45 : case EXEC_OMP_TASKLOOP_SIMD:
8072 45 : mask = GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
8073 45 : innermost = GFC_OMP_SPLIT_SIMD;
8074 45 : break;
8075 124 : case EXEC_OMP_TEAMS:
8076 124 : innermost = GFC_OMP_SPLIT_TEAMS;
8077 124 : break;
8078 14 : case EXEC_OMP_TEAMS_DISTRIBUTE:
8079 14 : mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE;
8080 14 : innermost = GFC_OMP_SPLIT_DISTRIBUTE;
8081 14 : break;
8082 32 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
8083 32 : mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
8084 : | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
8085 32 : innermost = GFC_OMP_SPLIT_DO;
8086 32 : break;
8087 56 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
8088 56 : mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
8089 : | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
8090 56 : innermost = GFC_OMP_SPLIT_SIMD;
8091 56 : break;
8092 37 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
8093 37 : mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
8094 37 : innermost = GFC_OMP_SPLIT_SIMD;
8095 37 : break;
8096 : case EXEC_OMP_TEAMS_LOOP:
8097 : mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DO;
8098 : innermost = GFC_OMP_SPLIT_DO;
8099 : break;
8100 0 : default:
8101 0 : gcc_unreachable ();
8102 : }
8103 4166 : if (mask == 0)
8104 : {
8105 1883 : clausesa[innermost] = *code->ext.omp_clauses;
8106 1883 : return;
8107 : }
8108 : /* Loops are similar to DO but still a bit different. */
8109 2289 : switch (code->op)
8110 : {
8111 54 : case EXEC_OMP_LOOP:
8112 54 : case EXEC_OMP_PARALLEL_LOOP:
8113 54 : case EXEC_OMP_TEAMS_LOOP:
8114 54 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
8115 54 : case EXEC_OMP_TARGET_TEAMS_LOOP:
8116 54 : is_loop = true;
8117 2289 : default:
8118 2289 : break;
8119 : }
8120 2289 : if (code->ext.omp_clauses != NULL)
8121 : {
8122 2289 : if (mask & GFC_OMP_MASK_TARGET)
8123 : {
8124 : /* First the clauses that are unique to some constructs. */
8125 340 : clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_MAP]
8126 340 : = code->ext.omp_clauses->lists[OMP_LIST_MAP];
8127 340 : clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_IS_DEVICE_PTR]
8128 340 : = code->ext.omp_clauses->lists[OMP_LIST_IS_DEVICE_PTR];
8129 340 : clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_HAS_DEVICE_ADDR]
8130 340 : = code->ext.omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR];
8131 340 : clausesa[GFC_OMP_SPLIT_TARGET].device
8132 340 : = code->ext.omp_clauses->device;
8133 340 : clausesa[GFC_OMP_SPLIT_TARGET].thread_limit
8134 340 : = code->ext.omp_clauses->thread_limit;
8135 340 : clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_USES_ALLOCATORS]
8136 340 : = code->ext.omp_clauses->lists[OMP_LIST_USES_ALLOCATORS];
8137 2380 : for (int i = 0; i < OMP_DEFAULTMAP_CAT_NUM; i++)
8138 2040 : clausesa[GFC_OMP_SPLIT_TARGET].defaultmap[i]
8139 2040 : = code->ext.omp_clauses->defaultmap[i];
8140 340 : clausesa[GFC_OMP_SPLIT_TARGET].if_exprs[OMP_IF_TARGET]
8141 340 : = code->ext.omp_clauses->if_exprs[OMP_IF_TARGET];
8142 : /* And this is copied to all. */
8143 340 : clausesa[GFC_OMP_SPLIT_TARGET].if_expr
8144 340 : = code->ext.omp_clauses->if_expr;
8145 340 : clausesa[GFC_OMP_SPLIT_TARGET].nowait
8146 340 : = code->ext.omp_clauses->nowait;
8147 340 : clausesa[GFC_OMP_SPLIT_TARGET].device_type
8148 340 : = code->ext.omp_clauses->device_type;
8149 : }
8150 2289 : if (mask & GFC_OMP_MASK_TEAMS)
8151 : {
8152 : /* First the clauses that are unique to some constructs. */
8153 344 : clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_lower
8154 344 : = code->ext.omp_clauses->num_teams_lower;
8155 344 : clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper
8156 344 : = code->ext.omp_clauses->num_teams_upper;
8157 344 : clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit
8158 344 : = code->ext.omp_clauses->thread_limit;
8159 : /* Shared and default clauses are allowed on parallel, teams
8160 : and taskloop. */
8161 344 : clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_SHARED]
8162 344 : = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
8163 344 : clausesa[GFC_OMP_SPLIT_TEAMS].default_sharing
8164 344 : = code->ext.omp_clauses->default_sharing;
8165 : }
8166 2289 : if (mask & GFC_OMP_MASK_DISTRIBUTE)
8167 : {
8168 : /* First the clauses that are unique to some constructs. */
8169 369 : clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_sched_kind
8170 369 : = code->ext.omp_clauses->dist_sched_kind;
8171 369 : clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_chunk_size
8172 369 : = code->ext.omp_clauses->dist_chunk_size;
8173 : /* Duplicate collapse. */
8174 369 : clausesa[GFC_OMP_SPLIT_DISTRIBUTE].collapse
8175 369 : = code->ext.omp_clauses->collapse;
8176 369 : clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_concurrent
8177 369 : = code->ext.omp_clauses->order_concurrent;
8178 369 : clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_unconstrained
8179 369 : = code->ext.omp_clauses->order_unconstrained;
8180 369 : clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_reproducible
8181 369 : = code->ext.omp_clauses->order_reproducible;
8182 : }
8183 2289 : if (mask & GFC_OMP_MASK_PARALLEL)
8184 : {
8185 : /* First the clauses that are unique to some constructs. */
8186 1844 : clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_COPYIN]
8187 1844 : = code->ext.omp_clauses->lists[OMP_LIST_COPYIN];
8188 1844 : clausesa[GFC_OMP_SPLIT_PARALLEL].num_threads
8189 1844 : = code->ext.omp_clauses->num_threads;
8190 1844 : clausesa[GFC_OMP_SPLIT_PARALLEL].proc_bind
8191 1844 : = code->ext.omp_clauses->proc_bind;
8192 : /* Shared and default clauses are allowed on parallel, teams
8193 : and taskloop. */
8194 1844 : clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_SHARED]
8195 1844 : = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
8196 1844 : clausesa[GFC_OMP_SPLIT_PARALLEL].default_sharing
8197 1844 : = code->ext.omp_clauses->default_sharing;
8198 1844 : clausesa[GFC_OMP_SPLIT_PARALLEL].if_exprs[OMP_IF_PARALLEL]
8199 1844 : = code->ext.omp_clauses->if_exprs[OMP_IF_PARALLEL];
8200 : /* And this is copied to all. */
8201 1844 : clausesa[GFC_OMP_SPLIT_PARALLEL].if_expr
8202 1844 : = code->ext.omp_clauses->if_expr;
8203 : }
8204 2289 : if (mask & GFC_OMP_MASK_MASKED)
8205 81 : clausesa[GFC_OMP_SPLIT_MASKED].filter = code->ext.omp_clauses->filter;
8206 2289 : if ((mask & GFC_OMP_MASK_DO) && !is_loop)
8207 : {
8208 : /* First the clauses that are unique to some constructs. */
8209 1818 : clausesa[GFC_OMP_SPLIT_DO].ordered
8210 1818 : = code->ext.omp_clauses->ordered;
8211 1818 : clausesa[GFC_OMP_SPLIT_DO].orderedc
8212 1818 : = code->ext.omp_clauses->orderedc;
8213 1818 : clausesa[GFC_OMP_SPLIT_DO].sched_kind
8214 1818 : = code->ext.omp_clauses->sched_kind;
8215 1818 : if (innermost == GFC_OMP_SPLIT_SIMD)
8216 539 : clausesa[GFC_OMP_SPLIT_DO].sched_simd
8217 539 : = code->ext.omp_clauses->sched_simd;
8218 1818 : clausesa[GFC_OMP_SPLIT_DO].sched_monotonic
8219 1818 : = code->ext.omp_clauses->sched_monotonic;
8220 1818 : clausesa[GFC_OMP_SPLIT_DO].sched_nonmonotonic
8221 1818 : = code->ext.omp_clauses->sched_nonmonotonic;
8222 1818 : clausesa[GFC_OMP_SPLIT_DO].chunk_size
8223 1818 : = code->ext.omp_clauses->chunk_size;
8224 1818 : clausesa[GFC_OMP_SPLIT_DO].nowait
8225 1818 : = code->ext.omp_clauses->nowait;
8226 : }
8227 1872 : if (mask & GFC_OMP_MASK_DO)
8228 : {
8229 1872 : clausesa[GFC_OMP_SPLIT_DO].bind
8230 1872 : = code->ext.omp_clauses->bind;
8231 : /* Duplicate collapse. */
8232 1872 : clausesa[GFC_OMP_SPLIT_DO].collapse
8233 1872 : = code->ext.omp_clauses->collapse;
8234 1872 : clausesa[GFC_OMP_SPLIT_DO].order_concurrent
8235 1872 : = code->ext.omp_clauses->order_concurrent;
8236 1872 : clausesa[GFC_OMP_SPLIT_DO].order_unconstrained
8237 1872 : = code->ext.omp_clauses->order_unconstrained;
8238 1872 : clausesa[GFC_OMP_SPLIT_DO].order_reproducible
8239 1872 : = code->ext.omp_clauses->order_reproducible;
8240 : }
8241 2289 : if (mask & GFC_OMP_MASK_SIMD)
8242 : {
8243 820 : clausesa[GFC_OMP_SPLIT_SIMD].safelen_expr
8244 820 : = code->ext.omp_clauses->safelen_expr;
8245 820 : clausesa[GFC_OMP_SPLIT_SIMD].simdlen_expr
8246 820 : = code->ext.omp_clauses->simdlen_expr;
8247 820 : clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_ALIGNED]
8248 820 : = code->ext.omp_clauses->lists[OMP_LIST_ALIGNED];
8249 : /* Duplicate collapse. */
8250 820 : clausesa[GFC_OMP_SPLIT_SIMD].collapse
8251 820 : = code->ext.omp_clauses->collapse;
8252 820 : clausesa[GFC_OMP_SPLIT_SIMD].if_exprs[OMP_IF_SIMD]
8253 820 : = code->ext.omp_clauses->if_exprs[OMP_IF_SIMD];
8254 820 : clausesa[GFC_OMP_SPLIT_SIMD].order_concurrent
8255 820 : = code->ext.omp_clauses->order_concurrent;
8256 820 : clausesa[GFC_OMP_SPLIT_SIMD].order_unconstrained
8257 820 : = code->ext.omp_clauses->order_unconstrained;
8258 820 : clausesa[GFC_OMP_SPLIT_SIMD].order_reproducible
8259 820 : = code->ext.omp_clauses->order_reproducible;
8260 : /* And this is copied to all. */
8261 820 : clausesa[GFC_OMP_SPLIT_SIMD].if_expr
8262 820 : = code->ext.omp_clauses->if_expr;
8263 : }
8264 2289 : if (mask & GFC_OMP_MASK_TASKLOOP)
8265 : {
8266 : /* First the clauses that are unique to some constructs. */
8267 163 : clausesa[GFC_OMP_SPLIT_TASKLOOP].nogroup
8268 163 : = code->ext.omp_clauses->nogroup;
8269 163 : clausesa[GFC_OMP_SPLIT_TASKLOOP].grainsize
8270 163 : = code->ext.omp_clauses->grainsize;
8271 163 : clausesa[GFC_OMP_SPLIT_TASKLOOP].grainsize_strict
8272 163 : = code->ext.omp_clauses->grainsize_strict;
8273 163 : clausesa[GFC_OMP_SPLIT_TASKLOOP].num_tasks
8274 163 : = code->ext.omp_clauses->num_tasks;
8275 163 : clausesa[GFC_OMP_SPLIT_TASKLOOP].num_tasks_strict
8276 163 : = code->ext.omp_clauses->num_tasks_strict;
8277 163 : clausesa[GFC_OMP_SPLIT_TASKLOOP].priority
8278 163 : = code->ext.omp_clauses->priority;
8279 163 : clausesa[GFC_OMP_SPLIT_TASKLOOP].final_expr
8280 163 : = code->ext.omp_clauses->final_expr;
8281 163 : clausesa[GFC_OMP_SPLIT_TASKLOOP].untied
8282 163 : = code->ext.omp_clauses->untied;
8283 163 : clausesa[GFC_OMP_SPLIT_TASKLOOP].mergeable
8284 163 : = code->ext.omp_clauses->mergeable;
8285 163 : clausesa[GFC_OMP_SPLIT_TASKLOOP].if_exprs[OMP_IF_TASKLOOP]
8286 163 : = code->ext.omp_clauses->if_exprs[OMP_IF_TASKLOOP];
8287 : /* And this is copied to all. */
8288 163 : clausesa[GFC_OMP_SPLIT_TASKLOOP].if_expr
8289 163 : = code->ext.omp_clauses->if_expr;
8290 : /* Shared and default clauses are allowed on parallel, teams
8291 : and taskloop. */
8292 163 : clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_SHARED]
8293 163 : = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
8294 163 : clausesa[GFC_OMP_SPLIT_TASKLOOP].default_sharing
8295 163 : = code->ext.omp_clauses->default_sharing;
8296 : /* Duplicate collapse. */
8297 163 : clausesa[GFC_OMP_SPLIT_TASKLOOP].collapse
8298 163 : = code->ext.omp_clauses->collapse;
8299 : }
8300 : /* Private clause is supported on all constructs but master/masked,
8301 : it is enough to put it on the innermost one except for master/masked. For
8302 : !$ omp parallel do put it on parallel though,
8303 : as that's what we did for OpenMP 3.1. */
8304 2289 : clausesa[((innermost == GFC_OMP_SPLIT_DO && !is_loop)
8305 : || code->op == EXEC_OMP_PARALLEL_MASTER
8306 1010 : || code->op == EXEC_OMP_PARALLEL_MASKED)
8307 999 : ? (int) GFC_OMP_SPLIT_PARALLEL
8308 3288 : : innermost].lists[OMP_LIST_PRIVATE]
8309 2289 : = code->ext.omp_clauses->lists[OMP_LIST_PRIVATE];
8310 : /* Firstprivate clause is supported on all constructs but
8311 : simd and masked/master. Put it on the outermost of those and duplicate
8312 : on parallel and teams. */
8313 2289 : if (mask & GFC_OMP_MASK_TARGET)
8314 340 : gfc_add_firstprivate_if_unmapped (&clausesa[GFC_OMP_SPLIT_TARGET],
8315 : code->ext.omp_clauses);
8316 2289 : if (mask & GFC_OMP_MASK_TEAMS)
8317 344 : clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_FIRSTPRIVATE]
8318 344 : = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
8319 1945 : else if (mask & GFC_OMP_MASK_DISTRIBUTE)
8320 113 : clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_FIRSTPRIVATE]
8321 113 : = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
8322 2289 : if (mask & GFC_OMP_MASK_TASKLOOP)
8323 163 : clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_FIRSTPRIVATE]
8324 163 : = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
8325 2289 : if ((mask & GFC_OMP_MASK_PARALLEL)
8326 1844 : && !(mask & GFC_OMP_MASK_TASKLOOP))
8327 1758 : clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_FIRSTPRIVATE]
8328 1758 : = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
8329 531 : else if ((mask & GFC_OMP_MASK_DO) && !is_loop)
8330 126 : clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_FIRSTPRIVATE]
8331 126 : = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
8332 : /* Lastprivate is allowed on distribute, do, simd, taskloop and loop.
8333 : In parallel do{, simd} we actually want to put it on
8334 : parallel rather than do. */
8335 2289 : if (mask & GFC_OMP_MASK_DISTRIBUTE)
8336 369 : clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_LASTPRIVATE]
8337 369 : = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
8338 2289 : if (mask & GFC_OMP_MASK_TASKLOOP)
8339 163 : clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_LASTPRIVATE]
8340 163 : = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
8341 2289 : if ((mask & GFC_OMP_MASK_PARALLEL) && !is_loop
8342 1809 : && !(mask & GFC_OMP_MASK_TASKLOOP))
8343 1723 : clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_LASTPRIVATE]
8344 1723 : = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
8345 566 : else if (mask & GFC_OMP_MASK_DO)
8346 180 : clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_LASTPRIVATE]
8347 180 : = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
8348 2289 : if (mask & GFC_OMP_MASK_SIMD)
8349 820 : clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_LASTPRIVATE]
8350 820 : = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
8351 : /* Reduction is allowed on simd, do, parallel, teams, taskloop, and loop.
8352 : Duplicate it on all of them, but
8353 : - omit on do if parallel is present;
8354 : - omit on task and parallel if loop is present;
8355 : additionally, inscan applies to do/simd only. */
8356 9156 : for (int i = OMP_LIST_REDUCTION; i <= OMP_LIST_REDUCTION_TASK; i++)
8357 : {
8358 6867 : if (mask & GFC_OMP_MASK_TASKLOOP
8359 489 : && i != OMP_LIST_REDUCTION_INSCAN)
8360 326 : clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[i]
8361 326 : = code->ext.omp_clauses->lists[i];
8362 6867 : if (mask & GFC_OMP_MASK_TEAMS
8363 1032 : && i != OMP_LIST_REDUCTION_INSCAN
8364 1032 : && !is_loop)
8365 650 : clausesa[GFC_OMP_SPLIT_TEAMS].lists[i]
8366 650 : = code->ext.omp_clauses->lists[i];
8367 6867 : if (mask & GFC_OMP_MASK_PARALLEL
8368 5532 : && i != OMP_LIST_REDUCTION_INSCAN
8369 3688 : && !(mask & GFC_OMP_MASK_TASKLOOP)
8370 3516 : && !is_loop)
8371 3446 : clausesa[GFC_OMP_SPLIT_PARALLEL].lists[i]
8372 3446 : = code->ext.omp_clauses->lists[i];
8373 3421 : else if (mask & GFC_OMP_MASK_DO)
8374 2232 : clausesa[GFC_OMP_SPLIT_DO].lists[i]
8375 2232 : = code->ext.omp_clauses->lists[i];
8376 6867 : if (mask & GFC_OMP_MASK_SIMD)
8377 2460 : clausesa[GFC_OMP_SPLIT_SIMD].lists[i]
8378 2460 : = code->ext.omp_clauses->lists[i];
8379 : }
8380 2289 : if (mask & GFC_OMP_MASK_TARGET)
8381 340 : clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_IN_REDUCTION]
8382 340 : = code->ext.omp_clauses->lists[OMP_LIST_IN_REDUCTION];
8383 2289 : if (mask & GFC_OMP_MASK_TASKLOOP)
8384 163 : clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_IN_REDUCTION]
8385 163 : = code->ext.omp_clauses->lists[OMP_LIST_IN_REDUCTION];
8386 : /* Linear clause is supported on do and simd,
8387 : put it on the innermost one. */
8388 2289 : clausesa[innermost].lists[OMP_LIST_LINEAR]
8389 2289 : = code->ext.omp_clauses->lists[OMP_LIST_LINEAR];
8390 : }
8391 : /* Propagate firstprivate/lastprivate/reduction vars to
8392 : shared (parallel, teams) and map-tofrom (target). */
8393 2289 : if (mask & GFC_OMP_MASK_TARGET)
8394 340 : gfc_add_clause_implicitly (&clausesa[GFC_OMP_SPLIT_TARGET],
8395 : code->ext.omp_clauses, true, false);
8396 2289 : if ((mask & GFC_OMP_MASK_PARALLEL) && innermost != GFC_OMP_MASK_PARALLEL)
8397 1844 : gfc_add_clause_implicitly (&clausesa[GFC_OMP_SPLIT_PARALLEL],
8398 : code->ext.omp_clauses, false,
8399 1844 : mask & GFC_OMP_MASK_DO);
8400 2289 : if (mask & GFC_OMP_MASK_TEAMS && innermost != GFC_OMP_MASK_TEAMS)
8401 344 : gfc_add_clause_implicitly (&clausesa[GFC_OMP_SPLIT_TEAMS],
8402 : code->ext.omp_clauses, false, false);
8403 2289 : if (((mask & (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
8404 : == (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
8405 1727 : && !is_loop)
8406 1692 : clausesa[GFC_OMP_SPLIT_DO].nowait = true;
8407 :
8408 : /* Distribute allocate clause to do, parallel, distribute, teams, target
8409 : and taskloop. The code below iterates over variables in the
8410 : allocate list and checks if that available is also in any
8411 : privatization clause on those construct. If yes, then we add it
8412 : to the list of 'allocate'ed variables for that construct. If a
8413 : variable is found in none of them then we issue an error. */
8414 :
8415 2289 : if (code->ext.omp_clauses->lists[OMP_LIST_ALLOCATE])
8416 : {
8417 : gfc_omp_namelist *alloc_nl, *priv_nl;
8418 : gfc_omp_namelist *tails[GFC_OMP_SPLIT_NUM];
8419 104 : for (alloc_nl = code->ext.omp_clauses->lists[OMP_LIST_ALLOCATE];
8420 181 : alloc_nl; alloc_nl = alloc_nl->next)
8421 : {
8422 : bool found = false;
8423 728 : for (int i = GFC_OMP_SPLIT_DO; i <= GFC_OMP_SPLIT_TASKLOOP; i++)
8424 : {
8425 : gfc_omp_namelist *p;
8426 : int list;
8427 24960 : for (list = 0; list < OMP_LIST_NUM; list++)
8428 : {
8429 24336 : switch (list)
8430 : {
8431 5616 : case OMP_LIST_PRIVATE:
8432 5616 : case OMP_LIST_FIRSTPRIVATE:
8433 5616 : case OMP_LIST_LASTPRIVATE:
8434 5616 : case OMP_LIST_REDUCTION:
8435 5616 : case OMP_LIST_REDUCTION_INSCAN:
8436 5616 : case OMP_LIST_REDUCTION_TASK:
8437 5616 : case OMP_LIST_IN_REDUCTION:
8438 5616 : case OMP_LIST_TASK_REDUCTION:
8439 5616 : case OMP_LIST_LINEAR:
8440 6092 : for (priv_nl = clausesa[i].lists[list]; priv_nl;
8441 476 : priv_nl = priv_nl->next)
8442 476 : if (alloc_nl->sym == priv_nl->sym)
8443 : {
8444 131 : found = true;
8445 131 : p = gfc_get_omp_namelist ();
8446 131 : p->sym = alloc_nl->sym;
8447 131 : p->expr = alloc_nl->expr;
8448 131 : p->u.align = alloc_nl->u.align;
8449 131 : p->u2.allocator = alloc_nl->u2.allocator;
8450 131 : p->where = alloc_nl->where;
8451 131 : if (clausesa[i].lists[OMP_LIST_ALLOCATE] == NULL)
8452 : {
8453 109 : clausesa[i].lists[OMP_LIST_ALLOCATE] = p;
8454 109 : tails[i] = p;
8455 : }
8456 : else
8457 : {
8458 22 : tails[i]->next = p;
8459 22 : tails[i] = tails[i]->next;
8460 : }
8461 : }
8462 : break;
8463 : default:
8464 : break;
8465 : }
8466 : }
8467 : }
8468 104 : if (!found)
8469 1 : gfc_error ("%qs specified in %<allocate%> clause at %L but not "
8470 : "in an explicit privatization clause",
8471 1 : alloc_nl->sym->name, &alloc_nl->where);
8472 : }
8473 : }
8474 : }
8475 :
8476 : static tree
8477 539 : gfc_trans_omp_do_simd (gfc_code *code, stmtblock_t *pblock,
8478 : gfc_omp_clauses *clausesa, tree omp_clauses)
8479 : {
8480 539 : stmtblock_t block;
8481 539 : gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
8482 539 : tree stmt, body, omp_do_clauses = NULL_TREE;
8483 539 : bool free_clausesa = false;
8484 :
8485 539 : if (pblock == NULL)
8486 411 : gfc_start_block (&block);
8487 : else
8488 128 : gfc_init_block (&block);
8489 :
8490 539 : if (clausesa == NULL)
8491 : {
8492 126 : clausesa = clausesa_buf;
8493 126 : gfc_split_omp_clauses (code, clausesa);
8494 126 : free_clausesa = true;
8495 : }
8496 539 : if (flag_openmp)
8497 534 : omp_do_clauses
8498 534 : = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DO], code->loc);
8499 667 : body = gfc_trans_omp_do (code, EXEC_OMP_SIMD, pblock ? pblock : &block,
8500 : &clausesa[GFC_OMP_SPLIT_SIMD], omp_clauses);
8501 539 : if (pblock == NULL)
8502 : {
8503 411 : if (TREE_CODE (body) != BIND_EXPR)
8504 411 : body = build3_v (BIND_EXPR, NULL, body, poplevel (1, 0));
8505 : else
8506 0 : poplevel (0, 0);
8507 : }
8508 128 : else if (TREE_CODE (body) != BIND_EXPR)
8509 128 : body = build3_v (BIND_EXPR, NULL, body, NULL_TREE);
8510 539 : if (flag_openmp)
8511 : {
8512 534 : stmt = make_node (OMP_FOR);
8513 534 : SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
8514 534 : TREE_TYPE (stmt) = void_type_node;
8515 534 : OMP_FOR_BODY (stmt) = body;
8516 534 : OMP_FOR_CLAUSES (stmt) = omp_do_clauses;
8517 : }
8518 : else
8519 : stmt = body;
8520 539 : gfc_add_expr_to_block (&block, stmt);
8521 539 : if (free_clausesa)
8522 126 : gfc_free_split_omp_clauses (code, clausesa);
8523 539 : return gfc_finish_block (&block);
8524 : }
8525 :
8526 : static tree
8527 1314 : gfc_trans_omp_parallel_do (gfc_code *code, bool is_loop, stmtblock_t *pblock,
8528 : gfc_omp_clauses *clausesa)
8529 : {
8530 1314 : stmtblock_t block, *new_pblock = pblock;
8531 1314 : gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
8532 1314 : tree stmt, omp_clauses = NULL_TREE;
8533 1314 : bool free_clausesa = false;
8534 :
8535 1314 : if (pblock == NULL)
8536 1106 : gfc_start_block (&block);
8537 : else
8538 208 : gfc_init_block (&block);
8539 :
8540 1314 : if (clausesa == NULL)
8541 : {
8542 1106 : clausesa = clausesa_buf;
8543 1106 : gfc_split_omp_clauses (code, clausesa);
8544 1106 : free_clausesa = true;
8545 : }
8546 1314 : omp_clauses
8547 1314 : = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
8548 : code->loc);
8549 1314 : if (pblock == NULL)
8550 : {
8551 1106 : if (!clausesa[GFC_OMP_SPLIT_DO].ordered
8552 1097 : && clausesa[GFC_OMP_SPLIT_DO].sched_kind != OMP_SCHED_STATIC)
8553 : new_pblock = █
8554 : else
8555 65 : pushlevel ();
8556 : }
8557 2593 : stmt = gfc_trans_omp_do (code, is_loop ? EXEC_OMP_LOOP : EXEC_OMP_DO,
8558 : new_pblock, &clausesa[GFC_OMP_SPLIT_DO],
8559 : omp_clauses);
8560 1314 : if (pblock == NULL)
8561 : {
8562 1106 : if (TREE_CODE (stmt) != BIND_EXPR)
8563 1090 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
8564 : else
8565 16 : poplevel (0, 0);
8566 : }
8567 208 : else if (TREE_CODE (stmt) != BIND_EXPR)
8568 208 : stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
8569 1314 : stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
8570 : void_type_node, stmt, omp_clauses);
8571 1314 : OMP_PARALLEL_COMBINED (stmt) = 1;
8572 1314 : gfc_add_expr_to_block (&block, stmt);
8573 1314 : if (free_clausesa)
8574 1106 : gfc_free_split_omp_clauses (code, clausesa);
8575 1314 : return gfc_finish_block (&block);
8576 : }
8577 :
8578 : static tree
8579 413 : gfc_trans_omp_parallel_do_simd (gfc_code *code, stmtblock_t *pblock,
8580 : gfc_omp_clauses *clausesa)
8581 : {
8582 413 : stmtblock_t block;
8583 413 : gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
8584 413 : tree stmt, omp_clauses = NULL_TREE;
8585 413 : bool free_clausesa = false;
8586 :
8587 413 : if (pblock == NULL)
8588 285 : gfc_start_block (&block);
8589 : else
8590 128 : gfc_init_block (&block);
8591 :
8592 413 : if (clausesa == NULL)
8593 : {
8594 285 : clausesa = clausesa_buf;
8595 285 : gfc_split_omp_clauses (code, clausesa);
8596 285 : free_clausesa = true;
8597 : }
8598 413 : if (flag_openmp)
8599 410 : omp_clauses
8600 410 : = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
8601 : code->loc);
8602 413 : if (pblock == NULL)
8603 285 : pushlevel ();
8604 413 : stmt = gfc_trans_omp_do_simd (code, pblock, clausesa, omp_clauses);
8605 413 : if (pblock == NULL)
8606 : {
8607 285 : if (TREE_CODE (stmt) != BIND_EXPR)
8608 214 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
8609 : else
8610 71 : poplevel (0, 0);
8611 : }
8612 128 : else if (TREE_CODE (stmt) != BIND_EXPR)
8613 128 : stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
8614 413 : if (flag_openmp)
8615 : {
8616 410 : stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
8617 : void_type_node, stmt, omp_clauses);
8618 410 : OMP_PARALLEL_COMBINED (stmt) = 1;
8619 : }
8620 413 : gfc_add_expr_to_block (&block, stmt);
8621 413 : if (free_clausesa)
8622 285 : gfc_free_split_omp_clauses (code, clausesa);
8623 413 : return gfc_finish_block (&block);
8624 : }
8625 :
8626 : static tree
8627 54 : gfc_trans_omp_parallel_sections (gfc_code *code)
8628 : {
8629 54 : stmtblock_t block;
8630 54 : gfc_omp_clauses section_clauses;
8631 54 : tree stmt, omp_clauses;
8632 :
8633 54 : memset (§ion_clauses, 0, sizeof (section_clauses));
8634 54 : section_clauses.nowait = true;
8635 :
8636 54 : gfc_start_block (&block);
8637 54 : omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
8638 : code->loc);
8639 54 : pushlevel ();
8640 54 : stmt = gfc_trans_omp_sections (code, §ion_clauses);
8641 54 : if (TREE_CODE (stmt) != BIND_EXPR)
8642 54 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
8643 : else
8644 0 : poplevel (0, 0);
8645 54 : stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
8646 : void_type_node, stmt, omp_clauses);
8647 54 : OMP_PARALLEL_COMBINED (stmt) = 1;
8648 54 : gfc_add_expr_to_block (&block, stmt);
8649 54 : return gfc_finish_block (&block);
8650 : }
8651 :
8652 : static tree
8653 50 : gfc_trans_omp_parallel_workshare (gfc_code *code)
8654 : {
8655 50 : stmtblock_t block;
8656 50 : gfc_omp_clauses workshare_clauses;
8657 50 : tree stmt, omp_clauses;
8658 :
8659 50 : memset (&workshare_clauses, 0, sizeof (workshare_clauses));
8660 50 : workshare_clauses.nowait = true;
8661 :
8662 50 : gfc_start_block (&block);
8663 50 : omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
8664 : code->loc);
8665 50 : pushlevel ();
8666 50 : stmt = gfc_trans_omp_workshare (code, &workshare_clauses);
8667 50 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
8668 50 : stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
8669 : void_type_node, stmt, omp_clauses);
8670 50 : OMP_PARALLEL_COMBINED (stmt) = 1;
8671 50 : gfc_add_expr_to_block (&block, stmt);
8672 50 : return gfc_finish_block (&block);
8673 : }
8674 :
8675 : static tree
8676 53 : gfc_trans_omp_scope (gfc_code *code)
8677 : {
8678 53 : stmtblock_t block;
8679 53 : tree body = gfc_trans_code (code->block->next);
8680 53 : if (IS_EMPTY_STMT (body))
8681 : return body;
8682 51 : gfc_start_block (&block);
8683 51 : tree omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
8684 : code->loc);
8685 51 : tree stmt = make_node (OMP_SCOPE);
8686 51 : SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
8687 51 : TREE_TYPE (stmt) = void_type_node;
8688 51 : OMP_SCOPE_BODY (stmt) = body;
8689 51 : OMP_SCOPE_CLAUSES (stmt) = omp_clauses;
8690 51 : gfc_add_expr_to_block (&block, stmt);
8691 51 : return gfc_finish_block (&block);
8692 : }
8693 :
8694 : static tree
8695 129 : gfc_trans_omp_sections (gfc_code *code, gfc_omp_clauses *clauses)
8696 : {
8697 129 : stmtblock_t block, body;
8698 129 : tree omp_clauses, stmt;
8699 129 : bool has_lastprivate = clauses->lists[OMP_LIST_LASTPRIVATE] != NULL;
8700 129 : location_t loc = gfc_get_location (&code->loc);
8701 :
8702 129 : gfc_start_block (&block);
8703 :
8704 129 : omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
8705 :
8706 129 : gfc_init_block (&body);
8707 499 : for (code = code->block; code; code = code->block)
8708 : {
8709 : /* Last section is special because of lastprivate, so even if it
8710 : is empty, chain it in. */
8711 370 : stmt = gfc_trans_omp_code (code->next,
8712 370 : has_lastprivate && code->block == NULL);
8713 370 : if (! IS_EMPTY_STMT (stmt))
8714 : {
8715 280 : stmt = build1_v (OMP_SECTION, stmt);
8716 280 : gfc_add_expr_to_block (&body, stmt);
8717 : }
8718 : }
8719 129 : stmt = gfc_finish_block (&body);
8720 :
8721 129 : stmt = build2_loc (loc, OMP_SECTIONS, void_type_node, stmt, omp_clauses);
8722 129 : gfc_add_expr_to_block (&block, stmt);
8723 :
8724 129 : return gfc_finish_block (&block);
8725 : }
8726 :
8727 : static tree
8728 556 : gfc_trans_omp_single (gfc_code *code, gfc_omp_clauses *clauses)
8729 : {
8730 556 : stmtblock_t block;
8731 556 : gfc_start_block (&block);
8732 556 : tree omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
8733 556 : tree stmt = gfc_trans_omp_code (code->block->next, true);
8734 556 : stmt = build2_loc (gfc_get_location (&code->loc), OMP_SINGLE, void_type_node,
8735 : stmt, omp_clauses);
8736 556 : gfc_add_expr_to_block (&block, stmt);
8737 556 : return gfc_finish_block (&block);
8738 : }
8739 :
8740 : static tree
8741 1121 : gfc_trans_omp_task (gfc_code *code)
8742 : {
8743 1121 : stmtblock_t block;
8744 1121 : tree stmt, omp_clauses;
8745 :
8746 1121 : gfc_start_block (&block);
8747 1121 : omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
8748 : code->loc);
8749 1121 : pushlevel ();
8750 1121 : stmt = gfc_trans_omp_code (code->block->next, true);
8751 1121 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
8752 1121 : stmt = build2_loc (gfc_get_location (&code->loc), OMP_TASK, void_type_node,
8753 : stmt, omp_clauses);
8754 1121 : gfc_add_expr_to_block (&block, stmt);
8755 1121 : return gfc_finish_block (&block);
8756 : }
8757 :
8758 : static tree
8759 181 : gfc_trans_omp_taskgroup (gfc_code *code)
8760 : {
8761 181 : stmtblock_t block;
8762 181 : gfc_start_block (&block);
8763 181 : tree body = gfc_trans_code (code->block->next);
8764 181 : tree stmt = make_node (OMP_TASKGROUP);
8765 181 : SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
8766 181 : TREE_TYPE (stmt) = void_type_node;
8767 181 : OMP_TASKGROUP_BODY (stmt) = body;
8768 181 : OMP_TASKGROUP_CLAUSES (stmt) = gfc_trans_omp_clauses (&block,
8769 : code->ext.omp_clauses,
8770 : code->loc);
8771 181 : gfc_add_expr_to_block (&block, stmt);
8772 181 : return gfc_finish_block (&block);
8773 : }
8774 :
8775 : static tree
8776 145 : gfc_trans_omp_taskwait (gfc_code *code)
8777 : {
8778 145 : if (!code->ext.omp_clauses)
8779 : {
8780 132 : tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
8781 132 : return build_call_expr_loc (input_location, decl, 0);
8782 : }
8783 13 : stmtblock_t block;
8784 13 : gfc_start_block (&block);
8785 13 : tree stmt = make_node (OMP_TASK);
8786 13 : SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc));
8787 13 : TREE_TYPE (stmt) = void_type_node;
8788 13 : OMP_TASK_BODY (stmt) = NULL_TREE;
8789 13 : OMP_TASK_CLAUSES (stmt) = gfc_trans_omp_clauses (&block,
8790 : code->ext.omp_clauses,
8791 : code->loc);
8792 13 : gfc_add_expr_to_block (&block, stmt);
8793 13 : return gfc_finish_block (&block);
8794 : }
8795 :
8796 : static tree
8797 8 : gfc_trans_omp_taskyield (void)
8798 : {
8799 8 : tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
8800 8 : return build_call_expr_loc (input_location, decl, 0);
8801 : }
8802 :
8803 : static tree
8804 341 : gfc_trans_omp_distribute (gfc_code *code, gfc_omp_clauses *clausesa)
8805 : {
8806 341 : stmtblock_t block;
8807 341 : gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
8808 341 : tree stmt, omp_clauses = NULL_TREE;
8809 341 : bool free_clausesa = false;
8810 :
8811 341 : gfc_start_block (&block);
8812 341 : if (clausesa == NULL)
8813 : {
8814 113 : clausesa = clausesa_buf;
8815 113 : gfc_split_omp_clauses (code, clausesa);
8816 113 : free_clausesa = true;
8817 : }
8818 341 : if (flag_openmp)
8819 341 : omp_clauses
8820 341 : = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
8821 : code->loc);
8822 341 : switch (code->op)
8823 : {
8824 0 : case EXEC_OMP_DISTRIBUTE:
8825 0 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
8826 0 : case EXEC_OMP_TEAMS_DISTRIBUTE:
8827 : /* This is handled in gfc_trans_omp_do. */
8828 0 : gcc_unreachable ();
8829 128 : break;
8830 128 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
8831 128 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
8832 128 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
8833 128 : stmt = gfc_trans_omp_parallel_do (code, false, &block, clausesa);
8834 128 : if (TREE_CODE (stmt) != BIND_EXPR)
8835 128 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
8836 : else
8837 0 : poplevel (0, 0);
8838 : break;
8839 113 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
8840 113 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
8841 113 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
8842 113 : stmt = gfc_trans_omp_parallel_do_simd (code, &block, clausesa);
8843 113 : if (TREE_CODE (stmt) != BIND_EXPR)
8844 113 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
8845 : else
8846 0 : poplevel (0, 0);
8847 : break;
8848 100 : case EXEC_OMP_DISTRIBUTE_SIMD:
8849 100 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
8850 100 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
8851 100 : stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
8852 : &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
8853 100 : if (TREE_CODE (stmt) != BIND_EXPR)
8854 100 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
8855 : else
8856 0 : poplevel (0, 0);
8857 : break;
8858 0 : default:
8859 0 : gcc_unreachable ();
8860 : }
8861 341 : if (flag_openmp)
8862 : {
8863 341 : tree distribute = make_node (OMP_DISTRIBUTE);
8864 341 : SET_EXPR_LOCATION (distribute, gfc_get_location (&code->loc));
8865 341 : TREE_TYPE (distribute) = void_type_node;
8866 341 : OMP_FOR_BODY (distribute) = stmt;
8867 341 : OMP_FOR_CLAUSES (distribute) = omp_clauses;
8868 341 : stmt = distribute;
8869 : }
8870 341 : gfc_add_expr_to_block (&block, stmt);
8871 341 : if (free_clausesa)
8872 113 : gfc_free_split_omp_clauses (code, clausesa);
8873 341 : return gfc_finish_block (&block);
8874 : }
8875 :
8876 : static tree
8877 468 : gfc_trans_omp_teams (gfc_code *code, gfc_omp_clauses *clausesa,
8878 : tree omp_clauses)
8879 : {
8880 468 : stmtblock_t block;
8881 468 : gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
8882 468 : tree stmt;
8883 468 : bool combined = true, free_clausesa = false;
8884 :
8885 468 : gfc_start_block (&block);
8886 468 : if (clausesa == NULL)
8887 : {
8888 269 : clausesa = clausesa_buf;
8889 269 : gfc_split_omp_clauses (code, clausesa);
8890 269 : free_clausesa = true;
8891 : }
8892 468 : if (flag_openmp)
8893 : {
8894 468 : omp_clauses
8895 468 : = chainon (omp_clauses,
8896 : gfc_trans_omp_clauses (&block,
8897 : &clausesa[GFC_OMP_SPLIT_TEAMS],
8898 : code->loc));
8899 468 : pushlevel ();
8900 : }
8901 468 : switch (code->op)
8902 : {
8903 193 : case EXEC_OMP_TARGET_TEAMS:
8904 193 : case EXEC_OMP_TEAMS:
8905 193 : stmt = gfc_trans_omp_code (code->block->next, true);
8906 193 : combined = false;
8907 193 : break;
8908 28 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
8909 28 : case EXEC_OMP_TEAMS_DISTRIBUTE:
8910 28 : stmt = gfc_trans_omp_do (code, EXEC_OMP_DISTRIBUTE, NULL,
8911 : &clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
8912 : NULL);
8913 28 : break;
8914 19 : case EXEC_OMP_TARGET_TEAMS_LOOP:
8915 19 : case EXEC_OMP_TEAMS_LOOP:
8916 19 : stmt = gfc_trans_omp_do (code, EXEC_OMP_LOOP, NULL,
8917 : &clausesa[GFC_OMP_SPLIT_DO],
8918 : NULL);
8919 19 : break;
8920 228 : default:
8921 228 : stmt = gfc_trans_omp_distribute (code, clausesa);
8922 228 : break;
8923 : }
8924 468 : if (flag_openmp)
8925 : {
8926 468 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
8927 468 : stmt = build2_loc (gfc_get_location (&code->loc), OMP_TEAMS,
8928 : void_type_node, stmt, omp_clauses);
8929 468 : if (combined)
8930 275 : OMP_TEAMS_COMBINED (stmt) = 1;
8931 : }
8932 468 : gfc_add_expr_to_block (&block, stmt);
8933 468 : if (free_clausesa)
8934 269 : gfc_free_split_omp_clauses (code, clausesa);
8935 468 : return gfc_finish_block (&block);
8936 : }
8937 :
8938 : static tree
8939 2099 : gfc_trans_omp_target (gfc_code *code)
8940 : {
8941 2099 : stmtblock_t block;
8942 2099 : gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
8943 2099 : tree stmt, omp_clauses = NULL_TREE;
8944 :
8945 2099 : gfc_start_block (&block);
8946 2099 : gfc_split_omp_clauses (code, clausesa);
8947 2099 : if (flag_openmp)
8948 2099 : omp_clauses
8949 2099 : = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TARGET],
8950 : code->loc);
8951 2099 : switch (code->op)
8952 : {
8953 1759 : case EXEC_OMP_TARGET:
8954 1759 : pushlevel ();
8955 1759 : stmt = gfc_trans_omp_code (code->block->next, true);
8956 1759 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
8957 1759 : break;
8958 20 : case EXEC_OMP_TARGET_PARALLEL:
8959 20 : {
8960 20 : stmtblock_t iblock;
8961 :
8962 20 : pushlevel ();
8963 20 : gfc_start_block (&iblock);
8964 20 : tree inner_clauses
8965 20 : = gfc_trans_omp_clauses (&iblock, &clausesa[GFC_OMP_SPLIT_PARALLEL],
8966 : code->loc);
8967 20 : stmt = gfc_trans_omp_code (code->block->next, true);
8968 20 : stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
8969 : inner_clauses);
8970 20 : gfc_add_expr_to_block (&iblock, stmt);
8971 20 : stmt = gfc_finish_block (&iblock);
8972 20 : if (TREE_CODE (stmt) != BIND_EXPR)
8973 17 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
8974 : else
8975 3 : poplevel (0, 0);
8976 : }
8977 20 : break;
8978 80 : case EXEC_OMP_TARGET_PARALLEL_DO:
8979 80 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
8980 80 : stmt = gfc_trans_omp_parallel_do (code,
8981 : (code->op
8982 : == EXEC_OMP_TARGET_PARALLEL_LOOP),
8983 : &block, clausesa);
8984 80 : if (TREE_CODE (stmt) != BIND_EXPR)
8985 80 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
8986 : else
8987 0 : poplevel (0, 0);
8988 : break;
8989 15 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
8990 15 : stmt = gfc_trans_omp_parallel_do_simd (code, &block, clausesa);
8991 15 : if (TREE_CODE (stmt) != BIND_EXPR)
8992 15 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
8993 : else
8994 0 : poplevel (0, 0);
8995 : break;
8996 26 : case EXEC_OMP_TARGET_SIMD:
8997 26 : stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
8998 : &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
8999 26 : if (TREE_CODE (stmt) != BIND_EXPR)
9000 26 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
9001 : else
9002 0 : poplevel (0, 0);
9003 : break;
9004 199 : default:
9005 199 : if (flag_openmp
9006 199 : && (clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper
9007 149 : || clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit))
9008 : {
9009 51 : gfc_omp_clauses clausesb;
9010 51 : tree teams_clauses;
9011 : /* For combined !$omp target teams, the num_teams and
9012 : thread_limit clauses are evaluated before entering the
9013 : target construct. */
9014 51 : memset (&clausesb, '\0', sizeof (clausesb));
9015 51 : clausesb.num_teams_lower
9016 51 : = clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_lower;
9017 51 : clausesb.num_teams_upper
9018 51 : = clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper;
9019 51 : clausesb.thread_limit = clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit;
9020 51 : clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_lower = NULL;
9021 51 : clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper = NULL;
9022 51 : clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit = NULL;
9023 51 : teams_clauses
9024 51 : = gfc_trans_omp_clauses (&block, &clausesb, code->loc);
9025 51 : pushlevel ();
9026 51 : stmt = gfc_trans_omp_teams (code, clausesa, teams_clauses);
9027 51 : }
9028 : else
9029 : {
9030 148 : pushlevel ();
9031 148 : stmt = gfc_trans_omp_teams (code, clausesa, NULL_TREE);
9032 : }
9033 199 : if (TREE_CODE (stmt) != BIND_EXPR)
9034 198 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
9035 : else
9036 1 : poplevel (0, 0);
9037 : break;
9038 : }
9039 2099 : if (flag_openmp)
9040 : {
9041 2099 : stmt = build2_loc (gfc_get_location (&code->loc), OMP_TARGET,
9042 : void_type_node, stmt, omp_clauses);
9043 2099 : if (code->op != EXEC_OMP_TARGET)
9044 340 : OMP_TARGET_COMBINED (stmt) = 1;
9045 2099 : cfun->has_omp_target = true;
9046 : }
9047 2099 : gfc_add_expr_to_block (&block, stmt);
9048 2099 : gfc_free_split_omp_clauses (code, clausesa);
9049 2099 : return gfc_finish_block (&block);
9050 : }
9051 :
9052 : static tree
9053 79 : gfc_trans_omp_taskloop (gfc_code *code, gfc_exec_op op)
9054 : {
9055 79 : stmtblock_t block;
9056 79 : gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
9057 79 : tree stmt, omp_clauses = NULL_TREE;
9058 :
9059 79 : gfc_start_block (&block);
9060 79 : gfc_split_omp_clauses (code, clausesa);
9061 79 : if (flag_openmp)
9062 79 : omp_clauses
9063 79 : = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TASKLOOP],
9064 : code->loc);
9065 79 : switch (op)
9066 : {
9067 0 : case EXEC_OMP_TASKLOOP:
9068 : /* This is handled in gfc_trans_omp_do. */
9069 0 : gcc_unreachable ();
9070 79 : break;
9071 79 : case EXEC_OMP_TASKLOOP_SIMD:
9072 79 : stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
9073 : &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
9074 79 : if (TREE_CODE (stmt) != BIND_EXPR)
9075 79 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
9076 : else
9077 0 : poplevel (0, 0);
9078 79 : break;
9079 0 : default:
9080 0 : gcc_unreachable ();
9081 : }
9082 79 : if (flag_openmp)
9083 : {
9084 79 : tree taskloop = make_node (OMP_TASKLOOP);
9085 79 : SET_EXPR_LOCATION (taskloop, gfc_get_location (&code->loc));
9086 79 : TREE_TYPE (taskloop) = void_type_node;
9087 79 : OMP_FOR_BODY (taskloop) = stmt;
9088 79 : OMP_FOR_CLAUSES (taskloop) = omp_clauses;
9089 79 : stmt = taskloop;
9090 : }
9091 79 : gfc_add_expr_to_block (&block, stmt);
9092 79 : gfc_free_split_omp_clauses (code, clausesa);
9093 79 : return gfc_finish_block (&block);
9094 : }
9095 :
9096 : static tree
9097 84 : gfc_trans_omp_master_masked_taskloop (gfc_code *code, gfc_exec_op op)
9098 : {
9099 84 : gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
9100 84 : stmtblock_t block;
9101 84 : tree stmt;
9102 :
9103 84 : if (op != EXEC_OMP_MASTER_TASKLOOP_SIMD
9104 56 : && code->op != EXEC_OMP_MASTER_TASKLOOP)
9105 45 : gfc_split_omp_clauses (code, clausesa);
9106 :
9107 84 : pushlevel ();
9108 84 : if (op == EXEC_OMP_MASKED_TASKLOOP_SIMD
9109 84 : || op == EXEC_OMP_MASTER_TASKLOOP_SIMD)
9110 48 : stmt = gfc_trans_omp_taskloop (code, EXEC_OMP_TASKLOOP_SIMD);
9111 : else
9112 : {
9113 36 : gcc_assert (op == EXEC_OMP_MASKED_TASKLOOP
9114 : || op == EXEC_OMP_MASTER_TASKLOOP);
9115 36 : stmt = gfc_trans_omp_do (code, EXEC_OMP_TASKLOOP, NULL,
9116 36 : code->op != EXEC_OMP_MASTER_TASKLOOP
9117 : ? &clausesa[GFC_OMP_SPLIT_TASKLOOP]
9118 : : code->ext.omp_clauses, NULL);
9119 : }
9120 84 : if (TREE_CODE (stmt) != BIND_EXPR)
9121 55 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
9122 : else
9123 29 : poplevel (0, 0);
9124 84 : gfc_start_block (&block);
9125 84 : if (op == EXEC_OMP_MASKED_TASKLOOP || op == EXEC_OMP_MASKED_TASKLOOP_SIMD)
9126 : {
9127 35 : tree clauses = gfc_trans_omp_clauses (&block,
9128 : &clausesa[GFC_OMP_SPLIT_MASKED],
9129 : code->loc);
9130 35 : tree msk = make_node (OMP_MASKED);
9131 35 : SET_EXPR_LOCATION (msk, gfc_get_location (&code->loc));
9132 35 : TREE_TYPE (msk) = void_type_node;
9133 35 : OMP_MASKED_BODY (msk) = stmt;
9134 35 : OMP_MASKED_CLAUSES (msk) = clauses;
9135 35 : OMP_MASKED_COMBINED (msk) = 1;
9136 35 : gfc_add_expr_to_block (&block, msk);
9137 : }
9138 : else
9139 : {
9140 49 : gcc_assert (op == EXEC_OMP_MASTER_TASKLOOP
9141 : || op == EXEC_OMP_MASTER_TASKLOOP_SIMD);
9142 49 : stmt = build1_v (OMP_MASTER, stmt);
9143 49 : gfc_add_expr_to_block (&block, stmt);
9144 : }
9145 84 : if (op != EXEC_OMP_MASTER_TASKLOOP_SIMD
9146 56 : && code->op != EXEC_OMP_MASTER_TASKLOOP)
9147 45 : gfc_free_split_omp_clauses (code, clausesa);
9148 84 : return gfc_finish_block (&block);
9149 : }
9150 :
9151 : static tree
9152 61 : gfc_trans_omp_parallel_master_masked (gfc_code *code)
9153 : {
9154 61 : stmtblock_t block;
9155 61 : tree stmt, omp_clauses;
9156 61 : gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
9157 61 : bool parallel_combined = false;
9158 :
9159 61 : if (code->op != EXEC_OMP_PARALLEL_MASTER)
9160 50 : gfc_split_omp_clauses (code, clausesa);
9161 :
9162 61 : gfc_start_block (&block);
9163 61 : omp_clauses = gfc_trans_omp_clauses (&block,
9164 61 : code->op == EXEC_OMP_PARALLEL_MASTER
9165 : ? code->ext.omp_clauses
9166 : : &clausesa[GFC_OMP_SPLIT_PARALLEL],
9167 : code->loc);
9168 61 : pushlevel ();
9169 61 : if (code->op == EXEC_OMP_PARALLEL_MASTER)
9170 11 : stmt = gfc_trans_omp_master (code);
9171 50 : else if (code->op == EXEC_OMP_PARALLEL_MASKED)
9172 11 : stmt = gfc_trans_omp_masked (code, &clausesa[GFC_OMP_SPLIT_MASKED]);
9173 : else
9174 : {
9175 39 : gfc_exec_op op;
9176 39 : switch (code->op)
9177 : {
9178 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
9179 : op = EXEC_OMP_MASKED_TASKLOOP;
9180 : break;
9181 8 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
9182 8 : op = EXEC_OMP_MASKED_TASKLOOP_SIMD;
9183 8 : break;
9184 10 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
9185 10 : op = EXEC_OMP_MASTER_TASKLOOP;
9186 10 : break;
9187 14 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
9188 14 : op = EXEC_OMP_MASTER_TASKLOOP_SIMD;
9189 14 : break;
9190 0 : default:
9191 0 : gcc_unreachable ();
9192 : }
9193 39 : stmt = gfc_trans_omp_master_masked_taskloop (code, op);
9194 39 : parallel_combined = true;
9195 : }
9196 61 : if (TREE_CODE (stmt) != BIND_EXPR)
9197 48 : stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
9198 : else
9199 13 : poplevel (0, 0);
9200 61 : stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
9201 : void_type_node, stmt, omp_clauses);
9202 : /* masked does have just filter clause, but during gimplification
9203 : isn't represented by a gimplification omp context, so for
9204 : !$omp parallel masked don't set OMP_PARALLEL_COMBINED,
9205 : so that
9206 : !$omp parallel masked
9207 : !$omp taskloop simd lastprivate (x)
9208 : isn't confused with
9209 : !$omp parallel masked taskloop simd lastprivate (x) */
9210 61 : if (parallel_combined)
9211 39 : OMP_PARALLEL_COMBINED (stmt) = 1;
9212 61 : gfc_add_expr_to_block (&block, stmt);
9213 61 : if (code->op != EXEC_OMP_PARALLEL_MASTER)
9214 50 : gfc_free_split_omp_clauses (code, clausesa);
9215 61 : return gfc_finish_block (&block);
9216 : }
9217 :
9218 : static tree
9219 1388 : gfc_trans_omp_target_data (gfc_code *code)
9220 : {
9221 1388 : stmtblock_t block;
9222 1388 : tree stmt, omp_clauses;
9223 :
9224 1388 : gfc_start_block (&block);
9225 1388 : omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
9226 : code->loc);
9227 1388 : stmt = gfc_trans_omp_code (code->block->next, true);
9228 1388 : stmt = build2_loc (gfc_get_location (&code->loc), OMP_TARGET_DATA,
9229 : void_type_node, stmt, omp_clauses);
9230 1388 : gfc_add_expr_to_block (&block, stmt);
9231 1388 : return gfc_finish_block (&block);
9232 : }
9233 :
9234 : static tree
9235 380 : gfc_trans_omp_target_enter_data (gfc_code *code)
9236 : {
9237 380 : stmtblock_t block;
9238 380 : tree stmt, omp_clauses;
9239 :
9240 380 : gfc_start_block (&block);
9241 380 : omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
9242 : code->loc);
9243 380 : stmt = build1_loc (input_location, OMP_TARGET_ENTER_DATA, void_type_node,
9244 : omp_clauses);
9245 380 : gfc_add_expr_to_block (&block, stmt);
9246 380 : return gfc_finish_block (&block);
9247 : }
9248 :
9249 : static tree
9250 318 : gfc_trans_omp_target_exit_data (gfc_code *code)
9251 : {
9252 318 : stmtblock_t block;
9253 318 : tree stmt, omp_clauses;
9254 :
9255 318 : gfc_start_block (&block);
9256 318 : omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
9257 : code->loc, false, false, code->op);
9258 318 : stmt = build1_loc (input_location, OMP_TARGET_EXIT_DATA, void_type_node,
9259 : omp_clauses);
9260 318 : gfc_add_expr_to_block (&block, stmt);
9261 318 : return gfc_finish_block (&block);
9262 : }
9263 :
9264 : static tree
9265 1697 : gfc_trans_omp_target_update (gfc_code *code)
9266 : {
9267 1697 : stmtblock_t block;
9268 1697 : tree stmt, omp_clauses;
9269 :
9270 1697 : gfc_start_block (&block);
9271 1697 : omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
9272 : code->loc);
9273 1697 : stmt = build1_loc (input_location, OMP_TARGET_UPDATE, void_type_node,
9274 : omp_clauses);
9275 1697 : gfc_add_expr_to_block (&block, stmt);
9276 1697 : return gfc_finish_block (&block);
9277 : }
9278 :
9279 : static tree
9280 8 : gfc_trans_openmp_interop (gfc_code *code, gfc_omp_clauses *clauses)
9281 : {
9282 8 : stmtblock_t block;
9283 8 : gfc_start_block (&block);
9284 8 : tree omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
9285 8 : tree stmt = build1_loc (input_location, OMP_INTEROP, void_type_node,
9286 : omp_clauses);
9287 8 : gfc_add_expr_to_block (&block, stmt);
9288 8 : return gfc_finish_block (&block);
9289 : }
9290 :
9291 : static tree
9292 85 : gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses)
9293 : {
9294 85 : tree res, tmp, stmt;
9295 85 : stmtblock_t block, *pblock = NULL;
9296 85 : stmtblock_t singleblock;
9297 85 : int saved_ompws_flags;
9298 85 : bool singleblock_in_progress = false;
9299 : /* True if previous gfc_code in workshare construct is not workshared. */
9300 85 : bool prev_singleunit;
9301 85 : location_t loc = gfc_get_location (&code->loc);
9302 :
9303 85 : code = code->block->next;
9304 :
9305 85 : pushlevel ();
9306 :
9307 85 : gfc_start_block (&block);
9308 85 : pblock = █
9309 :
9310 85 : ompws_flags = OMPWS_WORKSHARE_FLAG;
9311 85 : prev_singleunit = false;
9312 :
9313 : /* Translate statements one by one to trees until we reach
9314 : the end of the workshare construct. Adjacent gfc_codes that
9315 : are a single unit of work are clustered and encapsulated in a
9316 : single OMP_SINGLE construct. */
9317 282 : for (; code; code = code->next)
9318 : {
9319 197 : if (code->here != 0)
9320 : {
9321 0 : res = gfc_trans_label_here (code);
9322 0 : gfc_add_expr_to_block (pblock, res);
9323 : }
9324 :
9325 : /* No dependence analysis, use for clauses with wait.
9326 : If this is the last gfc_code, use default omp_clauses. */
9327 197 : if (code->next == NULL && clauses->nowait)
9328 60 : ompws_flags |= OMPWS_NOWAIT;
9329 :
9330 : /* By default, every gfc_code is a single unit of work. */
9331 197 : ompws_flags |= OMPWS_CURR_SINGLEUNIT;
9332 197 : ompws_flags &= ~(OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY);
9333 :
9334 197 : switch (code->op)
9335 : {
9336 : case EXEC_NOP:
9337 : res = NULL_TREE;
9338 : break;
9339 :
9340 125 : case EXEC_ASSIGN:
9341 125 : res = gfc_trans_assign (code);
9342 125 : break;
9343 :
9344 0 : case EXEC_POINTER_ASSIGN:
9345 0 : res = gfc_trans_pointer_assign (code);
9346 0 : break;
9347 :
9348 0 : case EXEC_INIT_ASSIGN:
9349 0 : res = gfc_trans_init_assign (code);
9350 0 : break;
9351 :
9352 24 : case EXEC_FORALL:
9353 24 : res = gfc_trans_forall (code);
9354 24 : break;
9355 :
9356 19 : case EXEC_WHERE:
9357 19 : res = gfc_trans_where (code);
9358 19 : break;
9359 :
9360 7 : case EXEC_OMP_ATOMIC:
9361 7 : res = gfc_trans_omp_directive (code);
9362 7 : break;
9363 :
9364 17 : case EXEC_OMP_PARALLEL:
9365 17 : case EXEC_OMP_PARALLEL_DO:
9366 17 : case EXEC_OMP_PARALLEL_MASTER:
9367 17 : case EXEC_OMP_PARALLEL_SECTIONS:
9368 17 : case EXEC_OMP_PARALLEL_WORKSHARE:
9369 17 : case EXEC_OMP_CRITICAL:
9370 17 : saved_ompws_flags = ompws_flags;
9371 17 : ompws_flags = 0;
9372 17 : res = gfc_trans_omp_directive (code);
9373 17 : ompws_flags = saved_ompws_flags;
9374 17 : break;
9375 :
9376 5 : case EXEC_BLOCK:
9377 5 : res = gfc_trans_block_construct (code);
9378 5 : break;
9379 :
9380 0 : default:
9381 0 : gfc_internal_error ("gfc_trans_omp_workshare(): Bad statement code");
9382 : }
9383 :
9384 197 : input_location = gfc_get_location (&code->loc);
9385 :
9386 197 : if (res != NULL_TREE && ! IS_EMPTY_STMT (res))
9387 : {
9388 197 : if (prev_singleunit)
9389 : {
9390 72 : if (ompws_flags & OMPWS_CURR_SINGLEUNIT)
9391 : /* Add current gfc_code to single block. */
9392 44 : gfc_add_expr_to_block (&singleblock, res);
9393 : else
9394 : {
9395 : /* Finish single block and add it to pblock. */
9396 28 : tmp = gfc_finish_block (&singleblock);
9397 28 : tmp = build2_loc (loc, OMP_SINGLE,
9398 : void_type_node, tmp, NULL_TREE);
9399 28 : gfc_add_expr_to_block (pblock, tmp);
9400 : /* Add current gfc_code to pblock. */
9401 28 : gfc_add_expr_to_block (pblock, res);
9402 28 : singleblock_in_progress = false;
9403 : }
9404 : }
9405 : else
9406 : {
9407 125 : if (ompws_flags & OMPWS_CURR_SINGLEUNIT)
9408 : {
9409 : /* Start single block. */
9410 73 : gfc_init_block (&singleblock);
9411 73 : gfc_add_expr_to_block (&singleblock, res);
9412 73 : singleblock_in_progress = true;
9413 73 : loc = gfc_get_location (&code->loc);
9414 : }
9415 : else
9416 : /* Add the new statement to the block. */
9417 52 : gfc_add_expr_to_block (pblock, res);
9418 : }
9419 197 : prev_singleunit = (ompws_flags & OMPWS_CURR_SINGLEUNIT) != 0;
9420 : }
9421 : }
9422 :
9423 : /* Finish remaining SINGLE block, if we were in the middle of one. */
9424 85 : if (singleblock_in_progress)
9425 : {
9426 : /* Finish single block and add it to pblock. */
9427 45 : tmp = gfc_finish_block (&singleblock);
9428 45 : tmp = build2_loc (loc, OMP_SINGLE, void_type_node, tmp,
9429 45 : clauses->nowait
9430 27 : ? build_omp_clause (input_location, OMP_CLAUSE_NOWAIT)
9431 : : NULL_TREE);
9432 45 : gfc_add_expr_to_block (pblock, tmp);
9433 : }
9434 :
9435 85 : stmt = gfc_finish_block (pblock);
9436 85 : if (TREE_CODE (stmt) != BIND_EXPR)
9437 : {
9438 65 : if (!IS_EMPTY_STMT (stmt))
9439 : {
9440 65 : tree bindblock = poplevel (1, 0);
9441 65 : stmt = build3_v (BIND_EXPR, NULL, stmt, bindblock);
9442 : }
9443 : else
9444 0 : poplevel (0, 0);
9445 : }
9446 : else
9447 20 : poplevel (0, 0);
9448 :
9449 85 : if (IS_EMPTY_STMT (stmt) && !clauses->nowait)
9450 0 : stmt = gfc_trans_omp_barrier ();
9451 :
9452 85 : ompws_flags = 0;
9453 85 : return stmt;
9454 : }
9455 :
9456 : tree
9457 76 : gfc_trans_oacc_declare (gfc_code *code)
9458 : {
9459 76 : stmtblock_t block;
9460 76 : tree stmt, oacc_clauses;
9461 76 : enum tree_code construct_code;
9462 :
9463 76 : construct_code = OACC_DATA;
9464 :
9465 76 : gfc_start_block (&block);
9466 :
9467 76 : oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.oacc_declare->clauses,
9468 : code->loc, false, true);
9469 76 : stmt = gfc_trans_omp_code (code->block->next, true);
9470 76 : stmt = build2_loc (input_location, construct_code, void_type_node, stmt,
9471 : oacc_clauses);
9472 76 : gfc_add_expr_to_block (&block, stmt);
9473 :
9474 76 : return gfc_finish_block (&block);
9475 : }
9476 :
9477 : tree
9478 12036 : gfc_trans_oacc_directive (gfc_code *code)
9479 : {
9480 12036 : switch (code->op)
9481 : {
9482 1556 : case EXEC_OACC_PARALLEL_LOOP:
9483 1556 : case EXEC_OACC_KERNELS_LOOP:
9484 1556 : case EXEC_OACC_SERIAL_LOOP:
9485 1556 : return gfc_trans_oacc_combined_directive (code);
9486 4187 : case EXEC_OACC_PARALLEL:
9487 4187 : case EXEC_OACC_KERNELS:
9488 4187 : case EXEC_OACC_SERIAL:
9489 4187 : case EXEC_OACC_DATA:
9490 4187 : case EXEC_OACC_HOST_DATA:
9491 4187 : return gfc_trans_oacc_construct (code);
9492 3375 : case EXEC_OACC_LOOP:
9493 3375 : return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses,
9494 3375 : NULL);
9495 2126 : case EXEC_OACC_UPDATE:
9496 2126 : case EXEC_OACC_CACHE:
9497 2126 : case EXEC_OACC_ENTER_DATA:
9498 2126 : case EXEC_OACC_EXIT_DATA:
9499 2126 : return gfc_trans_oacc_executable_directive (code);
9500 173 : case EXEC_OACC_WAIT:
9501 173 : return gfc_trans_oacc_wait_directive (code);
9502 543 : case EXEC_OACC_ATOMIC:
9503 543 : return gfc_trans_omp_atomic (code);
9504 76 : case EXEC_OACC_DECLARE:
9505 76 : return gfc_trans_oacc_declare (code);
9506 0 : default:
9507 0 : gcc_unreachable ();
9508 : }
9509 : }
9510 :
9511 : tree
9512 18941 : gfc_trans_omp_directive (gfc_code *code)
9513 : {
9514 18941 : switch (code->op)
9515 : {
9516 35 : case EXEC_OMP_ALLOCATE:
9517 35 : case EXEC_OMP_ALLOCATORS:
9518 35 : return gfc_trans_omp_allocators (code);
9519 10 : case EXEC_OMP_ASSUME:
9520 10 : return gfc_trans_omp_assume (code);
9521 2053 : case EXEC_OMP_ATOMIC:
9522 2053 : return gfc_trans_omp_atomic (code);
9523 604 : case EXEC_OMP_BARRIER:
9524 604 : return gfc_trans_omp_barrier ();
9525 310 : case EXEC_OMP_CANCEL:
9526 310 : return gfc_trans_omp_cancel (code);
9527 170 : case EXEC_OMP_CANCELLATION_POINT:
9528 170 : return gfc_trans_omp_cancellation_point (code);
9529 143 : case EXEC_OMP_CRITICAL:
9530 143 : return gfc_trans_omp_critical (code);
9531 108 : case EXEC_OMP_DEPOBJ:
9532 108 : return gfc_trans_omp_depobj (code);
9533 2456 : case EXEC_OMP_DISTRIBUTE:
9534 2456 : case EXEC_OMP_DO:
9535 2456 : case EXEC_OMP_LOOP:
9536 2456 : case EXEC_OMP_SIMD:
9537 2456 : case EXEC_OMP_TASKLOOP:
9538 2456 : case EXEC_OMP_TILE:
9539 2456 : case EXEC_OMP_UNROLL:
9540 2456 : return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses,
9541 2456 : NULL);
9542 128 : case EXEC_OMP_DISPATCH:
9543 128 : return gfc_trans_omp_dispatch (code);
9544 113 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
9545 113 : case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
9546 113 : case EXEC_OMP_DISTRIBUTE_SIMD:
9547 113 : return gfc_trans_omp_distribute (code, NULL);
9548 126 : case EXEC_OMP_DO_SIMD:
9549 126 : return gfc_trans_omp_do_simd (code, NULL, NULL, NULL_TREE);
9550 29 : case EXEC_OMP_ERROR:
9551 29 : return gfc_trans_omp_error (code);
9552 70 : case EXEC_OMP_FLUSH:
9553 70 : return gfc_trans_omp_flush (code);
9554 38 : case EXEC_OMP_MASKED:
9555 38 : return gfc_trans_omp_masked (code, NULL);
9556 105 : case EXEC_OMP_MASTER:
9557 105 : return gfc_trans_omp_master (code);
9558 45 : case EXEC_OMP_MASKED_TASKLOOP:
9559 45 : case EXEC_OMP_MASKED_TASKLOOP_SIMD:
9560 45 : case EXEC_OMP_MASTER_TASKLOOP:
9561 45 : case EXEC_OMP_MASTER_TASKLOOP_SIMD:
9562 45 : return gfc_trans_omp_master_masked_taskloop (code, code->op);
9563 88 : case EXEC_OMP_METADIRECTIVE:
9564 88 : return gfc_trans_omp_metadirective (code);
9565 521 : case EXEC_OMP_ORDERED:
9566 521 : return gfc_trans_omp_ordered (code);
9567 1869 : case EXEC_OMP_PARALLEL:
9568 1869 : return gfc_trans_omp_parallel (code);
9569 1082 : case EXEC_OMP_PARALLEL_DO:
9570 1082 : return gfc_trans_omp_parallel_do (code, false, NULL, NULL);
9571 24 : case EXEC_OMP_PARALLEL_LOOP:
9572 24 : return gfc_trans_omp_parallel_do (code, true, NULL, NULL);
9573 285 : case EXEC_OMP_PARALLEL_DO_SIMD:
9574 285 : return gfc_trans_omp_parallel_do_simd (code, NULL, NULL);
9575 61 : case EXEC_OMP_PARALLEL_MASKED:
9576 61 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
9577 61 : case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
9578 61 : case EXEC_OMP_PARALLEL_MASTER:
9579 61 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
9580 61 : case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
9581 61 : return gfc_trans_omp_parallel_master_masked (code);
9582 54 : case EXEC_OMP_PARALLEL_SECTIONS:
9583 54 : return gfc_trans_omp_parallel_sections (code);
9584 50 : case EXEC_OMP_PARALLEL_WORKSHARE:
9585 50 : return gfc_trans_omp_parallel_workshare (code);
9586 53 : case EXEC_OMP_SCOPE:
9587 53 : return gfc_trans_omp_scope (code);
9588 75 : case EXEC_OMP_SECTIONS:
9589 75 : return gfc_trans_omp_sections (code, code->ext.omp_clauses);
9590 556 : case EXEC_OMP_SINGLE:
9591 556 : return gfc_trans_omp_single (code, code->ext.omp_clauses);
9592 2099 : case EXEC_OMP_TARGET:
9593 2099 : case EXEC_OMP_TARGET_PARALLEL:
9594 2099 : case EXEC_OMP_TARGET_PARALLEL_DO:
9595 2099 : case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
9596 2099 : case EXEC_OMP_TARGET_PARALLEL_LOOP:
9597 2099 : case EXEC_OMP_TARGET_SIMD:
9598 2099 : case EXEC_OMP_TARGET_TEAMS:
9599 2099 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
9600 2099 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
9601 2099 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
9602 2099 : case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
9603 2099 : case EXEC_OMP_TARGET_TEAMS_LOOP:
9604 2099 : return gfc_trans_omp_target (code);
9605 1388 : case EXEC_OMP_TARGET_DATA:
9606 1388 : return gfc_trans_omp_target_data (code);
9607 380 : case EXEC_OMP_TARGET_ENTER_DATA:
9608 380 : return gfc_trans_omp_target_enter_data (code);
9609 318 : case EXEC_OMP_TARGET_EXIT_DATA:
9610 318 : return gfc_trans_omp_target_exit_data (code);
9611 1697 : case EXEC_OMP_TARGET_UPDATE:
9612 1697 : return gfc_trans_omp_target_update (code);
9613 1121 : case EXEC_OMP_TASK:
9614 1121 : return gfc_trans_omp_task (code);
9615 181 : case EXEC_OMP_TASKGROUP:
9616 181 : return gfc_trans_omp_taskgroup (code);
9617 31 : case EXEC_OMP_TASKLOOP_SIMD:
9618 31 : return gfc_trans_omp_taskloop (code, code->op);
9619 145 : case EXEC_OMP_TASKWAIT:
9620 145 : return gfc_trans_omp_taskwait (code);
9621 8 : case EXEC_OMP_TASKYIELD:
9622 8 : return gfc_trans_omp_taskyield ();
9623 269 : case EXEC_OMP_TEAMS:
9624 269 : case EXEC_OMP_TEAMS_DISTRIBUTE:
9625 269 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
9626 269 : case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
9627 269 : case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
9628 269 : case EXEC_OMP_TEAMS_LOOP:
9629 269 : return gfc_trans_omp_teams (code, NULL, NULL_TREE);
9630 35 : case EXEC_OMP_WORKSHARE:
9631 35 : return gfc_trans_omp_workshare (code, code->ext.omp_clauses);
9632 8 : case EXEC_OMP_INTEROP:
9633 8 : return gfc_trans_openmp_interop (code, code->ext.omp_clauses);
9634 0 : default:
9635 0 : gcc_unreachable ();
9636 : }
9637 : }
9638 :
9639 : void
9640 109 : gfc_trans_omp_declare_simd (gfc_namespace *ns)
9641 : {
9642 109 : if (ns->entries)
9643 : return;
9644 :
9645 109 : gfc_omp_declare_simd *ods;
9646 262 : for (ods = ns->omp_declare_simd; ods; ods = ods->next)
9647 : {
9648 153 : tree c = gfc_trans_omp_clauses (NULL, ods->clauses, ods->where, true);
9649 153 : tree fndecl = ns->proc_name->backend_decl;
9650 153 : if (c != NULL_TREE)
9651 103 : c = tree_cons (NULL_TREE, c, NULL_TREE);
9652 153 : c = build_tree_list (get_identifier ("omp declare simd"), c);
9653 153 : TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
9654 153 : DECL_ATTRIBUTES (fndecl) = c;
9655 : }
9656 : }
9657 :
9658 : /* Translate the context selector list GFC_SELECTORS, using WHERE as the
9659 : locus for error messages. */
9660 :
9661 : static tree
9662 513 : gfc_trans_omp_set_selector (gfc_omp_set_selector *gfc_selectors, locus where)
9663 : {
9664 513 : tree set_selectors = NULL_TREE;
9665 513 : gfc_omp_set_selector *oss;
9666 :
9667 1004 : for (oss = gfc_selectors; oss; oss = oss->next)
9668 : {
9669 491 : tree selectors = NULL_TREE;
9670 491 : gfc_omp_selector *os;
9671 491 : enum omp_tss_code set = oss->code;
9672 491 : gcc_assert (set != OMP_TRAIT_SET_INVALID);
9673 :
9674 1107 : for (os = oss->trait_selectors; os; os = os->next)
9675 : {
9676 616 : tree scoreval = NULL_TREE;
9677 616 : tree properties = NULL_TREE;
9678 616 : gfc_omp_trait_property *otp;
9679 616 : enum omp_ts_code sel = os->code;
9680 :
9681 : /* Per the spec, "Implementations can ignore specified
9682 : selectors that are not those described in this section";
9683 : however, we must record such selectors because they
9684 : cause match failures. */
9685 616 : if (sel == OMP_TRAIT_INVALID)
9686 : {
9687 1 : selectors = make_trait_selector (sel, NULL_TREE, NULL_TREE,
9688 : selectors);
9689 1 : continue;
9690 : }
9691 :
9692 987 : for (otp = os->properties; otp; otp = otp->next)
9693 : {
9694 372 : switch (otp->property_kind)
9695 : {
9696 85 : case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
9697 85 : case OMP_TRAIT_PROPERTY_BOOL_EXPR:
9698 85 : {
9699 85 : tree expr = NULL_TREE;
9700 85 : gfc_se se;
9701 85 : gfc_init_se (&se, NULL);
9702 85 : gfc_conv_expr (&se, otp->expr);
9703 85 : expr = se.expr;
9704 85 : properties = make_trait_property (NULL_TREE, expr,
9705 : properties);
9706 : }
9707 85 : break;
9708 23 : case OMP_TRAIT_PROPERTY_ID:
9709 23 : properties
9710 23 : = make_trait_property (get_identifier (otp->name),
9711 : NULL_TREE, properties);
9712 23 : break;
9713 250 : case OMP_TRAIT_PROPERTY_NAME_LIST:
9714 250 : {
9715 250 : tree prop = OMP_TP_NAMELIST_NODE;
9716 250 : tree value = NULL_TREE;
9717 250 : if (otp->is_name)
9718 165 : value = get_identifier (otp->name);
9719 : else
9720 85 : value = gfc_conv_constant_to_tree (otp->expr);
9721 :
9722 250 : properties = make_trait_property (prop, value,
9723 : properties);
9724 : }
9725 250 : break;
9726 14 : case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
9727 14 : properties = gfc_trans_omp_clauses (NULL, otp->clauses,
9728 : where, true);
9729 14 : break;
9730 0 : default:
9731 0 : gcc_unreachable ();
9732 : }
9733 : }
9734 :
9735 615 : if (os->score)
9736 : {
9737 51 : gfc_se se;
9738 51 : gfc_init_se (&se, NULL);
9739 51 : gfc_conv_expr (&se, os->score);
9740 51 : scoreval = se.expr;
9741 : }
9742 :
9743 615 : selectors = make_trait_selector (sel, scoreval,
9744 : properties, selectors);
9745 : }
9746 491 : set_selectors = make_trait_set_selector (set, selectors, set_selectors);
9747 : }
9748 513 : return set_selectors;
9749 : }
9750 :
9751 : /* If 'ns' points to a formal namespace in an interface, ns->parent == NULL;
9752 : hence, parent_ns is used instead. */
9753 :
9754 : void
9755 10445 : gfc_trans_omp_declare_variant (gfc_namespace *ns, gfc_namespace *parent_ns)
9756 : {
9757 10445 : tree base_fn_decl = ns->proc_name->backend_decl;
9758 10445 : gfc_namespace *search_ns = ns;
9759 10445 : gfc_omp_declare_variant *next;
9760 :
9761 10445 : for (gfc_omp_declare_variant *odv = search_ns->omp_declare_variant;
9762 28362 : search_ns; odv = next)
9763 : {
9764 : /* Look in the parent namespace if there are no more directives in the
9765 : current namespace. */
9766 17917 : if (!odv)
9767 : {
9768 17532 : if (!search_ns->parent && search_ns == ns)
9769 : search_ns = parent_ns;
9770 : else
9771 12343 : search_ns = search_ns->parent;
9772 17532 : if (search_ns)
9773 7087 : next = search_ns->omp_declare_variant;
9774 17532 : continue;
9775 : }
9776 :
9777 385 : next = odv->next;
9778 :
9779 385 : if (odv->error_p)
9780 17 : continue;
9781 :
9782 : /* Check directive the first time it is encountered. */
9783 368 : bool error_found = true;
9784 :
9785 368 : if (odv->checked_p)
9786 43 : error_found = false;
9787 368 : if (odv->base_proc_symtree == NULL)
9788 : {
9789 331 : if (!search_ns->proc_name->attr.function
9790 212 : && !search_ns->proc_name->attr.subroutine)
9791 1 : gfc_error ("The base name for %<declare variant%> must be "
9792 : "specified at %L", &odv->where);
9793 : else
9794 : error_found = false;
9795 : }
9796 : else
9797 : {
9798 37 : if (!search_ns->contained
9799 21 : && !odv->base_proc_symtree->n.sym->attr.use_assoc
9800 5 : && strcmp (odv->base_proc_symtree->name,
9801 5 : ns->proc_name->name))
9802 1 : gfc_error ("The base name at %L does not match the name of the "
9803 : "current procedure", &odv->where);
9804 36 : else if (odv->base_proc_symtree->n.sym->attr.entry)
9805 1 : gfc_error ("The base name at %L must not be an entry name",
9806 : &odv->where);
9807 35 : else if (odv->base_proc_symtree->n.sym->attr.generic)
9808 1 : gfc_error ("The base name at %L must not be a generic name",
9809 : &odv->where);
9810 34 : else if (odv->base_proc_symtree->n.sym->attr.proc_pointer)
9811 1 : gfc_error ("The base name at %L must not be a procedure pointer",
9812 : &odv->where);
9813 33 : else if (odv->base_proc_symtree->n.sym->attr.implicit_type)
9814 1 : gfc_error ("The base procedure at %L must have an explicit "
9815 : "interface", &odv->where);
9816 : else
9817 : error_found = false;
9818 : }
9819 :
9820 368 : odv->checked_p = true;
9821 368 : if (error_found)
9822 : {
9823 6 : odv->error_p = true;
9824 6 : continue;
9825 : }
9826 :
9827 : /* Ignore directives that do not apply to the current procedure. */
9828 362 : if ((odv->base_proc_symtree == NULL && search_ns != ns)
9829 336 : || (odv->base_proc_symtree != NULL
9830 32 : && !ns->proc_name->attr.use_assoc
9831 19 : && strcmp (odv->base_proc_symtree->name, ns->proc_name->name))
9832 323 : || (odv->base_proc_symtree != NULL
9833 19 : && ns->proc_name->attr.use_assoc
9834 13 : && strcmp (odv->base_proc_symtree->n.sym->name,
9835 : ns->proc_name->name)))
9836 44 : continue;
9837 :
9838 318 : tree set_selectors = gfc_trans_omp_set_selector (odv->set_selectors,
9839 : odv->where);
9840 318 : const char *variant_proc_name = odv->variant_proc_symtree->name;
9841 318 : gfc_symbol *variant_proc_sym = odv->variant_proc_symtree->n.sym;
9842 318 : if (variant_proc_sym == NULL || variant_proc_sym->attr.implicit_type)
9843 : {
9844 39 : gfc_symtree *proc_st;
9845 39 : gfc_find_sym_tree (variant_proc_name, gfc_current_ns, 1, &proc_st);
9846 39 : variant_proc_sym = proc_st ? proc_st->n.sym : NULL;
9847 : }
9848 39 : if (variant_proc_sym == NULL)
9849 : {
9850 1 : gfc_error ("Cannot find symbol %qs at %L", variant_proc_name,
9851 : &odv->where);
9852 1 : continue;
9853 : }
9854 317 : set_selectors = omp_check_context_selector
9855 317 : (gfc_get_location (&odv->where), set_selectors,
9856 : OMP_CTX_DECLARE_VARIANT);
9857 317 : if (set_selectors != error_mark_node)
9858 : {
9859 297 : if (!variant_proc_sym->attr.implicit_type
9860 297 : && !variant_proc_sym->attr.subroutine
9861 89 : && !variant_proc_sym->attr.function)
9862 : {
9863 0 : gfc_error ("variant %qs at %L is not a function or subroutine",
9864 : variant_proc_name, &odv->where);
9865 0 : variant_proc_sym = NULL;
9866 : }
9867 297 : else if (variant_proc_sym == ns->proc_name)
9868 : {
9869 1 : gfc_error ("variant %qs at %L is the same as base function",
9870 : variant_proc_name, &odv->where);
9871 1 : variant_proc_sym = NULL;
9872 : }
9873 296 : else if (omp_get_context_selector (set_selectors,
9874 : OMP_TRAIT_SET_CONSTRUCT,
9875 : OMP_TRAIT_CONSTRUCT_SIMD)
9876 : == NULL_TREE)
9877 : {
9878 282 : char err[256];
9879 282 : gfc_formal_arglist *last_arg = NULL, *extra_arg = NULL;
9880 282 : int nappend_args = 0;
9881 282 : if (odv->append_args_list)
9882 : {
9883 26 : gfc_formal_arglist *arg;
9884 26 : int nargs = 0;
9885 26 : for (arg = gfc_sym_get_dummy_args (ns->proc_name);
9886 56 : arg; arg = arg->next)
9887 30 : nargs++;
9888 :
9889 26 : last_arg = gfc_sym_get_dummy_args (variant_proc_sym);
9890 33 : for (int i = 1 ; i < nargs && last_arg; i++)
9891 7 : last_arg = last_arg->next;
9892 26 : if (nargs == 0)
9893 : {
9894 3 : extra_arg = last_arg;
9895 3 : last_arg = NULL;
9896 3 : variant_proc_sym->formal = NULL;
9897 : }
9898 23 : else if (last_arg)
9899 : {
9900 23 : extra_arg = last_arg->next;
9901 23 : last_arg->next = NULL;
9902 : }
9903 76 : for (gfc_omp_namelist *n = odv->append_args_list; n != NULL;
9904 50 : n = n->next)
9905 50 : nappend_args++;
9906 : }
9907 282 : if (!gfc_compare_interfaces (ns->proc_name, variant_proc_sym,
9908 : variant_proc_sym->name, 0, 1,
9909 : err, sizeof (err), NULL, NULL))
9910 : {
9911 2 : gfc_error ("variant %qs and base %qs at %L have "
9912 : "incompatible types: %s",
9913 2 : variant_proc_name, ns->proc_name->name,
9914 : &odv->where, err);
9915 2 : if (nappend_args)
9916 0 : inform (gfc_get_location (&odv->append_args_list->where),
9917 : "%<append_args%> clause implies that %qs has %d "
9918 : "dummy arguments of integer type with "
9919 : "%<omp_interop_kind%> kind", variant_proc_name,
9920 : nappend_args);
9921 : variant_proc_sym = NULL;
9922 : }
9923 282 : if (last_arg)
9924 23 : last_arg->next = extra_arg;
9925 259 : else if (extra_arg)
9926 3 : variant_proc_sym->formal = extra_arg;
9927 26 : locus *loc = (odv->append_args_list
9928 282 : ? &odv->append_args_list->where : &odv->where);
9929 282 : int nextra_arg = 0;
9930 335 : for (; extra_arg; extra_arg = extra_arg->next)
9931 : {
9932 53 : nextra_arg++;
9933 53 : if (!variant_proc_sym)
9934 8 : continue;
9935 45 : if (extra_arg->sym->ts.type != BT_INTEGER
9936 43 : || extra_arg->sym->ts.kind != gfc_index_integer_kind
9937 42 : || extra_arg->sym->attr.dimension
9938 40 : || extra_arg->sym->attr.codimension
9939 39 : || extra_arg->sym->attr.pointer
9940 38 : || extra_arg->sym->attr.allocatable
9941 37 : || extra_arg->sym->attr.proc_pointer)
9942 : {
9943 8 : gfc_error ("%qs at %L must be a nonpointer, "
9944 : "nonallocatable scalar integer dummy argument "
9945 : "of %<omp_interop_kind%> kind as it utilized "
9946 : "with the %<append_args%> clause at %L",
9947 : extra_arg->sym->name,
9948 : &extra_arg->sym->declared_at, loc);
9949 8 : variant_proc_sym = NULL;
9950 : }
9951 45 : if (extra_arg->sym->attr.optional)
9952 : {
9953 2 : gfc_error ("%qs at %L with OPTIONAL attribute "
9954 : "not support when utilized with the "
9955 : "%<append_args%> clause at %L",
9956 : extra_arg->sym->name,
9957 : &extra_arg->sym->declared_at, loc);
9958 2 : variant_proc_sym = NULL;
9959 : }
9960 : }
9961 282 : if (variant_proc_sym && nappend_args != nextra_arg)
9962 : {
9963 1 : gfc_error ("%qs at %L has %d but requires %d "
9964 : "%<omp_interop_kind%> kind dummy arguments as it "
9965 : "is utilized with the %<append_args%> clause at "
9966 : "%L", variant_proc_sym->name,
9967 : &variant_proc_sym->declared_at, nextra_arg,
9968 : nappend_args, loc);
9969 1 : variant_proc_sym = NULL;
9970 : }
9971 : }
9972 251 : if ((odv->adjust_args_list != NULL || odv->append_args_list != NULL)
9973 322 : && omp_get_context_selector (set_selectors,
9974 : OMP_TRAIT_SET_CONSTRUCT,
9975 : OMP_TRAIT_CONSTRUCT_DISPATCH)
9976 : == NULL_TREE)
9977 : {
9978 6 : gfc_error ("the %qs clause can only be specified if "
9979 : "the %<dispatch%> selector of the construct "
9980 : "selector set appears in the %<match%> clause at %L",
9981 3 : odv->adjust_args_list ? "adjust_args" : "append_args",
9982 : &odv->where);
9983 3 : variant_proc_sym = NULL;
9984 : }
9985 297 : if (variant_proc_sym != NULL)
9986 : {
9987 281 : gfc_set_sym_referenced (variant_proc_sym);
9988 281 : tree construct
9989 281 : = omp_get_context_selector_list (set_selectors,
9990 : OMP_TRAIT_SET_CONSTRUCT);
9991 281 : omp_mark_declare_variant (gfc_get_location (&odv->where),
9992 : gfc_get_symbol_decl (variant_proc_sym),
9993 : construct);
9994 281 : if (omp_context_selector_matches (set_selectors,
9995 : NULL_TREE, false))
9996 : {
9997 202 : tree need_device_ptr_list = NULL_TREE;
9998 202 : tree need_device_addr_list = NULL_TREE;
9999 202 : tree append_args_tree = NULL_TREE;
10000 202 : tree id = get_identifier ("omp declare variant base");
10001 202 : tree variant = gfc_get_symbol_decl (variant_proc_sym);
10002 202 : DECL_ATTRIBUTES (base_fn_decl)
10003 202 : = tree_cons (id, build_tree_list (variant, set_selectors),
10004 202 : DECL_ATTRIBUTES (base_fn_decl));
10005 202 : int arg_idx_offset = 0;
10006 202 : if (gfc_return_by_reference (ns->proc_name))
10007 : {
10008 2 : arg_idx_offset++;
10009 2 : if (ns->proc_name->ts.type == BT_CHARACTER)
10010 2 : arg_idx_offset++;
10011 : }
10012 202 : int nargs = 0;
10013 202 : for (gfc_formal_arglist *arg
10014 202 : = gfc_sym_get_dummy_args (ns->proc_name);
10015 443 : arg; arg = arg->next)
10016 241 : nargs++;
10017 202 : if (odv->append_args_list)
10018 : {
10019 14 : int append_arg_no = arg_idx_offset + nargs;
10020 14 : tree last_arg = NULL_TREE;
10021 14 : for (gfc_omp_namelist *n = odv->append_args_list;
10022 43 : n != NULL; n = n->next)
10023 : {
10024 29 : tree pref = NULL_TREE;
10025 29 : if (n->u.init.len)
10026 : {
10027 22 : pref = build_string (n->u.init.len,
10028 11 : n->u2.init_interop);
10029 11 : TREE_TYPE (pref) = build_array_type_nelts (
10030 : unsigned_char_type_node,
10031 11 : n->u.init.len);
10032 : }
10033 : /* Save location, (target + target sync) and
10034 : prefer_type list in a tree list. */
10035 29 : tree t = build_tree_list (n->u.init.target
10036 : ? boolean_true_node
10037 : : boolean_false_node,
10038 29 : n->u.init.targetsync
10039 : ? boolean_true_node
10040 : : boolean_false_node);
10041 29 : t = build1_loc (gfc_get_location (&n->where),
10042 : NOP_EXPR, void_type_node, t);
10043 29 : t = build_tree_list (t, pref);
10044 29 : if (append_args_tree)
10045 : {
10046 15 : TREE_CHAIN (last_arg) = t;
10047 15 : last_arg = t;
10048 : }
10049 : else
10050 : append_args_tree = last_arg = t;
10051 : }
10052 : /* Store as 'purpose' = arg number to be used for inserting
10053 : and 'value' = list of interop items. */
10054 14 : append_args_tree = build_tree_list (
10055 : build_int_cst (integer_type_node,
10056 14 : append_arg_no),
10057 : append_args_tree);
10058 : }
10059 202 : vec<gfc_symbol *> adjust_args_list = vNULL;
10060 202 : for (gfc_omp_namelist *arg_list = odv->adjust_args_list;
10061 312 : arg_list != NULL; arg_list = arg_list->next)
10062 : {
10063 110 : int from, to;
10064 110 : if (arg_list->expr == NULL || arg_list->sym)
10065 204 : from = ((arg_list->u.adj_args.omp_num_args_minus
10066 94 : || arg_list->u.adj_args.omp_num_args_plus)
10067 94 : ? nargs : 1);
10068 : else
10069 : {
10070 16 : if (arg_list->u.adj_args.omp_num_args_plus)
10071 0 : mpz_add_ui (arg_list->expr->value.integer,
10072 0 : arg_list->expr->value.integer, nargs);
10073 16 : if (arg_list->u.adj_args.omp_num_args_minus)
10074 2 : mpz_ui_sub (arg_list->expr->value.integer, nargs,
10075 2 : arg_list->expr->value.integer);
10076 16 : if (mpz_sgn (arg_list->expr->value.integer) <= 0)
10077 : {
10078 1 : gfc_warning (OPT_Wopenmp,
10079 : "Expected positive argument index "
10080 : "at %L", &arg_list->where);
10081 1 : from = 1;
10082 : }
10083 : else
10084 15 : from
10085 15 : = (mpz_fits_sint_p (arg_list->expr->value.integer)
10086 15 : ? mpz_get_si (arg_list->expr->value.integer)
10087 : : INT_MAX);
10088 16 : if (from > nargs)
10089 1 : gfc_warning (OPT_Wopenmp,
10090 : "Argument index at %L exceeds number "
10091 : "of arguments %d", &arg_list->where,
10092 : nargs);
10093 : }
10094 110 : locus loc = arg_list->where;
10095 110 : if (!arg_list->u.adj_args.range_start)
10096 : to = from;
10097 : else
10098 : {
10099 6 : loc = gfc_get_location_range (&arg_list->where, 0,
10100 : &arg_list->where, 0,
10101 6 : &arg_list->next->where);
10102 6 : if (arg_list->next->expr == NULL)
10103 : to = nargs;
10104 : else
10105 : {
10106 4 : if (arg_list->next->u.adj_args.omp_num_args_plus)
10107 0 : mpz_add_ui (arg_list->next->expr->value.integer,
10108 0 : arg_list->next->expr->value.integer,
10109 : nargs);
10110 4 : if (arg_list->next->u.adj_args.omp_num_args_minus)
10111 2 : mpz_ui_sub (arg_list->next->expr->value.integer,
10112 : nargs,
10113 2 : arg_list->next->expr->value.integer);
10114 4 : if (mpz_sgn (arg_list->next->expr->value.integer)
10115 : <= 0)
10116 : {
10117 0 : gfc_warning (OPT_Wopenmp,
10118 : "Expected positive argument "
10119 : "index at %L", &loc);
10120 0 : to = 0;
10121 : }
10122 : else
10123 4 : to = mpz_get_si (
10124 4 : arg_list->next->expr->value.integer);
10125 : }
10126 6 : if (from > to && to != 0)
10127 1 : gfc_warning (OPT_Wopenmp,
10128 : "Upper argument index smaller than "
10129 : "lower one at %L", &loc);
10130 6 : if (to > nargs)
10131 : to = nargs;
10132 6 : arg_list = arg_list->next;
10133 : }
10134 110 : if (from > nargs)
10135 1 : continue;
10136 : /* Change to zero based index. */
10137 109 : from--; to--;
10138 109 : gfc_formal_arglist *arg = ns->proc_name->formal;
10139 109 : if (!arg_list->sym && to >= from)
10140 35 : for (int idx = 0; idx < from; idx++)
10141 18 : arg = arg->next;
10142 223 : for (int idx = from; idx <= to; idx++)
10143 : {
10144 114 : if (idx > from)
10145 6 : arg = arg->next;
10146 114 : if (arg_list->sym)
10147 : {
10148 91 : for (arg = ns->proc_name->formal, idx = 0;
10149 201 : arg != NULL; arg = arg->next, idx++)
10150 200 : if (arg->sym == arg_list->sym)
10151 : break;
10152 91 : if (!arg || !arg_list->sym->attr.dummy)
10153 : {
10154 1 : gfc_error ("List item %qs at %L, declared at "
10155 : "%L, is not a dummy argument",
10156 : arg_list->sym->name, &loc,
10157 : &arg_list->sym->declared_at);
10158 1 : continue;
10159 : }
10160 : }
10161 113 : if (arg_list->u.adj_args.need_ptr
10162 82 : && (arg->sym->ts.f90_type != BT_VOID
10163 80 : || !arg->sym->ts.u.derived->ts.is_iso_c
10164 80 : || (arg->sym->ts.u.derived->intmod_sym_id
10165 : != ISOCBINDING_PTR)
10166 79 : || arg->sym->attr.dimension))
10167 : {
10168 6 : gfc_error ("Argument %qs at %L to list item in "
10169 : "%<need_device_ptr%> at %L must be a "
10170 : "scalar of TYPE(C_PTR)",
10171 : arg->sym->name,
10172 : &arg->sym->declared_at, &loc);
10173 6 : if (!arg->sym->attr.value)
10174 6 : inform (gfc_get_location (&loc),
10175 : "Consider using %<need_device_addr%> "
10176 : "instead");
10177 6 : continue;
10178 : }
10179 107 : if (arg_list->u.adj_args.need_addr
10180 11 : && arg->sym->attr.value)
10181 : {
10182 1 : gfc_error ("Argument %qs at %L to list item in "
10183 : "%<need_device_addr%> at %L must not "
10184 : "have the VALUE attribute",
10185 : arg->sym->name,
10186 : &arg->sym->declared_at, &loc);
10187 1 : continue;
10188 : }
10189 106 : if (adjust_args_list.contains (arg->sym))
10190 : {
10191 7 : gfc_error ("%qs at %L is specified more than "
10192 7 : "once", arg->sym->name, &loc);
10193 7 : continue;
10194 : }
10195 99 : adjust_args_list.safe_push (arg->sym);
10196 :
10197 99 : if (arg_list->u.adj_args.need_addr)
10198 : {
10199 : /* TODO: Has to to support OPTIONAL and array
10200 : descriptors; should check for CLASS, coarrays?
10201 : Reject "abc" and 123 as actual arguments (in
10202 : gimplify.cc or in the FE? Reject noncontiguous
10203 : actuals? Cf. also PR C++/118859.
10204 : Also check array-valued type(c_ptr). */
10205 7 : static bool warned = false;
10206 7 : if (!warned)
10207 1 : sorry_at (gfc_get_location (&loc),
10208 : "%<need_device_addr%> not yet "
10209 : "supported");
10210 7 : warned = true;
10211 7 : continue;
10212 7 : }
10213 92 : if (arg_list->u.adj_args.need_ptr
10214 : || arg_list->u.adj_args.need_addr)
10215 : {
10216 : // Store 0-based argument index,
10217 : // as in gimplify_call_expr
10218 74 : tree t
10219 74 : = build_tree_list (
10220 : NULL_TREE,
10221 : build_int_cst (integer_type_node,
10222 74 : idx + arg_idx_offset));
10223 74 : if (arg_list->u.adj_args.need_ptr)
10224 74 : need_device_ptr_list
10225 74 : = chainon (need_device_ptr_list, t);
10226 : else
10227 0 : need_device_addr_list
10228 0 : = chainon (need_device_addr_list, t);
10229 : }
10230 : }
10231 : }
10232 202 : tree t = NULL_TREE;
10233 202 : if (need_device_ptr_list
10234 202 : || need_device_addr_list
10235 166 : || append_args_tree)
10236 : {
10237 50 : t = build_tree_list (need_device_ptr_list,
10238 : need_device_addr_list),
10239 50 : TREE_CHAIN (t) = append_args_tree;
10240 50 : DECL_ATTRIBUTES (variant) = tree_cons (
10241 : get_identifier ("omp declare variant variant args"), t,
10242 50 : DECL_ATTRIBUTES (variant));
10243 : }
10244 : }
10245 : }
10246 : }
10247 : }
10248 10445 : }
10249 :
10250 : /* Add ptr for tracking as being allocated by GOMP_alloc. */
10251 :
10252 : tree
10253 29 : gfc_omp_call_add_alloc (tree ptr)
10254 : {
10255 29 : static tree fn = NULL_TREE;
10256 29 : if (fn == NULL_TREE)
10257 : {
10258 6 : fn = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
10259 6 : tree att = build_tree_list (NULL_TREE, build_string (4, ". R "));
10260 6 : att = tree_cons (get_identifier ("fn spec"), att, TYPE_ATTRIBUTES (fn));
10261 6 : fn = build_type_attribute_variant (fn, att);
10262 6 : fn = build_fn_decl ("GOMP_add_alloc", fn);
10263 : }
10264 29 : return build_call_expr_loc (input_location, fn, 1, ptr);
10265 : }
10266 :
10267 : /* Generated function returns true when it was tracked via GOMP_add_alloc and
10268 : removes it from the tracking. As called just before GOMP_free or omp_realloc
10269 : the pointer is or might become invalid, thus, it is always removed. */
10270 :
10271 : tree
10272 47 : gfc_omp_call_is_alloc (tree ptr)
10273 : {
10274 47 : static tree fn = NULL_TREE;
10275 47 : if (fn == NULL_TREE)
10276 : {
10277 6 : fn = build_function_type_list (boolean_type_node, ptr_type_node,
10278 : NULL_TREE);
10279 6 : tree att = build_tree_list (NULL_TREE, build_string (4, ". R "));
10280 6 : att = tree_cons (get_identifier ("fn spec"), att, TYPE_ATTRIBUTES (fn));
10281 6 : fn = build_type_attribute_variant (fn, att);
10282 6 : fn = build_fn_decl ("GOMP_is_alloc", fn);
10283 : }
10284 47 : return build_call_expr_loc (input_location, fn, 1, ptr);
10285 : }
10286 :
10287 : tree
10288 88 : gfc_trans_omp_metadirective (gfc_code *code)
10289 : {
10290 88 : gfc_omp_variant *variant = code->ext.omp_variants;
10291 :
10292 88 : tree metadirective_tree = make_node (OMP_METADIRECTIVE);
10293 88 : SET_EXPR_LOCATION (metadirective_tree, gfc_get_location (&code->loc));
10294 88 : TREE_TYPE (metadirective_tree) = void_type_node;
10295 88 : OMP_METADIRECTIVE_VARIANTS (metadirective_tree) = NULL_TREE;
10296 :
10297 88 : tree tree_body = NULL_TREE;
10298 :
10299 283 : while (variant)
10300 : {
10301 195 : tree ctx = gfc_trans_omp_set_selector (variant->selectors,
10302 : variant->where);
10303 195 : ctx = omp_check_context_selector (gfc_get_location (&variant->where),
10304 : ctx, OMP_CTX_METADIRECTIVE);
10305 195 : if (ctx == error_mark_node)
10306 : return error_mark_node;
10307 :
10308 : /* If the selector doesn't match, drop the whole variant. */
10309 195 : if (!omp_context_selector_matches (ctx, NULL_TREE, false))
10310 : {
10311 23 : variant = variant->next;
10312 23 : continue;
10313 : }
10314 :
10315 172 : gfc_code *next_code = variant->code->next;
10316 172 : if (next_code && tree_body == NULL_TREE)
10317 18 : tree_body = gfc_trans_code (next_code);
10318 :
10319 172 : if (next_code)
10320 20 : variant->code->next = NULL;
10321 172 : tree directive = gfc_trans_code (variant->code);
10322 172 : if (next_code)
10323 20 : variant->code->next = next_code;
10324 :
10325 20 : tree body = next_code ? tree_body : NULL_TREE;
10326 172 : tree omp_variant = make_omp_metadirective_variant (ctx, directive, body);
10327 344 : OMP_METADIRECTIVE_VARIANTS (metadirective_tree)
10328 172 : = chainon (OMP_METADIRECTIVE_VARIANTS (metadirective_tree),
10329 : omp_variant);
10330 172 : variant = variant->next;
10331 : }
10332 :
10333 : /* TODO: Resolve the metadirective here if possible. */
10334 :
10335 : return metadirective_tree;
10336 : }
|