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