Line data Source code
1 : /* Lowering pass for OMP directives. Converts OMP directives into explicit
2 : calls to the runtime library (libgomp), data marshalling to implement data
3 : sharing and copying clauses, offloading to accelerators, and more.
4 :
5 : Contributed by Diego Novillo <dnovillo@redhat.com>
6 :
7 : Copyright (C) 2005-2026 Free Software Foundation, Inc.
8 :
9 : This file is part of GCC.
10 :
11 : GCC is free software; you can redistribute it and/or modify it under
12 : the terms of the GNU General Public License as published by the Free
13 : Software Foundation; either version 3, or (at your option) any later
14 : version.
15 :
16 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 : for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with GCC; see the file COPYING3. If not see
23 : <http://www.gnu.org/licenses/>. */
24 :
25 : #include "config.h"
26 : #include "system.h"
27 : #include "coretypes.h"
28 : #include "backend.h"
29 : #include "target.h"
30 : #include "tree.h"
31 : #include "gimple.h"
32 : #include "tree-pass.h"
33 : #include "ssa.h"
34 : #include "cgraph.h"
35 : #include "pretty-print.h"
36 : #include "diagnostic-core.h"
37 : #include "fold-const.h"
38 : #include "stor-layout.h"
39 : #include "internal-fn.h"
40 : #include "gimple-iterator.h"
41 : #include "gimple-fold.h"
42 : #include "gimplify.h"
43 : #include "gimplify-me.h"
44 : #include "gimple-walk.h"
45 : #include "tree-iterator.h"
46 : #include "tree-inline.h"
47 : #include "langhooks.h"
48 : #include "tree-dfa.h"
49 : #include "tree-ssa.h"
50 : #include "splay-tree.h"
51 : #include "omp-general.h"
52 : #include "omp-low.h"
53 : #include "gimple-low.h"
54 : #include "alloc-pool.h"
55 : #include "symbol-summary.h"
56 : #include "tree-nested.h"
57 : #include "context.h"
58 : #include "gomp-constants.h"
59 : #include "gimple-pretty-print.h"
60 : #include "stringpool.h"
61 : #include "attribs.h"
62 : #include "omp-offload.h"
63 :
64 : /* Lowering of OMP parallel and workshare constructs proceeds in two
65 : phases. The first phase scans the function looking for OMP statements
66 : and then for variables that must be replaced to satisfy data sharing
67 : clauses. The second phase expands code for the constructs, as well as
68 : re-gimplifying things when variables have been replaced with complex
69 : expressions.
70 :
71 : Final code generation is done by pass_expand_omp. The flowgraph is
72 : scanned for regions which are then moved to a new
73 : function, to be invoked by the thread library, or offloaded. */
74 :
75 : /* Context structure. Used to store information about each parallel
76 : directive in the code. */
77 :
78 : struct omp_context
79 : {
80 : /* This field must be at the beginning, as we do "inheritance": Some
81 : callback functions for tree-inline.cc (e.g., omp_copy_decl)
82 : receive a copy_body_data pointer that is up-casted to an
83 : omp_context pointer. */
84 : copy_body_data cb;
85 :
86 : /* The tree of contexts corresponding to the encountered constructs. */
87 : struct omp_context *outer;
88 : gimple *stmt;
89 :
90 : /* Map variables to fields in a structure that allows communication
91 : between sending and receiving threads. */
92 : splay_tree field_map;
93 : tree record_type;
94 : tree sender_decl;
95 : tree receiver_decl;
96 :
97 : /* These are used just by task contexts, if task firstprivate fn is
98 : needed. srecord_type is used to communicate from the thread
99 : that encountered the task construct to task firstprivate fn,
100 : record_type is allocated by GOMP_task, initialized by task firstprivate
101 : fn and passed to the task body fn. */
102 : splay_tree sfield_map;
103 : tree srecord_type;
104 :
105 : /* A chain of variables to add to the top-level block surrounding the
106 : construct. In the case of a parallel, this is in the child function. */
107 : tree block_vars;
108 :
109 : /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
110 : barriers should jump to during omplower pass. */
111 : tree cancel_label;
112 :
113 : /* The sibling GIMPLE_OMP_FOR simd with _simt_ clause or NULL
114 : otherwise. */
115 : gimple *simt_stmt;
116 :
117 : /* For task reductions registered in this context, a vector containing
118 : the length of the private copies block (if constant, otherwise NULL)
119 : and then offsets (if constant, otherwise NULL) for each entry. */
120 : vec<tree> task_reductions;
121 :
122 : /* A hash map from the reduction clauses to the registered array
123 : elts. */
124 : hash_map<tree, unsigned> *task_reduction_map;
125 :
126 : /* And a hash map from the lastprivate(conditional:) variables to their
127 : corresponding tracking loop iteration variables. */
128 : hash_map<tree, tree> *lastprivate_conditional_map;
129 :
130 : /* And a hash map from the allocate variables to their corresponding
131 : allocators. */
132 : hash_map<tree, tree> *allocate_map;
133 :
134 : /* A tree_list of the reduction clauses in this context. This is
135 : only used for checking the consistency of OpenACC reduction
136 : clauses in scan_omp_for and is not guaranteed to contain a valid
137 : value outside of this function. */
138 : tree local_reduction_clauses;
139 :
140 : /* A tree_list of the reduction clauses in outer contexts. This is
141 : only used for checking the consistency of OpenACC reduction
142 : clauses in scan_omp_for and is not guaranteed to contain a valid
143 : value outside of this function. */
144 : tree outer_reduction_clauses;
145 :
146 : /* Nesting depth of this context. Used to beautify error messages re
147 : invalid gotos. The outermost ctx is depth 1, with depth 0 being
148 : reserved for the main body of the function. */
149 : int depth;
150 :
151 : /* True if this parallel directive is nested within another. */
152 : bool is_nested;
153 :
154 : /* True if this construct can be cancelled. */
155 : bool cancellable;
156 :
157 : /* True if lower_omp_1 should look up lastprivate conditional in parent
158 : context. */
159 : bool combined_into_simd_safelen1;
160 :
161 : /* True if there is nested scan context with inclusive clause. */
162 : bool scan_inclusive;
163 :
164 : /* True if there is nested scan context with exclusive clause. */
165 : bool scan_exclusive;
166 :
167 : /* True in the second simd loop of for simd with inscan reductions. */
168 : bool for_simd_scan_phase;
169 :
170 : /* True if there is order(concurrent) clause on the construct. */
171 : bool order_concurrent;
172 :
173 : /* True if there is bind clause on the construct (i.e. a loop construct). */
174 : bool loop_p;
175 :
176 : /* Only used for omp target contexts. True if a teams construct is
177 : strictly nested in it. */
178 : bool teams_nested_p;
179 :
180 : /* Only used for omp target contexts. True if an OpenMP construct other
181 : than teams is strictly nested in it. */
182 : bool nonteams_nested_p;
183 :
184 : /* Candidates for adjusting OpenACC privatization level. */
185 : vec<tree> oacc_privatization_candidates;
186 : };
187 :
188 : static splay_tree all_contexts;
189 : static int taskreg_nesting_level;
190 : static int target_nesting_level;
191 : static bitmap make_addressable_vars;
192 : static bitmap global_nonaddressable_vars;
193 : static vec<omp_context *> taskreg_contexts;
194 : static vec<gomp_task *> task_cpyfns;
195 :
196 : static void scan_omp (gimple_seq *, omp_context *);
197 : static tree scan_omp_1_op (tree *, int *, void *);
198 : static bool omp_maybe_offloaded_ctx (omp_context *ctx);
199 :
200 : #define WALK_SUBSTMTS \
201 : case GIMPLE_BIND: \
202 : case GIMPLE_TRY: \
203 : case GIMPLE_CATCH: \
204 : case GIMPLE_EH_FILTER: \
205 : case GIMPLE_ASSUME: \
206 : case GIMPLE_TRANSACTION: \
207 : /* The sub-statements for these should be walked. */ \
208 : *handled_ops_p = false; \
209 : break;
210 :
211 : /* Return whether CTX represents an OpenACC 'parallel' or 'serial' construct.
212 : (This doesn't include OpenACC 'kernels' decomposed parts.) */
213 :
214 : static bool
215 33658 : is_oacc_parallel_or_serial (omp_context *ctx)
216 : {
217 33658 : enum gimple_code outer_type = gimple_code (ctx->stmt);
218 33658 : return ((outer_type == GIMPLE_OMP_TARGET)
219 33658 : && ((gimple_omp_target_kind (ctx->stmt)
220 : == GF_OMP_TARGET_KIND_OACC_PARALLEL)
221 15316 : || (gimple_omp_target_kind (ctx->stmt)
222 33658 : == GF_OMP_TARGET_KIND_OACC_SERIAL)));
223 : }
224 :
225 : /* Return whether CTX represents an OpenACC 'kernels' construct.
226 : (This doesn't include OpenACC 'kernels' decomposed parts.) */
227 :
228 : static bool
229 49900 : is_oacc_kernels (omp_context *ctx)
230 : {
231 49900 : enum gimple_code outer_type = gimple_code (ctx->stmt);
232 49900 : return ((outer_type == GIMPLE_OMP_TARGET)
233 49900 : && (gimple_omp_target_kind (ctx->stmt)
234 49900 : == GF_OMP_TARGET_KIND_OACC_KERNELS));
235 : }
236 :
237 : /* Return whether CTX represents an OpenACC 'kernels' decomposed part. */
238 :
239 : static bool
240 21645 : is_oacc_kernels_decomposed_part (omp_context *ctx)
241 : {
242 21645 : enum gimple_code outer_type = gimple_code (ctx->stmt);
243 21645 : return ((outer_type == GIMPLE_OMP_TARGET)
244 21645 : && ((gimple_omp_target_kind (ctx->stmt)
245 : == GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED)
246 14552 : || (gimple_omp_target_kind (ctx->stmt)
247 : == GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE)
248 14552 : || (gimple_omp_target_kind (ctx->stmt)
249 21645 : == GF_OMP_TARGET_KIND_OACC_DATA_KERNELS)));
250 : }
251 :
252 : /* Return true if STMT corresponds to an OpenMP target region. */
253 : static bool
254 42898 : is_omp_target (gimple *stmt)
255 : {
256 42898 : if (gimple_code (stmt) == GIMPLE_OMP_TARGET)
257 : {
258 6511 : int kind = gimple_omp_target_kind (stmt);
259 6511 : return (kind == GF_OMP_TARGET_KIND_REGION
260 6511 : || kind == GF_OMP_TARGET_KIND_DATA
261 6511 : || kind == GF_OMP_TARGET_KIND_ENTER_DATA
262 11147 : || kind == GF_OMP_TARGET_KIND_EXIT_DATA);
263 : }
264 : return false;
265 : }
266 :
267 : /* If DECL is the artificial dummy VAR_DECL created for non-static
268 : data member privatization, return the underlying "this" parameter,
269 : otherwise return NULL. */
270 :
271 : tree
272 536974 : omp_member_access_dummy_var (tree decl)
273 : {
274 536974 : if (!VAR_P (decl)
275 329509 : || !DECL_ARTIFICIAL (decl)
276 161805 : || !DECL_IGNORED_P (decl)
277 156377 : || !DECL_HAS_VALUE_EXPR_P (decl)
278 549759 : || !lang_hooks.decls.omp_disregard_value_expr (decl, false))
279 534714 : return NULL_TREE;
280 :
281 2260 : tree v = DECL_VALUE_EXPR (decl);
282 2260 : if (TREE_CODE (v) != COMPONENT_REF)
283 : return NULL_TREE;
284 :
285 16164 : while (1)
286 9197 : switch (TREE_CODE (v))
287 : {
288 6967 : case COMPONENT_REF:
289 6967 : case MEM_REF:
290 6967 : case INDIRECT_REF:
291 6967 : CASE_CONVERT:
292 6967 : case POINTER_PLUS_EXPR:
293 6967 : v = TREE_OPERAND (v, 0);
294 6967 : continue;
295 2211 : case PARM_DECL:
296 2211 : if (DECL_CONTEXT (v) == current_function_decl
297 2211 : && DECL_ARTIFICIAL (v)
298 4422 : && TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE)
299 : return v;
300 : return NULL_TREE;
301 : default:
302 : return NULL_TREE;
303 : }
304 : }
305 :
306 : /* Helper for unshare_and_remap, called through walk_tree. */
307 :
308 : static tree
309 1579 : unshare_and_remap_1 (tree *tp, int *walk_subtrees, void *data)
310 : {
311 1579 : tree *pair = (tree *) data;
312 1579 : if (*tp == pair[0])
313 : {
314 233 : *tp = unshare_expr (pair[1]);
315 233 : *walk_subtrees = 0;
316 : }
317 1346 : else if (IS_TYPE_OR_DECL_P (*tp))
318 244 : *walk_subtrees = 0;
319 1579 : return NULL_TREE;
320 : }
321 :
322 : /* Return unshare_expr (X) with all occurrences of FROM
323 : replaced with TO. */
324 :
325 : static tree
326 150 : unshare_and_remap (tree x, tree from, tree to)
327 : {
328 150 : tree pair[2] = { from, to };
329 150 : x = unshare_expr (x);
330 150 : walk_tree (&x, unshare_and_remap_1, pair, NULL);
331 150 : return x;
332 : }
333 :
334 : /* Convenience function for calling scan_omp_1_op on tree operands. */
335 :
336 : static inline tree
337 338788 : scan_omp_op (tree *tp, omp_context *ctx)
338 : {
339 338788 : struct walk_stmt_info wi;
340 :
341 338788 : memset (&wi, 0, sizeof (wi));
342 338788 : wi.info = ctx;
343 338788 : wi.want_locations = true;
344 :
345 338788 : return walk_tree (tp, scan_omp_1_op, &wi, NULL);
346 : }
347 :
348 : static void lower_omp (gimple_seq *, omp_context *);
349 : static tree lookup_decl_in_outer_ctx (tree, omp_context *);
350 : static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
351 :
352 : /* Return true if CTX is for an omp parallel. */
353 :
354 : static inline bool
355 774811 : is_parallel_ctx (omp_context *ctx)
356 : {
357 61094 : return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
358 : }
359 :
360 :
361 : /* Return true if CTX is for an omp task. */
362 :
363 : static inline bool
364 236018 : is_task_ctx (omp_context *ctx)
365 : {
366 38770 : return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
367 : }
368 :
369 :
370 : /* Return true if CTX is for an omp taskloop. */
371 :
372 : static inline bool
373 8095 : is_taskloop_ctx (omp_context *ctx)
374 : {
375 8095 : return gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
376 8095 : && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP;
377 : }
378 :
379 :
380 : /* Return true if CTX is for a host omp teams. */
381 :
382 : static inline bool
383 520306 : is_host_teams_ctx (omp_context *ctx)
384 : {
385 520306 : return gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS
386 520306 : && gimple_omp_teams_host (as_a <gomp_teams *> (ctx->stmt));
387 : }
388 :
389 : /* Return true if CTX is for an omp parallel or omp task or host omp teams
390 : (the last one is strictly not a task region in OpenMP speak, but we
391 : need to treat it similarly). */
392 :
393 : static inline bool
394 662359 : is_taskreg_ctx (omp_context *ctx)
395 : {
396 662359 : return is_parallel_ctx (ctx) || is_task_ctx (ctx) || is_host_teams_ctx (ctx);
397 : }
398 :
399 : /* Return true if EXPR is variable sized. If IS_REF is true, then
400 : EXPR is assumed to be a reference and the object it refers
401 : to is checked instead. */
402 :
403 : static inline bool
404 904585 : is_variable_sized (const_tree expr, bool is_ref = false)
405 : {
406 904585 : if (is_ref)
407 2166 : expr = TREE_TYPE (expr);
408 904585 : return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
409 : }
410 :
411 : /* Lookup variables. The "maybe" form
412 : allows for the variable form to not have been entered, otherwise we
413 : assert that the variable must have been entered. */
414 :
415 : static inline tree
416 714764 : lookup_decl (tree var, omp_context *ctx)
417 : {
418 1429429 : tree *n = ctx->cb.decl_map->get (var);
419 714764 : return *n;
420 : }
421 :
422 : static inline tree
423 717285 : maybe_lookup_decl (const_tree var, omp_context *ctx)
424 : {
425 717285 : tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
426 717285 : return n ? *n : NULL_TREE;
427 : }
428 :
429 : static inline tree
430 127113 : lookup_field (tree var, omp_context *ctx)
431 : {
432 127113 : splay_tree_node n;
433 254226 : n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
434 127113 : return (tree) n->value;
435 : }
436 :
437 : static inline tree
438 169225 : lookup_sfield (splay_tree_key key, omp_context *ctx)
439 : {
440 169225 : splay_tree_node n;
441 169225 : n = splay_tree_lookup (ctx->sfield_map
442 : ? ctx->sfield_map : ctx->field_map, key);
443 169225 : return (tree) n->value;
444 : }
445 :
446 : static inline tree
447 967 : lookup_sfield (tree var, omp_context *ctx)
448 : {
449 967 : return lookup_sfield ((splay_tree_key) var, ctx);
450 : }
451 :
452 : static inline tree
453 221384 : maybe_lookup_field (splay_tree_key key, omp_context *ctx)
454 : {
455 221384 : splay_tree_node n;
456 221384 : n = splay_tree_lookup (ctx->field_map, key);
457 221384 : return n ? (tree) n->value : NULL_TREE;
458 : }
459 :
460 : static inline tree
461 221384 : maybe_lookup_field (tree var, omp_context *ctx)
462 : {
463 2555 : return maybe_lookup_field ((splay_tree_key) var, ctx);
464 : }
465 :
466 : /* Return true if DECL should be copied by pointer. SHARED_CTX is
467 : the parallel context if DECL is to be shared. */
468 :
469 : static bool
470 231402 : use_pointer_for_field (tree decl, omp_context *shared_ctx)
471 : {
472 451284 : if (AGGREGATE_TYPE_P (TREE_TYPE (decl))
473 214755 : || TYPE_ATOMIC (TREE_TYPE (decl))
474 446157 : || POLY_INT_CST_P (DECL_SIZE (decl)))
475 : return true;
476 :
477 : /* We can only use copy-in/copy-out semantics for shared variables
478 : when we know the value is not accessible from an outer scope. */
479 214725 : if (shared_ctx)
480 : {
481 28809 : gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
482 :
483 : /* ??? Trivially accessible from anywhere. But why would we even
484 : be passing an address in this case? Should we simply assert
485 : this to be false, or should we have a cleanup pass that removes
486 : these from the list of mappings? */
487 28809 : if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, shared_ctx)))
488 : return true;
489 :
490 : /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
491 : without analyzing the expression whether or not its location
492 : is accessible to anyone else. In the case of nested parallel
493 : regions it certainly may be. */
494 28809 : if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
495 : return true;
496 :
497 : /* Do not use copy-in/copy-out for variables that have their
498 : address taken. */
499 27895 : if (is_global_var (decl))
500 : {
501 : /* For file scope vars, track whether we've seen them as
502 : non-addressable initially and in that case, keep the same
503 : answer for the duration of the pass, even when they are made
504 : addressable later on e.g. through reduction expansion. Global
505 : variables which weren't addressable before the pass will not
506 : have their privatized copies address taken. See PR91216. */
507 1232 : if (!TREE_ADDRESSABLE (decl))
508 : {
509 479 : if (!global_nonaddressable_vars)
510 74 : global_nonaddressable_vars = BITMAP_ALLOC (NULL);
511 479 : bitmap_set_bit (global_nonaddressable_vars, DECL_UID (decl));
512 : }
513 753 : else if (!global_nonaddressable_vars
514 986 : || !bitmap_bit_p (global_nonaddressable_vars,
515 233 : DECL_UID (decl)))
516 731 : return true;
517 : }
518 26663 : else if (TREE_ADDRESSABLE (decl))
519 : return true;
520 :
521 : /* lower_send_shared_vars only uses copy-in, but not copy-out
522 : for these. */
523 18103 : if (TREE_READONLY (decl)
524 18103 : || ((TREE_CODE (decl) == RESULT_DECL
525 11847 : || TREE_CODE (decl) == PARM_DECL)
526 673 : && DECL_BY_REFERENCE (decl)))
527 : return false;
528 :
529 : /* Disallow copy-in/out in nested parallel if
530 : decl is shared in outer parallel, otherwise
531 : each thread could store the shared variable
532 : in its own copy-in location, making the
533 : variable no longer really shared. */
534 11615 : if (shared_ctx->is_nested)
535 : {
536 2470 : omp_context *up;
537 :
538 5975 : for (up = shared_ctx->outer; up; up = up->outer)
539 5702 : if ((is_taskreg_ctx (up)
540 3643 : || (gimple_code (up->stmt) == GIMPLE_OMP_TARGET
541 411 : && is_gimple_omp_offloaded (up->stmt)))
542 6113 : && maybe_lookup_decl (decl, up))
543 : break;
544 :
545 2470 : if (up)
546 : {
547 2197 : tree c;
548 :
549 2197 : if (gimple_code (up->stmt) == GIMPLE_OMP_TARGET)
550 : {
551 309 : for (c = gimple_omp_target_clauses (up->stmt);
552 2031 : c; c = OMP_CLAUSE_CHAIN (c))
553 1932 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
554 1932 : && OMP_CLAUSE_DECL (c) == decl)
555 : break;
556 : }
557 : else
558 1888 : for (c = gimple_omp_taskreg_clauses (up->stmt);
559 6909 : c; c = OMP_CLAUSE_CHAIN (c))
560 6454 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
561 6454 : && OMP_CLAUSE_DECL (c) == decl)
562 : break;
563 :
564 2197 : if (c)
565 1643 : goto maybe_mark_addressable_and_ret;
566 : }
567 : }
568 :
569 : /* For tasks avoid using copy-in/out. As tasks can be
570 : deferred or executed in different thread, when GOMP_task
571 : returns, the task hasn't necessarily terminated. */
572 9972 : if (is_task_ctx (shared_ctx))
573 : {
574 2195 : tree outer;
575 552 : maybe_mark_addressable_and_ret:
576 2195 : outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
577 2195 : if (is_gimple_reg (outer) && !omp_member_access_dummy_var (outer))
578 : {
579 : /* Taking address of OUTER in lower_send_shared_vars
580 : might need regimplification of everything that uses the
581 : variable. */
582 984 : if (!make_addressable_vars)
583 491 : make_addressable_vars = BITMAP_ALLOC (NULL);
584 984 : bitmap_set_bit (make_addressable_vars, DECL_UID (outer));
585 984 : TREE_ADDRESSABLE (outer) = 1;
586 : }
587 2195 : return true;
588 : }
589 : }
590 :
591 : return false;
592 : }
593 :
594 : /* Construct a new automatic decl similar to VAR. */
595 :
596 : static tree
597 229288 : omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
598 : {
599 229288 : tree copy = copy_var_decl (var, name, type);
600 :
601 229288 : DECL_CONTEXT (copy) = current_function_decl;
602 :
603 229288 : if (ctx)
604 : {
605 229007 : DECL_CHAIN (copy) = ctx->block_vars;
606 229007 : ctx->block_vars = copy;
607 : }
608 : else
609 281 : record_vars (copy);
610 :
611 : /* If VAR is listed in make_addressable_vars, it wasn't
612 : originally addressable, but was only later made so.
613 : We don't need to take address of privatizations
614 : from that var. */
615 229288 : if (TREE_ADDRESSABLE (var)
616 229288 : && ((make_addressable_vars
617 3469 : && bitmap_bit_p (make_addressable_vars, DECL_UID (var)))
618 39449 : || (global_nonaddressable_vars
619 515 : && bitmap_bit_p (global_nonaddressable_vars, DECL_UID (var)))))
620 2079 : TREE_ADDRESSABLE (copy) = 0;
621 :
622 229288 : return copy;
623 : }
624 :
625 : static tree
626 229288 : omp_copy_decl_1 (tree var, omp_context *ctx)
627 : {
628 229288 : return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
629 : }
630 :
631 : /* Build tree nodes to access the field for VAR on the receiver side. */
632 :
633 : static tree
634 122655 : build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
635 : {
636 122655 : tree x, field = lookup_field (var, ctx);
637 :
638 : /* If the receiver record type was remapped in the child function,
639 : remap the field into the new record type. */
640 122655 : x = maybe_lookup_field (field, ctx);
641 122655 : if (x != NULL)
642 11167 : field = x;
643 :
644 122655 : x = build_simple_mem_ref (ctx->receiver_decl);
645 122655 : TREE_THIS_NOTRAP (x) = 1;
646 122655 : x = omp_build_component_ref (x, field);
647 122655 : if (by_ref)
648 : {
649 36110 : x = build_simple_mem_ref (x);
650 36110 : TREE_THIS_NOTRAP (x) = 1;
651 : }
652 :
653 122655 : return x;
654 : }
655 :
656 : /* Build tree nodes to access VAR in the scope outer to CTX. In the case
657 : of a parallel, this is a component reference; for workshare constructs
658 : this is some variable. */
659 :
660 : static tree
661 114110 : build_outer_var_ref (tree var, omp_context *ctx,
662 : enum omp_clause_code code = OMP_CLAUSE_ERROR)
663 : {
664 114110 : tree x;
665 114110 : omp_context *outer = ctx->outer;
666 114499 : for (; outer; outer = outer->outer)
667 : {
668 82151 : if (gimple_code (outer->stmt) == GIMPLE_OMP_TASKGROUP)
669 373 : continue;
670 81794 : if (gimple_code (outer->stmt) == GIMPLE_OMP_SCOPE
671 81778 : && !maybe_lookup_decl (var, outer))
672 16 : continue;
673 : break;
674 : }
675 :
676 114110 : if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
677 : x = var;
678 105969 : else if (is_variable_sized (var))
679 : {
680 47 : x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
681 47 : x = build_outer_var_ref (x, ctx, code);
682 47 : x = build_simple_mem_ref (x);
683 : }
684 105922 : else if (is_taskreg_ctx (ctx))
685 : {
686 63671 : bool by_ref = use_pointer_for_field (var, NULL);
687 63671 : x = build_receiver_ref (var, by_ref, ctx);
688 : }
689 42251 : else if ((gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
690 40882 : && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
691 13789 : || ctx->loop_p
692 13016 : || code == OMP_CLAUSE_ALLOCATE
693 55105 : || (code == OMP_CLAUSE_PRIVATE
694 40 : && (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
695 : || gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS
696 : || gimple_code (ctx->stmt) == GIMPLE_OMP_SINGLE)))
697 : {
698 : /* #pragma omp simd isn't a worksharing construct, and can reference
699 : even private vars in its linear etc. clauses.
700 : Similarly for OMP_CLAUSE_PRIVATE with outer ref, that can refer
701 : to private vars in all worksharing constructs. */
702 29417 : x = NULL_TREE;
703 29417 : if (outer && is_taskreg_ctx (outer))
704 912 : x = lookup_decl (var, outer);
705 28505 : else if (outer)
706 22315 : x = maybe_lookup_decl_in_outer_ctx (var, ctx);
707 23227 : if (x == NULL_TREE)
708 : x = var;
709 : }
710 12834 : else if (code == OMP_CLAUSE_LASTPRIVATE && is_taskloop_ctx (ctx))
711 : {
712 689 : gcc_assert (outer);
713 689 : splay_tree_node n
714 1378 : = splay_tree_lookup (outer->field_map,
715 689 : (splay_tree_key) &DECL_UID (var));
716 689 : if (n == NULL)
717 : {
718 610 : if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, outer)))
719 : x = var;
720 : else
721 384 : x = lookup_decl (var, outer);
722 : }
723 : else
724 : {
725 79 : tree field = (tree) n->value;
726 : /* If the receiver record type was remapped in the child function,
727 : remap the field into the new record type. */
728 79 : x = maybe_lookup_field (field, outer);
729 79 : if (x != NULL)
730 0 : field = x;
731 :
732 79 : x = build_simple_mem_ref (outer->receiver_decl);
733 79 : x = omp_build_component_ref (x, field);
734 79 : if (use_pointer_for_field (var, outer))
735 59 : x = build_simple_mem_ref (x);
736 : }
737 : }
738 12145 : else if (outer)
739 11953 : x = lookup_decl (var, outer);
740 192 : else if (omp_privatize_by_reference (var))
741 : /* This can happen with orphaned constructs. If var is reference, it is
742 : possible it is shared and as such valid. */
743 : x = var;
744 94 : else if (omp_member_access_dummy_var (var))
745 : x = var;
746 : else
747 0 : gcc_unreachable ();
748 :
749 114110 : if (x == var)
750 : {
751 16238 : tree t = omp_member_access_dummy_var (var);
752 16238 : if (t)
753 : {
754 220 : x = DECL_VALUE_EXPR (var);
755 220 : tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
756 220 : if (o != t)
757 54 : x = unshare_and_remap (x, t, o);
758 : else
759 166 : x = unshare_expr (x);
760 : }
761 : }
762 :
763 114110 : if (omp_privatize_by_reference (var))
764 3032 : x = build_simple_mem_ref (x);
765 :
766 114110 : return x;
767 : }
768 :
769 : /* Build tree nodes to access the field for VAR on the sender side. */
770 :
771 : static tree
772 168179 : build_sender_ref (splay_tree_key key, omp_context *ctx)
773 : {
774 168179 : tree field = lookup_sfield (key, ctx);
775 168179 : tree tmp = ctx->sender_decl;
776 168179 : if (POINTER_TYPE_P (TREE_TYPE (tmp)))
777 451 : tmp = build_fold_indirect_ref (tmp);
778 168179 : return omp_build_component_ref (tmp, field);
779 : }
780 :
781 : static tree
782 164025 : build_sender_ref (tree var, omp_context *ctx)
783 : {
784 0 : return build_sender_ref ((splay_tree_key) var, ctx);
785 : }
786 :
787 : /* Add a new field for VAR inside the structure CTX. If BY_REF is true,
788 : use a pointer to the VAR rather than VAR itself.
789 : MASK is a bit mask of other options. Bits are interpreted as:
790 : 1: Install VAR in ctx->field_map.
791 : 2: Install VAR in ctx->sfield_map.
792 : 4: VAR is an array, convert it to a pointer.
793 : 8: Use DECL_UID (VAR) instead of VAR as key.
794 : 16: Use DECL_NAME (VAR) instead of VAR as key.
795 : 32: Don't dereference omp_is_reference types.
796 : KEY_EXPR allows specifying something other than VAR as the lookup key.
797 : If specified, it also overrides the 8 and 16 MASK bits. */
798 :
799 : static void
800 131003 : install_var_field (tree var, bool by_ref, int mask, omp_context *ctx,
801 : tree key_expr = NULL_TREE)
802 : {
803 131003 : tree field, type, sfield = NULL_TREE;
804 131003 : splay_tree_key key = (splay_tree_key) var;
805 :
806 131003 : if (key_expr)
807 : /* Allow caller to explicitly set the expression used as the key. */
808 44762 : key = (splay_tree_key) key_expr;
809 : else
810 : {
811 86241 : if ((mask & 16) != 0)
812 : {
813 624 : key = (splay_tree_key) &DECL_NAME (var);
814 624 : gcc_checking_assert (key != (splay_tree_key) var);
815 : }
816 86241 : if ((mask & 8) != 0)
817 : {
818 1619 : key = (splay_tree_key) &DECL_UID (var);
819 1619 : gcc_checking_assert (key != (splay_tree_key) var);
820 : }
821 : }
822 131003 : gcc_assert ((mask & 1) == 0
823 : || !splay_tree_lookup (ctx->field_map, key));
824 131003 : gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
825 : || !splay_tree_lookup (ctx->sfield_map, key));
826 131003 : gcc_assert ((mask & 3) == 3
827 : || !is_gimple_omp_oacc (ctx->stmt));
828 :
829 131003 : type = TREE_TYPE (var);
830 131003 : if ((mask & 16) != 0)
831 624 : type = lang_hooks.decls.omp_array_data (var, true);
832 :
833 : /* Prevent redeclaring the var in the split-off function with a restrict
834 : pointer type. Note that we only clear type itself, restrict qualifiers in
835 : the pointed-to type will be ignored by points-to analysis. */
836 131003 : if (POINTER_TYPE_P (type)
837 131003 : && TYPE_RESTRICT (type))
838 6843 : type = build_qualified_type (type, TYPE_QUALS (type) & ~TYPE_QUAL_RESTRICT);
839 :
840 131003 : if (mask & 4)
841 : {
842 425 : gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
843 425 : type = build_pointer_type (build_pointer_type (type));
844 : }
845 130578 : else if (by_ref)
846 63972 : type = build_pointer_type (type);
847 66606 : else if ((mask & (32 | 3)) == 1
848 66606 : && omp_privatize_by_reference (var))
849 162 : type = TREE_TYPE (type);
850 :
851 131003 : field = build_decl (DECL_SOURCE_LOCATION (var),
852 131003 : FIELD_DECL, DECL_NAME (var), type);
853 :
854 : /* Remember what variable this field was created for. This does have a
855 : side effect of making dwarf2out ignore this member, so for helpful
856 : debugging we clear it later in delete_omp_context. */
857 131003 : DECL_ABSTRACT_ORIGIN (field) = var;
858 131003 : if ((mask & 16) == 0 && type == TREE_TYPE (var))
859 : {
860 62282 : SET_DECL_ALIGN (field, DECL_ALIGN (var));
861 62282 : DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
862 62282 : TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
863 : }
864 : else
865 68721 : SET_DECL_ALIGN (field, TYPE_ALIGN (type));
866 :
867 131003 : if ((mask & 3) == 3)
868 : {
869 129999 : insert_field_into_struct (ctx->record_type, field);
870 129999 : if (ctx->srecord_type)
871 : {
872 644 : sfield = build_decl (DECL_SOURCE_LOCATION (var),
873 644 : FIELD_DECL, DECL_NAME (var), type);
874 644 : DECL_ABSTRACT_ORIGIN (sfield) = var;
875 644 : SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
876 644 : DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
877 644 : TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
878 644 : insert_field_into_struct (ctx->srecord_type, sfield);
879 : }
880 : }
881 : else
882 : {
883 1004 : if (ctx->srecord_type == NULL_TREE)
884 : {
885 520 : tree t;
886 :
887 520 : ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
888 520 : ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
889 2003 : for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
890 : {
891 1483 : sfield = build_decl (DECL_SOURCE_LOCATION (t),
892 1483 : FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
893 1483 : DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
894 1483 : insert_field_into_struct (ctx->srecord_type, sfield);
895 2966 : splay_tree_insert (ctx->sfield_map,
896 1483 : (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
897 : (splay_tree_value) sfield);
898 : }
899 : }
900 1004 : sfield = field;
901 1004 : insert_field_into_struct ((mask & 1) ? ctx->record_type
902 : : ctx->srecord_type, field);
903 : }
904 :
905 131003 : if (mask & 1)
906 130640 : splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
907 131003 : if ((mask & 2) && ctx->sfield_map)
908 1007 : splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
909 131003 : }
910 :
911 : static tree
912 228857 : install_var_local (tree var, omp_context *ctx)
913 : {
914 228857 : tree new_var = omp_copy_decl_1 (var, ctx);
915 228857 : insert_decl_map (&ctx->cb, var, new_var);
916 228857 : return new_var;
917 : }
918 :
919 : /* Adjust the replacement for DECL in CTX for the new context. This means
920 : copying the DECL_VALUE_EXPR, and fixing up the type. */
921 :
922 : static void
923 204045 : fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
924 : {
925 204045 : tree new_decl, size;
926 :
927 204045 : new_decl = lookup_decl (decl, ctx);
928 :
929 204045 : TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
930 :
931 406957 : if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
932 204234 : && DECL_HAS_VALUE_EXPR_P (decl))
933 : {
934 1322 : tree ve = DECL_VALUE_EXPR (decl);
935 1322 : walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
936 1322 : SET_DECL_VALUE_EXPR (new_decl, ve);
937 1322 : DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
938 : }
939 :
940 204045 : if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
941 : {
942 1133 : size = remap_decl (DECL_SIZE (decl), &ctx->cb);
943 1133 : if (size == error_mark_node)
944 316 : size = TYPE_SIZE (TREE_TYPE (new_decl));
945 1133 : DECL_SIZE (new_decl) = size;
946 :
947 1133 : size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
948 1133 : if (size == error_mark_node)
949 303 : size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
950 1133 : DECL_SIZE_UNIT (new_decl) = size;
951 : }
952 204045 : }
953 :
954 : /* The callback for remap_decl. Search all containing contexts for a
955 : mapping of the variable; this avoids having to duplicate the splay
956 : tree ahead of time. We know a mapping doesn't already exist in the
957 : given context. Create new mappings to implement default semantics. */
958 :
959 : static tree
960 462528 : omp_copy_decl (tree var, copy_body_data *cb)
961 : {
962 462528 : omp_context *ctx = (omp_context *) cb;
963 462528 : tree new_var;
964 :
965 462528 : if (TREE_CODE (var) == LABEL_DECL)
966 : {
967 187875 : if (FORCED_LABEL (var) || DECL_NONLOCAL (var))
968 : return var;
969 187869 : new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
970 187869 : DECL_CONTEXT (new_var) = current_function_decl;
971 187869 : insert_decl_map (&ctx->cb, var, new_var);
972 187869 : return new_var;
973 : }
974 :
975 356477 : while (!is_taskreg_ctx (ctx))
976 : {
977 337291 : ctx = ctx->outer;
978 337291 : if (ctx == NULL)
979 : return var;
980 279023 : new_var = maybe_lookup_decl (var, ctx);
981 279023 : if (new_var)
982 : return new_var;
983 : }
984 :
985 19186 : if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
986 13365 : return var;
987 :
988 5821 : return error_mark_node;
989 : }
990 :
991 : /* Create a new context, with OUTER_CTX being the surrounding context. */
992 :
993 : static omp_context *
994 137599 : new_omp_context (gimple *stmt, omp_context *outer_ctx)
995 : {
996 137599 : omp_context *ctx = XCNEW (omp_context);
997 :
998 137599 : splay_tree_insert (all_contexts, (splay_tree_key) stmt,
999 : (splay_tree_value) ctx);
1000 137599 : ctx->stmt = stmt;
1001 :
1002 137599 : if (outer_ctx)
1003 : {
1004 74386 : ctx->outer = outer_ctx;
1005 74386 : ctx->cb = outer_ctx->cb;
1006 74386 : ctx->cb.block = NULL;
1007 74386 : ctx->depth = outer_ctx->depth + 1;
1008 : }
1009 : else
1010 : {
1011 63213 : ctx->cb.src_fn = current_function_decl;
1012 63213 : ctx->cb.dst_fn = current_function_decl;
1013 63213 : ctx->cb.src_node = cgraph_node::get (current_function_decl);
1014 63213 : gcc_checking_assert (ctx->cb.src_node);
1015 63213 : ctx->cb.dst_node = ctx->cb.src_node;
1016 63213 : ctx->cb.src_cfun = cfun;
1017 63213 : ctx->cb.copy_decl = omp_copy_decl;
1018 63213 : ctx->cb.eh_lp_nr = 0;
1019 63213 : ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1020 63213 : ctx->cb.adjust_array_error_bounds = true;
1021 63213 : ctx->cb.dont_remap_vla_if_no_change = true;
1022 63213 : ctx->depth = 1;
1023 : }
1024 :
1025 137599 : ctx->cb.decl_map = new hash_map<tree, tree>;
1026 :
1027 137599 : return ctx;
1028 : }
1029 :
1030 : static gimple_seq maybe_catch_exception (gimple_seq);
1031 :
1032 : /* Finalize task copyfn. */
1033 :
1034 : static void
1035 480 : finalize_task_copyfn (gomp_task *task_stmt)
1036 : {
1037 480 : struct function *child_cfun;
1038 480 : tree child_fn;
1039 480 : gimple_seq seq = NULL, new_seq;
1040 480 : gbind *bind;
1041 :
1042 480 : child_fn = gimple_omp_task_copy_fn (task_stmt);
1043 480 : if (child_fn == NULL_TREE)
1044 0 : return;
1045 :
1046 480 : child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1047 480 : DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1048 :
1049 480 : push_cfun (child_cfun);
1050 480 : bind = gimplify_body (child_fn, false);
1051 480 : gimple_seq_add_stmt (&seq, bind);
1052 480 : new_seq = maybe_catch_exception (seq);
1053 480 : if (new_seq != seq)
1054 : {
1055 332 : bind = gimple_build_bind (NULL, new_seq, NULL);
1056 332 : seq = NULL;
1057 332 : gimple_seq_add_stmt (&seq, bind);
1058 : }
1059 480 : gimple_set_body (child_fn, seq);
1060 480 : pop_cfun ();
1061 :
1062 : /* Inform the callgraph about the new function. */
1063 480 : cgraph_node *node = cgraph_node::get_create (child_fn);
1064 480 : node->parallelized_function = 1;
1065 480 : cgraph_node::add_new_function (child_fn, false);
1066 : }
1067 :
1068 : /* Destroy a omp_context data structures. Called through the splay tree
1069 : value delete callback. */
1070 :
1071 : static void
1072 137593 : delete_omp_context (splay_tree_value value)
1073 : {
1074 137593 : omp_context *ctx = (omp_context *) value;
1075 :
1076 275186 : delete ctx->cb.decl_map;
1077 :
1078 137593 : if (ctx->field_map)
1079 69065 : splay_tree_delete (ctx->field_map);
1080 137593 : if (ctx->sfield_map)
1081 520 : splay_tree_delete (ctx->sfield_map);
1082 :
1083 : /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1084 : it produces corrupt debug information. */
1085 137593 : if (ctx->record_type)
1086 : {
1087 53353 : tree t;
1088 222194 : for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1089 168841 : DECL_ABSTRACT_ORIGIN (t) = NULL;
1090 : }
1091 137593 : if (ctx->srecord_type)
1092 : {
1093 520 : tree t;
1094 3010 : for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1095 2490 : DECL_ABSTRACT_ORIGIN (t) = NULL;
1096 : }
1097 :
1098 137593 : if (ctx->task_reduction_map)
1099 : {
1100 1165 : ctx->task_reductions.release ();
1101 2330 : delete ctx->task_reduction_map;
1102 : }
1103 :
1104 137860 : delete ctx->lastprivate_conditional_map;
1105 138891 : delete ctx->allocate_map;
1106 :
1107 137593 : XDELETE (ctx);
1108 137593 : }
1109 :
1110 : /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1111 : context. */
1112 :
1113 : static void
1114 36742 : fixup_child_record_type (omp_context *ctx)
1115 : {
1116 36742 : tree f, type = ctx->record_type;
1117 :
1118 36742 : if (!ctx->receiver_decl)
1119 : return;
1120 : /* ??? It isn't sufficient to just call remap_type here, because
1121 : variably_modified_type_p doesn't work the way we expect for
1122 : record types. Testing each field for whether it needs remapping
1123 : and creating a new record by hand works, however. */
1124 161362 : for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1125 125889 : if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1126 : break;
1127 36742 : if (f)
1128 : {
1129 1269 : tree name, new_fields = NULL;
1130 :
1131 1269 : type = lang_hooks.types.make_type (RECORD_TYPE);
1132 1269 : name = DECL_NAME (TYPE_NAME (ctx->record_type));
1133 1269 : name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1134 : TYPE_DECL, name, type);
1135 1269 : TYPE_NAME (type) = name;
1136 :
1137 13448 : for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1138 : {
1139 12179 : tree new_f = copy_node (f);
1140 12179 : DECL_CONTEXT (new_f) = type;
1141 12179 : TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1142 12179 : DECL_CHAIN (new_f) = new_fields;
1143 12179 : walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1144 12179 : walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1145 : &ctx->cb, NULL);
1146 12179 : walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1147 : &ctx->cb, NULL);
1148 12179 : new_fields = new_f;
1149 :
1150 : /* Arrange to be able to look up the receiver field
1151 : given the sender field. */
1152 12179 : splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1153 : (splay_tree_value) new_f);
1154 : }
1155 1269 : TYPE_FIELDS (type) = nreverse (new_fields);
1156 1269 : layout_type (type);
1157 : }
1158 :
1159 : /* In a target region we never modify any of the pointers in *.omp_data_i,
1160 : so attempt to help the optimizers. */
1161 36742 : if (is_gimple_omp_offloaded (ctx->stmt))
1162 17601 : type = build_qualified_type (type, TYPE_QUAL_CONST);
1163 :
1164 36742 : TREE_TYPE (ctx->receiver_decl)
1165 110226 : = build_qualified_type (flexible_array_type_p (type)
1166 107 : ? build_pointer_type (type)
1167 36635 : : build_reference_type (type), TYPE_QUAL_RESTRICT);
1168 : }
1169 :
1170 : /* Instantiate decls as necessary in CTX to satisfy the data sharing
1171 : specified by CLAUSES. */
1172 :
1173 : static void
1174 129746 : scan_sharing_clauses (tree clauses, omp_context *ctx)
1175 : {
1176 129746 : tree c, decl;
1177 129746 : bool scan_array_reductions = false;
1178 129746 : bool flex_array_ptr = false;
1179 :
1180 549406 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1181 419660 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
1182 419660 : && (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) == NULL_TREE
1183 : /* omp_default_mem_alloc is 1 */
1184 1137 : || !integer_onep (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
1185 572 : || OMP_CLAUSE_ALLOCATE_ALIGN (c) != NULL_TREE))
1186 : {
1187 : /* The allocate clauses that appear on a target construct or on
1188 : constructs in a target region must specify an allocator expression
1189 : unless a requires directive with the dynamic_allocators clause
1190 : is present in the same compilation unit. */
1191 1629 : if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) == NULL_TREE
1192 1020 : && ((omp_requires_mask & OMP_REQUIRES_DYNAMIC_ALLOCATORS) == 0)
1193 2637 : && omp_maybe_offloaded_ctx (ctx))
1194 10 : error_at (OMP_CLAUSE_LOCATION (c), "%<allocate%> clause must"
1195 : " specify an allocator here");
1196 1629 : if ((omp_requires_mask & OMP_REQUIRES_DYNAMIC_ALLOCATORS) == 0
1197 1617 : && OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) != NULL_TREE
1198 609 : && DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
1199 1978 : && !DECL_ARTIFICIAL (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)))
1200 : {
1201 275 : tree alloc2 = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
1202 275 : if (TREE_CODE (alloc2) == MEM_REF
1203 275 : || TREE_CODE (alloc2) == INDIRECT_REF)
1204 0 : alloc2 = TREE_OPERAND (alloc2, 0);
1205 275 : omp_context *ctx2 = ctx;
1206 736 : for (; ctx2; ctx2 = ctx2->outer)
1207 476 : if (is_gimple_omp_offloaded (ctx2->stmt))
1208 : break;
1209 275 : if (ctx2 != NULL)
1210 : {
1211 15 : tree c2 = gimple_omp_target_clauses (ctx2->stmt);
1212 80 : for (; c2; c2 = OMP_CLAUSE_CHAIN (c2))
1213 78 : if (OMP_CLAUSE_CODE (c2) == OMP_CLAUSE_USES_ALLOCATORS
1214 91 : && operand_equal_p (
1215 13 : alloc2, OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR (c2)))
1216 : break;
1217 15 : if (c2 == NULL_TREE)
1218 4 : error_at (EXPR_LOC_OR_LOC (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
1219 : OMP_CLAUSE_LOCATION (c)),
1220 : "allocator %qE in %<allocate%> clause inside a "
1221 : "target region must be specified in an "
1222 : "%<uses_allocators%> clause on the %<target%> "
1223 : "directive", alloc2);
1224 : }
1225 : }
1226 1629 : if (ctx->allocate_map == NULL)
1227 1298 : ctx->allocate_map = new hash_map<tree, tree>;
1228 1629 : tree val = integer_zero_node;
1229 1629 : if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
1230 609 : val = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
1231 1629 : if (OMP_CLAUSE_ALLOCATE_ALIGN (c))
1232 295 : val = build_tree_list (val, OMP_CLAUSE_ALLOCATE_ALIGN (c));
1233 1629 : ctx->allocate_map->put (OMP_CLAUSE_DECL (c), val);
1234 : }
1235 :
1236 549406 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1237 : {
1238 419660 : bool by_ref;
1239 :
1240 419660 : switch (OMP_CLAUSE_CODE (c))
1241 : {
1242 73105 : case OMP_CLAUSE_PRIVATE:
1243 73105 : decl = OMP_CLAUSE_DECL (c);
1244 73105 : if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1245 165 : goto do_private;
1246 72940 : else if (!is_variable_sized (decl))
1247 72577 : install_var_local (decl, ctx);
1248 : break;
1249 :
1250 46549 : case OMP_CLAUSE_SHARED:
1251 46549 : decl = OMP_CLAUSE_DECL (c);
1252 46549 : if (ctx->allocate_map && ctx->allocate_map->get (decl))
1253 37 : ctx->allocate_map->remove (decl);
1254 : /* Ignore shared directives in teams construct inside of
1255 : target construct. */
1256 46549 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS
1257 46549 : && !is_host_teams_ctx (ctx))
1258 : {
1259 : /* Global variables don't need to be copied,
1260 : the receiver side will use them directly. */
1261 11856 : tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1262 11856 : if (is_global_var (odecl))
1263 : break;
1264 8127 : insert_decl_map (&ctx->cb, decl, odecl);
1265 8127 : break;
1266 : }
1267 34693 : gcc_assert (is_taskreg_ctx (ctx));
1268 34693 : gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1269 : || !is_variable_sized (decl));
1270 : /* Global variables don't need to be copied,
1271 : the receiver side will use them directly. */
1272 34693 : if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1273 : break;
1274 28628 : if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
1275 : {
1276 86 : use_pointer_for_field (decl, ctx);
1277 86 : break;
1278 : }
1279 28542 : by_ref = use_pointer_for_field (decl, NULL);
1280 54728 : if ((! TREE_READONLY (decl) && !OMP_CLAUSE_SHARED_READONLY (c))
1281 19150 : || TREE_ADDRESSABLE (decl)
1282 18793 : || by_ref
1283 47335 : || omp_privatize_by_reference (decl))
1284 : {
1285 11751 : by_ref = use_pointer_for_field (decl, ctx);
1286 11751 : install_var_field (decl, by_ref, 3, ctx);
1287 11751 : install_var_local (decl, ctx);
1288 11751 : break;
1289 : }
1290 : /* We don't need to copy const scalar vars back. */
1291 16791 : OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1292 16791 : goto do_private;
1293 :
1294 14529 : case OMP_CLAUSE_REDUCTION:
1295 : /* Collect 'reduction' clauses on OpenACC compute construct. */
1296 14529 : if (is_gimple_omp_oacc (ctx->stmt)
1297 14529 : && is_gimple_omp_offloaded (ctx->stmt))
1298 : {
1299 : /* No 'reduction' clauses on OpenACC 'kernels'. */
1300 790 : gcc_checking_assert (!is_oacc_kernels (ctx));
1301 : /* Likewise, on OpenACC 'kernels' decomposed parts. */
1302 790 : gcc_checking_assert (!is_oacc_kernels_decomposed_part (ctx));
1303 :
1304 790 : ctx->local_reduction_clauses
1305 790 : = tree_cons (NULL, c, ctx->local_reduction_clauses);
1306 : }
1307 : /* FALLTHRU */
1308 :
1309 16603 : case OMP_CLAUSE_IN_REDUCTION:
1310 16603 : decl = OMP_CLAUSE_DECL (c);
1311 16603 : if (ctx->allocate_map
1312 16603 : && ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1313 365 : && (OMP_CLAUSE_REDUCTION_INSCAN (c)
1314 365 : || OMP_CLAUSE_REDUCTION_TASK (c)))
1315 373 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
1316 365 : || is_task_ctx (ctx)))
1317 : {
1318 : /* For now. */
1319 17 : if (ctx->allocate_map->get (decl))
1320 17 : ctx->allocate_map->remove (decl);
1321 : }
1322 16603 : if (TREE_CODE (decl) == MEM_REF)
1323 : {
1324 2366 : tree t = TREE_OPERAND (decl, 0);
1325 2366 : if (TREE_CODE (t) == POINTER_PLUS_EXPR)
1326 436 : t = TREE_OPERAND (t, 0);
1327 2366 : if (INDIRECT_REF_P (t)
1328 2272 : || TREE_CODE (t) == ADDR_EXPR)
1329 1378 : t = TREE_OPERAND (t, 0);
1330 2366 : if (is_omp_target (ctx->stmt))
1331 : {
1332 96 : if (is_variable_sized (t))
1333 : {
1334 32 : gcc_assert (DECL_HAS_VALUE_EXPR_P (t));
1335 32 : t = DECL_VALUE_EXPR (t);
1336 32 : gcc_assert (INDIRECT_REF_P (t));
1337 32 : t = TREE_OPERAND (t, 0);
1338 32 : gcc_assert (DECL_P (t));
1339 : }
1340 96 : tree at = t;
1341 96 : if (ctx->outer)
1342 96 : scan_omp_op (&at, ctx->outer);
1343 96 : tree nt = omp_copy_decl_1 (at, ctx->outer);
1344 192 : splay_tree_insert (ctx->field_map,
1345 96 : (splay_tree_key) &DECL_CONTEXT (t),
1346 : (splay_tree_value) nt);
1347 96 : if (at != t)
1348 96 : splay_tree_insert (ctx->field_map,
1349 48 : (splay_tree_key) &DECL_CONTEXT (at),
1350 : (splay_tree_value) nt);
1351 96 : break;
1352 : }
1353 2270 : install_var_local (t, ctx);
1354 2270 : if (is_taskreg_ctx (ctx)
1355 1822 : && (!is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
1356 387 : || (is_task_ctx (ctx)
1357 310 : && (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE
1358 234 : || (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE
1359 0 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (t)))
1360 : == POINTER_TYPE)))))
1361 1511 : && !is_variable_sized (t)
1362 3722 : && (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
1363 617 : || (!OMP_CLAUSE_REDUCTION_TASK (c)
1364 578 : && !is_task_ctx (ctx))))
1365 : {
1366 1335 : by_ref = use_pointer_for_field (t, NULL);
1367 1335 : if (is_task_ctx (ctx)
1368 835 : && TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE
1369 1495 : && TREE_CODE (TREE_TYPE (TREE_TYPE (t))) == POINTER_TYPE)
1370 : {
1371 32 : install_var_field (t, false, 1, ctx);
1372 32 : install_var_field (t, by_ref, 2, ctx);
1373 : }
1374 : else
1375 1303 : install_var_field (t, by_ref, 3, ctx);
1376 : }
1377 : break;
1378 : }
1379 14237 : if (is_omp_target (ctx->stmt))
1380 : {
1381 335 : tree at = decl;
1382 335 : if (ctx->outer)
1383 54 : scan_omp_op (&at, ctx->outer);
1384 335 : tree nt = omp_copy_decl_1 (at, ctx->outer);
1385 670 : splay_tree_insert (ctx->field_map,
1386 335 : (splay_tree_key) &DECL_CONTEXT (decl),
1387 : (splay_tree_value) nt);
1388 335 : if (at != decl)
1389 24 : splay_tree_insert (ctx->field_map,
1390 12 : (splay_tree_key) &DECL_CONTEXT (at),
1391 : (splay_tree_value) nt);
1392 335 : break;
1393 : }
1394 13902 : if (is_task_ctx (ctx)
1395 26734 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1396 12832 : && OMP_CLAUSE_REDUCTION_TASK (c)
1397 373 : && is_parallel_ctx (ctx)))
1398 : {
1399 : /* Global variables don't need to be copied,
1400 : the receiver side will use them directly. */
1401 1150 : if (!is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1402 : {
1403 462 : by_ref = use_pointer_for_field (decl, ctx);
1404 462 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)
1405 304 : install_var_field (decl, by_ref, 3, ctx);
1406 : }
1407 1150 : install_var_local (decl, ctx);
1408 1150 : break;
1409 : }
1410 12752 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1411 12752 : && OMP_CLAUSE_REDUCTION_TASK (c))
1412 : {
1413 293 : install_var_local (decl, ctx);
1414 293 : break;
1415 : }
1416 12459 : goto do_private;
1417 :
1418 22664 : case OMP_CLAUSE_LASTPRIVATE:
1419 : /* Let the corresponding firstprivate clause create
1420 : the variable. */
1421 22664 : if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1422 : break;
1423 : /* FALLTHRU */
1424 :
1425 59206 : case OMP_CLAUSE_FIRSTPRIVATE:
1426 59206 : case OMP_CLAUSE_LINEAR:
1427 59206 : decl = OMP_CLAUSE_DECL (c);
1428 89009 : do_private:
1429 89009 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1430 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR
1431 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
1432 45711 : && is_gimple_omp_offloaded (ctx->stmt))
1433 : {
1434 16255 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1435 16255 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR
1436 239 : && lang_hooks.decls.omp_array_data (decl, true)))
1437 : {
1438 : /* OpenACC firstprivate clauses are later processed with same
1439 : code path as map clauses in lower_omp_target, so follow
1440 : the same convention of using the whole clause expression
1441 : as splay-tree key. */
1442 15886 : tree k = (is_oacc_parallel_or_serial (ctx) ? c : NULL_TREE);
1443 15886 : by_ref = !omp_privatize_by_reference (decl);
1444 15886 : install_var_field (decl, by_ref, 3, ctx, k);
1445 : }
1446 369 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
1447 : {
1448 220 : if (INDIRECT_REF_P (decl))
1449 0 : decl = TREE_OPERAND (decl, 0);
1450 220 : install_var_field (decl, true, 3, ctx);
1451 : }
1452 149 : else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1453 8 : install_var_field (decl, true, 3, ctx);
1454 : else
1455 141 : install_var_field (decl, false, 3, ctx);
1456 : }
1457 89009 : if (is_variable_sized (decl))
1458 : {
1459 60 : if (is_task_ctx (ctx))
1460 : {
1461 14 : if (ctx->allocate_map
1462 14 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1463 : {
1464 : /* For now. */
1465 0 : if (ctx->allocate_map->get (decl))
1466 0 : ctx->allocate_map->remove (decl);
1467 : }
1468 14 : install_var_field (decl, false, 1, ctx);
1469 : }
1470 : break;
1471 : }
1472 88949 : else if (is_taskreg_ctx (ctx))
1473 : {
1474 38284 : bool global
1475 38284 : = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1476 38284 : by_ref = use_pointer_for_field (decl, NULL);
1477 :
1478 38284 : if (is_task_ctx (ctx)
1479 38284 : && (global || by_ref || omp_privatize_by_reference (decl)))
1480 : {
1481 595 : if (ctx->allocate_map
1482 595 : && ctx->allocate_map->get (decl))
1483 35 : install_var_field (decl, by_ref, 32 | 1, ctx);
1484 : else
1485 560 : install_var_field (decl, false, 1, ctx);
1486 595 : if (!global)
1487 331 : install_var_field (decl, by_ref, 2, ctx);
1488 : }
1489 37689 : else if (!global)
1490 36420 : install_var_field (decl, by_ref, 3, ctx);
1491 : }
1492 88949 : install_var_local (decl, ctx);
1493 : /* For descr arrays on target: firstprivatize data + attach ptr. */
1494 88949 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1495 45276 : && is_gimple_omp_offloaded (ctx->stmt)
1496 15861 : && !is_gimple_omp_oacc (ctx->stmt)
1497 11613 : && lang_hooks.decls.omp_array_data (decl, true)
1498 88980 : && lang_hooks.decls.omp_array_data_privatize (decl))
1499 : {
1500 23 : install_var_field (decl, false, 16 | 3, ctx);
1501 23 : install_var_field (decl, true, 8 | 3, ctx);
1502 : }
1503 : break;
1504 :
1505 2118 : case OMP_CLAUSE_USE_DEVICE_PTR:
1506 2118 : case OMP_CLAUSE_USE_DEVICE_ADDR:
1507 2118 : decl = OMP_CLAUSE_DECL (c);
1508 :
1509 : /* Fortran array descriptors. */
1510 2118 : if (lang_hooks.decls.omp_array_data (decl, true))
1511 601 : install_var_field (decl, false, 19, ctx);
1512 1517 : else if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_ADDR
1513 1312 : && !omp_privatize_by_reference (decl)
1514 513 : && !omp_is_allocatable_or_ptr (decl))
1515 2454 : || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1516 407 : install_var_field (decl, true, 11, ctx);
1517 : else
1518 1110 : install_var_field (decl, false, 11, ctx);
1519 2118 : if (DECL_SIZE (decl)
1520 2118 : && !poly_int_tree_p (DECL_SIZE (decl)))
1521 : {
1522 6 : tree decl2 = DECL_VALUE_EXPR (decl);
1523 6 : gcc_assert (INDIRECT_REF_P (decl2));
1524 6 : decl2 = TREE_OPERAND (decl2, 0);
1525 6 : gcc_assert (DECL_P (decl2));
1526 6 : install_var_local (decl2, ctx);
1527 : }
1528 2118 : install_var_local (decl, ctx);
1529 2118 : break;
1530 :
1531 239 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
1532 239 : decl = OMP_CLAUSE_DECL (c);
1533 239 : while (INDIRECT_REF_P (decl)
1534 256 : || TREE_CODE (decl) == ARRAY_REF)
1535 17 : decl = TREE_OPERAND (decl, 0);
1536 239 : goto do_private;
1537 :
1538 149 : case OMP_CLAUSE_IS_DEVICE_PTR:
1539 149 : decl = OMP_CLAUSE_DECL (c);
1540 149 : goto do_private;
1541 :
1542 20111 : case OMP_CLAUSE__LOOPTEMP_:
1543 20111 : case OMP_CLAUSE__REDUCTEMP_:
1544 20111 : gcc_assert (is_taskreg_ctx (ctx));
1545 20111 : decl = OMP_CLAUSE_DECL (c);
1546 20111 : install_var_field (decl, false, 3, ctx);
1547 20111 : install_var_local (decl, ctx);
1548 20111 : break;
1549 :
1550 896 : case OMP_CLAUSE_COPYPRIVATE:
1551 896 : case OMP_CLAUSE_COPYIN:
1552 896 : decl = OMP_CLAUSE_DECL (c);
1553 896 : by_ref = use_pointer_for_field (decl, NULL);
1554 896 : install_var_field (decl, by_ref, 3, ctx);
1555 896 : break;
1556 :
1557 55236 : case OMP_CLAUSE_FINAL:
1558 55236 : case OMP_CLAUSE_IF:
1559 55236 : case OMP_CLAUSE_SELF:
1560 55236 : case OMP_CLAUSE_NUM_THREADS:
1561 55236 : case OMP_CLAUSE_NUM_TEAMS:
1562 55236 : case OMP_CLAUSE_THREAD_LIMIT:
1563 55236 : case OMP_CLAUSE_DEVICE:
1564 55236 : case OMP_CLAUSE_SCHEDULE:
1565 55236 : case OMP_CLAUSE_DIST_SCHEDULE:
1566 55236 : case OMP_CLAUSE_DEPEND:
1567 55236 : case OMP_CLAUSE_PRIORITY:
1568 55236 : case OMP_CLAUSE_GRAINSIZE:
1569 55236 : case OMP_CLAUSE_NUM_TASKS:
1570 55236 : case OMP_CLAUSE_NUM_GANGS:
1571 55236 : case OMP_CLAUSE_NUM_WORKERS:
1572 55236 : case OMP_CLAUSE_VECTOR_LENGTH:
1573 55236 : case OMP_CLAUSE_DETACH:
1574 55236 : case OMP_CLAUSE_FILTER:
1575 55236 : if (ctx->outer)
1576 17573 : scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1577 : break;
1578 :
1579 88329 : case OMP_CLAUSE_TO:
1580 88329 : case OMP_CLAUSE_FROM:
1581 88329 : case OMP_CLAUSE_MAP:
1582 88329 : if (ctx->outer)
1583 15385 : scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1584 88329 : decl = OMP_CLAUSE_DECL (c);
1585 : /* If requested, make 'decl' addressable. */
1586 88329 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1587 88329 : && OMP_CLAUSE_MAP_DECL_MAKE_ADDRESSABLE (c))
1588 : {
1589 433 : gcc_checking_assert (DECL_P (decl));
1590 :
1591 433 : bool decl_addressable = TREE_ADDRESSABLE (decl);
1592 433 : if (!decl_addressable)
1593 : {
1594 219 : if (!make_addressable_vars)
1595 131 : make_addressable_vars = BITMAP_ALLOC (NULL);
1596 219 : bitmap_set_bit (make_addressable_vars, DECL_UID (decl));
1597 219 : TREE_ADDRESSABLE (decl) = 1;
1598 : }
1599 :
1600 433 : if (dump_enabled_p ())
1601 : {
1602 421 : location_t loc = OMP_CLAUSE_LOCATION (c);
1603 421 : const dump_user_location_t d_u_loc
1604 421 : = dump_user_location_t::from_location_t (loc);
1605 : /* PR100695 "Format decoder, quoting in 'dump_printf' etc." */
1606 : #if __GNUC__ >= 10
1607 421 : # pragma GCC diagnostic push
1608 421 : # pragma GCC diagnostic ignored "-Wformat"
1609 : #endif
1610 421 : if (!decl_addressable)
1611 207 : dump_printf_loc (MSG_NOTE, d_u_loc,
1612 : "variable %<%T%>"
1613 : " made addressable\n",
1614 : decl);
1615 : else
1616 214 : dump_printf_loc (MSG_NOTE, d_u_loc,
1617 : "variable %<%T%>"
1618 : " already made addressable\n",
1619 : decl);
1620 : #if __GNUC__ >= 10
1621 421 : # pragma GCC diagnostic pop
1622 : #endif
1623 : }
1624 :
1625 : /* Done. */
1626 433 : OMP_CLAUSE_MAP_DECL_MAKE_ADDRESSABLE (c) = 0;
1627 : }
1628 : /* Global variables with "omp declare target" attribute
1629 : don't need to be copied, the receiver side will use them
1630 : directly. However, global variables with "omp declare target link"
1631 : attribute need to be copied. Or when ALWAYS modifier is used. */
1632 88329 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1633 80544 : && DECL_P (decl)
1634 44359 : && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
1635 40542 : && (OMP_CLAUSE_MAP_KIND (c)
1636 : != GOMP_MAP_FIRSTPRIVATE_REFERENCE)
1637 40113 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH
1638 39879 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_DETACH)
1639 4545 : || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1640 41017 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_TO
1641 40882 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_FROM
1642 40853 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_TOFROM
1643 40365 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_PRESENT_TO
1644 40335 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_PRESENT_FROM
1645 40313 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_PRESENT_TOFROM
1646 40299 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_TO_PSET
1647 36308 : && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1648 7560 : && varpool_node::get_create (decl)->offloadable
1649 93595 : && !lookup_attribute ("omp declare target link",
1650 5266 : DECL_ATTRIBUTES (decl)))
1651 : break;
1652 83091 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1653 83091 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
1654 : {
1655 : /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1656 : not offloaded; there is nothing to map for those. */
1657 10489 : if (!is_gimple_omp_offloaded (ctx->stmt)
1658 4978 : && !POINTER_TYPE_P (TREE_TYPE (decl))
1659 10753 : && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
1660 : break;
1661 : }
1662 82827 : if (!flex_array_ptr)
1663 82599 : flex_array_ptr = lang_hooks.decls.omp_deep_mapping_p (ctx->stmt, c);
1664 82827 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1665 75042 : && DECL_P (decl)
1666 38857 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
1667 38623 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
1668 83126 : && is_omp_target (ctx->stmt))
1669 : {
1670 : /* If this is an offloaded region, an attach operation should
1671 : only exist when the pointer variable is mapped in a prior
1672 : clause. An exception is if we have a reference (to pointer):
1673 : in that case we should have mapped "*decl" in a previous
1674 : mapping instead of "decl". Skip the assertion in that case.
1675 : If we had an error, we may not have attempted to sort clauses
1676 : properly, so avoid the test. */
1677 261 : if (TREE_CODE (TREE_TYPE (decl)) != REFERENCE_TYPE
1678 229 : && is_gimple_omp_offloaded (ctx->stmt)
1679 331 : && !seen_error ())
1680 62 : gcc_assert
1681 : (maybe_lookup_decl (decl, ctx)
1682 : || (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1683 : && lookup_attribute ("omp declare target",
1684 : DECL_ATTRIBUTES (decl))));
1685 :
1686 : /* By itself, attach/detach is generated as part of pointer
1687 : variable mapping and should not create new variables in the
1688 : offloaded region, however sender refs for it must be created
1689 : for its address to be passed to the runtime. */
1690 261 : tree field
1691 261 : = build_decl (OMP_CLAUSE_LOCATION (c),
1692 : FIELD_DECL, NULL_TREE, ptr_type_node);
1693 261 : SET_DECL_ALIGN (field, TYPE_ALIGN (ptr_type_node));
1694 261 : insert_field_into_struct (ctx->record_type, field);
1695 : /* To not clash with a map of the pointer variable itself,
1696 : attach/detach maps have their field looked up by the *clause*
1697 : tree expression, not the decl. */
1698 261 : gcc_assert (!splay_tree_lookup (ctx->field_map,
1699 : (splay_tree_key) c));
1700 261 : splay_tree_insert (ctx->field_map, (splay_tree_key) c,
1701 : (splay_tree_value) field);
1702 261 : break;
1703 : }
1704 82566 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1705 82566 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
1706 70966 : || (OMP_CLAUSE_MAP_KIND (c)
1707 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
1708 : {
1709 4244 : if (TREE_CODE (decl) == COMPONENT_REF
1710 4244 : || (INDIRECT_REF_P (decl)
1711 0 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
1712 0 : && (((TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
1713 : == REFERENCE_TYPE)
1714 0 : || (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
1715 : == POINTER_TYPE)))))
1716 : break;
1717 4244 : if (DECL_SIZE (decl)
1718 4244 : && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1719 : {
1720 710 : tree decl2 = DECL_VALUE_EXPR (decl);
1721 710 : gcc_assert (INDIRECT_REF_P (decl2));
1722 710 : decl2 = TREE_OPERAND (decl2, 0);
1723 710 : gcc_assert (DECL_P (decl2));
1724 710 : install_var_local (decl2, ctx);
1725 : }
1726 4244 : install_var_local (decl, ctx);
1727 4244 : break;
1728 : }
1729 78322 : if (DECL_P (decl))
1730 : {
1731 40514 : if (DECL_SIZE (decl)
1732 40514 : && !poly_int_tree_p (DECL_SIZE (decl)))
1733 : {
1734 0 : tree decl2 = DECL_VALUE_EXPR (decl);
1735 0 : gcc_assert (INDIRECT_REF_P (decl2));
1736 0 : decl2 = TREE_OPERAND (decl2, 0);
1737 0 : gcc_assert (DECL_P (decl2));
1738 0 : install_var_field (decl2, true, 3, ctx, c);
1739 0 : install_var_local (decl2, ctx);
1740 0 : install_var_local (decl, ctx);
1741 : }
1742 : else
1743 : {
1744 40514 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1745 34352 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1746 5204 : && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1747 45718 : && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1748 425 : install_var_field (decl, true, 7, ctx, c);
1749 : else
1750 40089 : install_var_field (decl, true, 3, ctx, c);
1751 40514 : if (is_gimple_omp_offloaded (ctx->stmt)
1752 40514 : && !(is_gimple_omp_oacc (ctx->stmt)
1753 13857 : && OMP_CLAUSE_MAP_IN_REDUCTION (c)))
1754 23830 : install_var_local (decl, ctx);
1755 : }
1756 : }
1757 : else
1758 : {
1759 37808 : tree base = get_base_address (decl);
1760 37808 : tree nc = OMP_CLAUSE_CHAIN (c);
1761 37808 : if (DECL_P (base)
1762 9267 : && nc != NULL_TREE
1763 6677 : && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1764 5515 : && OMP_CLAUSE_DECL (nc) == base
1765 1184 : && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
1766 38476 : && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1767 : {
1768 0 : OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1769 0 : OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1770 : }
1771 : else
1772 : {
1773 37808 : if (ctx->outer)
1774 : {
1775 7152 : scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1776 7152 : decl = OMP_CLAUSE_DECL (c);
1777 : }
1778 37808 : gcc_assert (!splay_tree_lookup (ctx->field_map,
1779 : (splay_tree_key) decl));
1780 37808 : tree field
1781 37808 : = build_decl (OMP_CLAUSE_LOCATION (c),
1782 : FIELD_DECL, NULL_TREE, ptr_type_node);
1783 37808 : SET_DECL_ALIGN (field, TYPE_ALIGN (ptr_type_node));
1784 37808 : insert_field_into_struct (ctx->record_type, field);
1785 37808 : splay_tree_insert (ctx->field_map, (splay_tree_key) c,
1786 : (splay_tree_value) field);
1787 : }
1788 : }
1789 : break;
1790 :
1791 3973 : case OMP_CLAUSE_ORDER:
1792 3973 : ctx->order_concurrent = true;
1793 3973 : break;
1794 :
1795 1907 : case OMP_CLAUSE_BIND:
1796 1907 : ctx->loop_p = true;
1797 1907 : break;
1798 :
1799 : case OMP_CLAUSE_NOWAIT:
1800 : case OMP_CLAUSE_ORDERED:
1801 : case OMP_CLAUSE_COLLAPSE:
1802 : case OMP_CLAUSE_UNTIED:
1803 : case OMP_CLAUSE_MERGEABLE:
1804 : case OMP_CLAUSE_PROC_BIND:
1805 : case OMP_CLAUSE_SAFELEN:
1806 : case OMP_CLAUSE_SIMDLEN:
1807 : case OMP_CLAUSE_THREADS:
1808 : case OMP_CLAUSE_SIMD:
1809 : case OMP_CLAUSE_NOGROUP:
1810 : case OMP_CLAUSE_DEFAULTMAP:
1811 : case OMP_CLAUSE_ASYNC:
1812 : case OMP_CLAUSE_WAIT:
1813 : case OMP_CLAUSE_GANG:
1814 : case OMP_CLAUSE_WORKER:
1815 : case OMP_CLAUSE_VECTOR:
1816 : case OMP_CLAUSE_INDEPENDENT:
1817 : case OMP_CLAUSE_AUTO:
1818 : case OMP_CLAUSE_SEQ:
1819 : case OMP_CLAUSE_TILE:
1820 : case OMP_CLAUSE__SIMT_:
1821 : case OMP_CLAUSE_DEFAULT:
1822 : case OMP_CLAUSE_NONTEMPORAL:
1823 : case OMP_CLAUSE_IF_PRESENT:
1824 : case OMP_CLAUSE_FINALIZE:
1825 : case OMP_CLAUSE_TASK_REDUCTION:
1826 : case OMP_CLAUSE_ALLOCATE:
1827 : case OMP_CLAUSE_DEVICE_TYPE:
1828 : break;
1829 :
1830 90 : case OMP_CLAUSE_USES_ALLOCATORS:
1831 90 : decl = OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR (c);
1832 90 : gcc_assert (DECL_P (decl));
1833 90 : gcc_assert (is_gimple_omp_offloaded (ctx->stmt));
1834 90 : install_var_field (decl, false, 3, ctx);
1835 90 : install_var_local (decl, ctx);
1836 90 : break;
1837 :
1838 162 : case OMP_CLAUSE_ALIGNED:
1839 162 : decl = OMP_CLAUSE_DECL (c);
1840 162 : if (is_global_var (decl)
1841 162 : && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1842 86 : install_var_local (decl, ctx);
1843 : break;
1844 :
1845 349 : case OMP_CLAUSE__CONDTEMP_:
1846 349 : decl = OMP_CLAUSE_DECL (c);
1847 349 : if (is_parallel_ctx (ctx))
1848 : {
1849 112 : install_var_field (decl, false, 3, ctx);
1850 112 : install_var_local (decl, ctx);
1851 : }
1852 237 : else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1853 237 : && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD
1854 362 : && !OMP_CLAUSE__CONDTEMP__ITER (c))
1855 125 : install_var_local (decl, ctx);
1856 : break;
1857 :
1858 : case OMP_CLAUSE_INIT:
1859 : case OMP_CLAUSE_USE:
1860 : case OMP_CLAUSE_DESTROY:
1861 : break;
1862 :
1863 0 : case OMP_CLAUSE__CACHE_:
1864 0 : case OMP_CLAUSE_NOHOST:
1865 0 : default:
1866 0 : gcc_unreachable ();
1867 : }
1868 : }
1869 :
1870 549406 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1871 : {
1872 419660 : switch (OMP_CLAUSE_CODE (c))
1873 : {
1874 22664 : case OMP_CLAUSE_LASTPRIVATE:
1875 : /* Let the corresponding firstprivate clause create
1876 : the variable. */
1877 22664 : if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1878 7203 : scan_array_reductions = true;
1879 22664 : if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1880 : break;
1881 : /* FALLTHRU */
1882 :
1883 149490 : case OMP_CLAUSE_FIRSTPRIVATE:
1884 149490 : case OMP_CLAUSE_PRIVATE:
1885 149490 : case OMP_CLAUSE_LINEAR:
1886 149490 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
1887 149490 : case OMP_CLAUSE_IS_DEVICE_PTR:
1888 149490 : decl = OMP_CLAUSE_DECL (c);
1889 149490 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
1890 : {
1891 256 : while (INDIRECT_REF_P (decl)
1892 256 : || TREE_CODE (decl) == ARRAY_REF)
1893 17 : decl = TREE_OPERAND (decl, 0);
1894 : }
1895 :
1896 149490 : if (is_variable_sized (decl))
1897 : {
1898 423 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1899 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR
1900 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
1901 53 : && is_gimple_omp_offloaded (ctx->stmt))
1902 : {
1903 12 : tree decl2 = DECL_VALUE_EXPR (decl);
1904 12 : gcc_assert (INDIRECT_REF_P (decl2));
1905 12 : decl2 = TREE_OPERAND (decl2, 0);
1906 12 : gcc_assert (DECL_P (decl2));
1907 12 : install_var_local (decl2, ctx);
1908 12 : fixup_remapped_decl (decl2, ctx, false);
1909 : }
1910 423 : install_var_local (decl, ctx);
1911 : }
1912 298980 : fixup_remapped_decl (decl, ctx,
1913 149490 : OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1914 149490 : && OMP_CLAUSE_PRIVATE_DEBUG (c));
1915 149490 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1916 149490 : && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1917 : scan_array_reductions = true;
1918 : break;
1919 :
1920 16603 : case OMP_CLAUSE_REDUCTION:
1921 16603 : case OMP_CLAUSE_IN_REDUCTION:
1922 16603 : decl = OMP_CLAUSE_DECL (c);
1923 16603 : if (TREE_CODE (decl) != MEM_REF && !is_omp_target (ctx->stmt))
1924 : {
1925 13902 : if (is_variable_sized (decl))
1926 0 : install_var_local (decl, ctx);
1927 13902 : fixup_remapped_decl (decl, ctx, false);
1928 : }
1929 16603 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1930 2834 : scan_array_reductions = true;
1931 : break;
1932 :
1933 530 : case OMP_CLAUSE_TASK_REDUCTION:
1934 530 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1935 2834 : scan_array_reductions = true;
1936 : break;
1937 :
1938 29758 : case OMP_CLAUSE_SHARED:
1939 : /* Ignore shared directives in teams construct inside of
1940 : target construct. */
1941 29758 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS
1942 29758 : && !is_host_teams_ctx (ctx))
1943 : break;
1944 17902 : decl = OMP_CLAUSE_DECL (c);
1945 17902 : if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1946 : break;
1947 11837 : if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
1948 : {
1949 86 : if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
1950 : ctx->outer)))
1951 : break;
1952 79 : bool by_ref = use_pointer_for_field (decl, ctx);
1953 79 : install_var_field (decl, by_ref, 11, ctx);
1954 79 : break;
1955 : }
1956 11751 : fixup_remapped_decl (decl, ctx, false);
1957 11751 : break;
1958 :
1959 80544 : case OMP_CLAUSE_MAP:
1960 80544 : if (!is_gimple_omp_offloaded (ctx->stmt))
1961 : break;
1962 53805 : decl = OMP_CLAUSE_DECL (c);
1963 53805 : if (DECL_P (decl)
1964 33886 : && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
1965 30237 : && (OMP_CLAUSE_MAP_KIND (c)
1966 : != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
1967 4078 : || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1968 31011 : && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1969 61188 : && varpool_node::get_create (decl)->offloadable)
1970 : break;
1971 48123 : if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
1972 45911 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
1973 2212 : && is_omp_target (ctx->stmt)
1974 50126 : && !is_gimple_omp_offloaded (ctx->stmt))
1975 : break;
1976 48123 : if (DECL_P (decl))
1977 : {
1978 28204 : if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1979 25151 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
1980 6700 : && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1981 29829 : && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1982 : {
1983 24 : tree new_decl = lookup_decl (decl, ctx);
1984 24 : TREE_TYPE (new_decl)
1985 48 : = remap_type (TREE_TYPE (decl), &ctx->cb);
1986 : }
1987 28180 : else if (DECL_SIZE (decl)
1988 28180 : && !poly_int_tree_p (DECL_SIZE (decl)))
1989 : {
1990 710 : tree decl2 = DECL_VALUE_EXPR (decl);
1991 710 : gcc_assert (INDIRECT_REF_P (decl2));
1992 710 : decl2 = TREE_OPERAND (decl2, 0);
1993 710 : gcc_assert (DECL_P (decl2));
1994 710 : fixup_remapped_decl (decl2, ctx, false);
1995 710 : fixup_remapped_decl (decl, ctx, true);
1996 : }
1997 : else
1998 27470 : fixup_remapped_decl (decl, ctx, false);
1999 : }
2000 : break;
2001 :
2002 : case OMP_CLAUSE_COPYPRIVATE:
2003 : case OMP_CLAUSE_COPYIN:
2004 : case OMP_CLAUSE_DEFAULT:
2005 : case OMP_CLAUSE_IF:
2006 : case OMP_CLAUSE_SELF:
2007 : case OMP_CLAUSE_NUM_THREADS:
2008 : case OMP_CLAUSE_NUM_TEAMS:
2009 : case OMP_CLAUSE_THREAD_LIMIT:
2010 : case OMP_CLAUSE_DEVICE:
2011 : case OMP_CLAUSE_SCHEDULE:
2012 : case OMP_CLAUSE_DIST_SCHEDULE:
2013 : case OMP_CLAUSE_NOWAIT:
2014 : case OMP_CLAUSE_ORDERED:
2015 : case OMP_CLAUSE_COLLAPSE:
2016 : case OMP_CLAUSE_UNTIED:
2017 : case OMP_CLAUSE_FINAL:
2018 : case OMP_CLAUSE_MERGEABLE:
2019 : case OMP_CLAUSE_PROC_BIND:
2020 : case OMP_CLAUSE_SAFELEN:
2021 : case OMP_CLAUSE_SIMDLEN:
2022 : case OMP_CLAUSE_ALIGNED:
2023 : case OMP_CLAUSE_DEPEND:
2024 : case OMP_CLAUSE_DETACH:
2025 : case OMP_CLAUSE_ALLOCATE:
2026 : case OMP_CLAUSE__LOOPTEMP_:
2027 : case OMP_CLAUSE__REDUCTEMP_:
2028 : case OMP_CLAUSE_TO:
2029 : case OMP_CLAUSE_FROM:
2030 : case OMP_CLAUSE_PRIORITY:
2031 : case OMP_CLAUSE_GRAINSIZE:
2032 : case OMP_CLAUSE_NUM_TASKS:
2033 : case OMP_CLAUSE_THREADS:
2034 : case OMP_CLAUSE_SIMD:
2035 : case OMP_CLAUSE_NOGROUP:
2036 : case OMP_CLAUSE_DEFAULTMAP:
2037 : case OMP_CLAUSE_ORDER:
2038 : case OMP_CLAUSE_BIND:
2039 : case OMP_CLAUSE_USE_DEVICE_PTR:
2040 : case OMP_CLAUSE_USE_DEVICE_ADDR:
2041 : case OMP_CLAUSE_NONTEMPORAL:
2042 : case OMP_CLAUSE_ASYNC:
2043 : case OMP_CLAUSE_WAIT:
2044 : case OMP_CLAUSE_NUM_GANGS:
2045 : case OMP_CLAUSE_NUM_WORKERS:
2046 : case OMP_CLAUSE_VECTOR_LENGTH:
2047 : case OMP_CLAUSE_GANG:
2048 : case OMP_CLAUSE_WORKER:
2049 : case OMP_CLAUSE_VECTOR:
2050 : case OMP_CLAUSE_INDEPENDENT:
2051 : case OMP_CLAUSE_AUTO:
2052 : case OMP_CLAUSE_SEQ:
2053 : case OMP_CLAUSE_TILE:
2054 : case OMP_CLAUSE__SIMT_:
2055 : case OMP_CLAUSE_IF_PRESENT:
2056 : case OMP_CLAUSE_FINALIZE:
2057 : case OMP_CLAUSE_FILTER:
2058 : case OMP_CLAUSE__CONDTEMP_:
2059 : case OMP_CLAUSE_INIT:
2060 : case OMP_CLAUSE_USE:
2061 : case OMP_CLAUSE_DESTROY:
2062 : case OMP_CLAUSE_DEVICE_TYPE:
2063 : case OMP_CLAUSE_USES_ALLOCATORS:
2064 : break;
2065 :
2066 0 : case OMP_CLAUSE__CACHE_:
2067 0 : case OMP_CLAUSE_NOHOST:
2068 0 : default:
2069 0 : gcc_unreachable ();
2070 : }
2071 : }
2072 :
2073 129746 : gcc_checking_assert (!scan_array_reductions
2074 : || !is_gimple_omp_oacc (ctx->stmt));
2075 : if (scan_array_reductions)
2076 : {
2077 34354 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2078 29182 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2079 26806 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
2080 26182 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
2081 29886 : && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2082 : {
2083 2178 : omp_context *rctx = ctx;
2084 2178 : if (is_omp_target (ctx->stmt))
2085 60 : rctx = ctx->outer;
2086 2178 : scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), rctx);
2087 2178 : scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), rctx);
2088 : }
2089 27004 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2090 27004 : && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2091 7203 : scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2092 19801 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2093 19801 : && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2094 656 : scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2095 : }
2096 129746 : if (flex_array_ptr)
2097 : {
2098 144 : tree field = build_range_type (size_type_node,
2099 : build_int_cstu (size_type_node, 0),
2100 : NULL_TREE);
2101 144 : field = build_array_type (ptr_type_node, field);
2102 144 : field = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, field);
2103 144 : SET_DECL_ALIGN (field, TYPE_ALIGN (ptr_type_node));
2104 144 : DECL_CONTEXT (field) = ctx->record_type;
2105 144 : DECL_CHAIN (field) = TYPE_FIELDS (ctx->record_type);
2106 144 : TYPE_FIELDS (ctx->record_type) = field;
2107 : }
2108 129746 : }
2109 :
2110 : /* Create a new name for omp child function. Returns an identifier. */
2111 :
2112 : static tree
2113 51326 : create_omp_child_function_name (bool task_copy)
2114 : {
2115 102132 : return clone_function_name_numbered (current_function_decl,
2116 51326 : task_copy ? "_omp_cpyfn" : "_omp_fn");
2117 : }
2118 :
2119 : /* Return true if CTX may belong to offloaded code: either if current function
2120 : is offloaded, or any enclosing context corresponds to a target region. */
2121 :
2122 : static bool
2123 122793 : omp_maybe_offloaded_ctx (omp_context *ctx)
2124 : {
2125 122793 : if (cgraph_node::get (current_function_decl)->offloadable)
2126 : return true;
2127 203000 : for (; ctx; ctx = ctx->outer)
2128 119951 : if (is_gimple_omp_offloaded (ctx->stmt))
2129 : return true;
2130 : return false;
2131 : }
2132 :
2133 : /* Build a decl for the omp child function. It'll not contain a body
2134 : yet, just the bare decl. */
2135 :
2136 : static void
2137 51326 : create_omp_child_function (omp_context *ctx, bool task_copy)
2138 : {
2139 51326 : tree decl, type, name, t;
2140 :
2141 51326 : name = create_omp_child_function_name (task_copy);
2142 51326 : if (task_copy)
2143 520 : type = build_function_type_list (void_type_node, ptr_type_node,
2144 : ptr_type_node, NULL_TREE);
2145 : else
2146 50806 : type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2147 :
2148 51326 : decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2149 :
2150 51326 : gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2151 : || !task_copy);
2152 39940 : if (!task_copy)
2153 50806 : ctx->cb.dst_fn = decl;
2154 : else
2155 520 : gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2156 :
2157 51326 : TREE_STATIC (decl) = 1;
2158 51326 : TREE_USED (decl) = 1;
2159 51326 : DECL_ARTIFICIAL (decl) = 1;
2160 51326 : DECL_IGNORED_P (decl) = 0;
2161 51326 : TREE_PUBLIC (decl) = 0;
2162 51326 : DECL_UNINLINABLE (decl) = 1;
2163 51326 : DECL_EXTERNAL (decl) = 0;
2164 51326 : DECL_CONTEXT (decl) = NULL_TREE;
2165 51326 : DECL_INITIAL (decl) = make_node (BLOCK);
2166 51326 : BLOCK_SUPERCONTEXT (DECL_INITIAL (decl)) = decl;
2167 51326 : DECL_ATTRIBUTES (decl) = DECL_ATTRIBUTES (current_function_decl);
2168 : /* Remove omp declare simd attribute from the new attributes. */
2169 51326 : if (tree a = lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (decl)))
2170 : {
2171 9 : while (tree a2 = lookup_attribute ("omp declare simd", TREE_CHAIN (a)))
2172 : a = a2;
2173 9 : a = TREE_CHAIN (a);
2174 22 : for (tree *p = &DECL_ATTRIBUTES (decl); *p != a;)
2175 13 : if (is_attribute_p ("omp declare simd", get_attribute_name (*p)))
2176 9 : *p = TREE_CHAIN (*p);
2177 : else
2178 : {
2179 4 : tree chain = TREE_CHAIN (*p);
2180 4 : *p = copy_node (*p);
2181 4 : p = &TREE_CHAIN (*p);
2182 4 : *p = chain;
2183 : }
2184 : }
2185 102652 : DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl)
2186 51326 : = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (current_function_decl);
2187 102652 : DECL_FUNCTION_SPECIFIC_TARGET (decl)
2188 51326 : = DECL_FUNCTION_SPECIFIC_TARGET (current_function_decl);
2189 102652 : DECL_FUNCTION_VERSIONED (decl)
2190 51326 : = DECL_FUNCTION_VERSIONED (current_function_decl);
2191 :
2192 51326 : if (omp_maybe_offloaded_ctx (ctx))
2193 : {
2194 31015 : cgraph_node::get_create (decl)->offloadable = 1;
2195 31015 : if (ENABLE_OFFLOADING)
2196 : g->have_offload = true;
2197 : }
2198 :
2199 51326 : if (cgraph_node::get_create (decl)->offloadable)
2200 : {
2201 31015 : const char *target_attr = (is_gimple_omp_offloaded (ctx->stmt)
2202 31015 : ? "omp target entrypoint"
2203 6208 : : "omp declare target");
2204 31015 : if (lookup_attribute ("omp declare target",
2205 31015 : DECL_ATTRIBUTES (current_function_decl)))
2206 : {
2207 3032 : if (is_gimple_omp_offloaded (ctx->stmt))
2208 1620 : DECL_ATTRIBUTES (decl)
2209 1620 : = remove_attribute ("omp declare target",
2210 1620 : copy_list (DECL_ATTRIBUTES (decl)));
2211 : else
2212 : target_attr = NULL;
2213 : }
2214 1620 : if (target_attr
2215 29603 : && is_gimple_omp_offloaded (ctx->stmt)
2216 24807 : && lookup_attribute ("noclone", DECL_ATTRIBUTES (decl)) == NULL_TREE)
2217 19300 : DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("noclone"),
2218 19300 : NULL_TREE, DECL_ATTRIBUTES (decl));
2219 31015 : if (target_attr)
2220 29603 : DECL_ATTRIBUTES (decl)
2221 59206 : = tree_cons (get_identifier (target_attr),
2222 29603 : NULL_TREE, DECL_ATTRIBUTES (decl));
2223 : }
2224 :
2225 51326 : t = build_decl (DECL_SOURCE_LOCATION (decl),
2226 : RESULT_DECL, NULL_TREE, void_type_node);
2227 51326 : DECL_ARTIFICIAL (t) = 1;
2228 51326 : DECL_IGNORED_P (t) = 1;
2229 51326 : DECL_CONTEXT (t) = decl;
2230 51326 : DECL_RESULT (decl) = t;
2231 :
2232 51326 : tree data_name = get_identifier (".omp_data_i");
2233 51326 : t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2234 : ptr_type_node);
2235 51326 : DECL_ARTIFICIAL (t) = 1;
2236 51326 : DECL_NAMELESS (t) = 1;
2237 51326 : DECL_ARG_TYPE (t) = ptr_type_node;
2238 51326 : DECL_CONTEXT (t) = current_function_decl;
2239 51326 : TREE_USED (t) = 1;
2240 51326 : TREE_READONLY (t) = 1;
2241 51326 : DECL_ARGUMENTS (decl) = t;
2242 51326 : if (!task_copy)
2243 50806 : ctx->receiver_decl = t;
2244 : else
2245 : {
2246 520 : t = build_decl (DECL_SOURCE_LOCATION (decl),
2247 : PARM_DECL, get_identifier (".omp_data_o"),
2248 : ptr_type_node);
2249 520 : DECL_ARTIFICIAL (t) = 1;
2250 520 : DECL_NAMELESS (t) = 1;
2251 520 : DECL_ARG_TYPE (t) = ptr_type_node;
2252 520 : DECL_CONTEXT (t) = current_function_decl;
2253 520 : TREE_USED (t) = 1;
2254 520 : TREE_ADDRESSABLE (t) = 1;
2255 520 : DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2256 520 : DECL_ARGUMENTS (decl) = t;
2257 : }
2258 :
2259 : /* Allocate memory for the function structure. The call to
2260 : allocate_struct_function clobbers CFUN, so we need to restore
2261 : it afterward. */
2262 51326 : push_struct_function (decl);
2263 51326 : cfun->function_end_locus = gimple_location (ctx->stmt);
2264 51326 : init_tree_ssa (cfun);
2265 51326 : pop_cfun ();
2266 51326 : }
2267 :
2268 : /* Callback for walk_gimple_seq. Check if combined parallel
2269 : contains gimple_omp_for_combined_into_p OMP_FOR. */
2270 :
2271 : tree
2272 35647 : omp_find_combined_for (gimple_stmt_iterator *gsi_p,
2273 : bool *handled_ops_p,
2274 : struct walk_stmt_info *wi)
2275 : {
2276 35647 : gimple *stmt = gsi_stmt (*gsi_p);
2277 :
2278 35647 : *handled_ops_p = true;
2279 35647 : switch (gimple_code (stmt))
2280 : {
2281 19972 : WALK_SUBSTMTS;
2282 :
2283 13502 : case GIMPLE_OMP_FOR:
2284 13502 : if (gimple_omp_for_combined_into_p (stmt)
2285 13502 : && gimple_omp_for_kind (stmt)
2286 7960 : == *(const enum gf_mask *) (wi->info))
2287 : {
2288 7960 : wi->info = stmt;
2289 7960 : return integer_zero_node;
2290 : }
2291 : break;
2292 : default:
2293 : break;
2294 : }
2295 : return NULL;
2296 : }
2297 :
2298 : /* Add _LOOPTEMP_/_REDUCTEMP_ clauses on OpenMP parallel or task. */
2299 :
2300 : static void
2301 14087 : add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2302 : omp_context *outer_ctx)
2303 : {
2304 14087 : struct walk_stmt_info wi;
2305 :
2306 14087 : memset (&wi, 0, sizeof (wi));
2307 14087 : wi.val_only = true;
2308 14087 : wi.info = (void *) &msk;
2309 14087 : walk_gimple_seq (gimple_omp_body (stmt), omp_find_combined_for, NULL, &wi);
2310 14087 : if (wi.info != (void *) &msk)
2311 : {
2312 7960 : gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2313 7960 : struct omp_for_data fd;
2314 7960 : omp_extract_for_data (for_stmt, &fd, NULL);
2315 : /* We need two temporaries with fd.loop.v type (istart/iend)
2316 : and then (fd.collapse - 1) temporaries with the same
2317 : type for count2 ... countN-1 vars if not constant. */
2318 7960 : size_t count = 2, i;
2319 7960 : tree type = fd.iter_type;
2320 7960 : if (fd.collapse > 1
2321 2648 : && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2322 : {
2323 1466 : count += fd.collapse - 1;
2324 : /* If there are lastprivate clauses on the inner
2325 : GIMPLE_OMP_FOR, add one more temporaries for the total number
2326 : of iterations (product of count1 ... countN-1). */
2327 1466 : if (omp_find_clause (gimple_omp_for_clauses (for_stmt),
2328 : OMP_CLAUSE_LASTPRIVATE)
2329 1466 : || (msk == GF_OMP_FOR_KIND_FOR
2330 1335 : && omp_find_clause (gimple_omp_parallel_clauses (stmt),
2331 : OMP_CLAUSE_LASTPRIVATE)))
2332 : {
2333 726 : tree temp = create_tmp_var (type);
2334 726 : tree c = build_omp_clause (UNKNOWN_LOCATION,
2335 : OMP_CLAUSE__LOOPTEMP_);
2336 726 : insert_decl_map (&outer_ctx->cb, temp, temp);
2337 726 : OMP_CLAUSE_DECL (c) = temp;
2338 726 : OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2339 726 : gimple_omp_taskreg_set_clauses (stmt, c);
2340 : }
2341 1466 : if (fd.non_rect
2342 24 : && fd.last_nonrect == fd.first_nonrect + 1)
2343 12 : if (tree v = gimple_omp_for_index (for_stmt, fd.last_nonrect))
2344 12 : if (!TYPE_UNSIGNED (TREE_TYPE (v)))
2345 : {
2346 12 : v = gimple_omp_for_index (for_stmt, fd.first_nonrect);
2347 12 : tree type2 = TREE_TYPE (v);
2348 12 : count++;
2349 48 : for (i = 0; i < 3; i++)
2350 : {
2351 36 : tree temp = create_tmp_var (type2);
2352 36 : tree c = build_omp_clause (UNKNOWN_LOCATION,
2353 : OMP_CLAUSE__LOOPTEMP_);
2354 36 : insert_decl_map (&outer_ctx->cb, temp, temp);
2355 36 : OMP_CLAUSE_DECL (c) = temp;
2356 36 : OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2357 36 : gimple_omp_taskreg_set_clauses (stmt, c);
2358 : }
2359 : }
2360 : }
2361 26725 : for (i = 0; i < count; i++)
2362 : {
2363 18765 : tree temp = create_tmp_var (type);
2364 18765 : tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2365 18765 : insert_decl_map (&outer_ctx->cb, temp, temp);
2366 18765 : OMP_CLAUSE_DECL (c) = temp;
2367 18765 : OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2368 18765 : gimple_omp_taskreg_set_clauses (stmt, c);
2369 : }
2370 : }
2371 14087 : if (msk == GF_OMP_FOR_KIND_TASKLOOP
2372 15654 : && omp_find_clause (gimple_omp_task_clauses (stmt),
2373 : OMP_CLAUSE_REDUCTION))
2374 : {
2375 517 : tree type = build_pointer_type (pointer_sized_int_node);
2376 517 : tree temp = create_tmp_var (type);
2377 517 : tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__REDUCTEMP_);
2378 517 : insert_decl_map (&outer_ctx->cb, temp, temp);
2379 517 : OMP_CLAUSE_DECL (c) = temp;
2380 517 : OMP_CLAUSE_CHAIN (c) = gimple_omp_task_clauses (stmt);
2381 517 : gimple_omp_task_set_clauses (stmt, c);
2382 : }
2383 14087 : }
2384 :
2385 : /* Scan an OpenMP parallel directive. */
2386 :
2387 : static void
2388 18168 : scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2389 : {
2390 18168 : omp_context *ctx;
2391 18168 : tree name;
2392 18168 : gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2393 :
2394 : /* Ignore parallel directives with empty bodies, unless there
2395 : are copyin clauses. */
2396 18168 : if (optimize > 0
2397 12465 : && empty_body_p (gimple_omp_body (stmt))
2398 18215 : && omp_find_clause (gimple_omp_parallel_clauses (stmt),
2399 : OMP_CLAUSE_COPYIN) == NULL)
2400 : {
2401 41 : gsi_replace (gsi, gimple_build_nop (), false);
2402 41 : return;
2403 : }
2404 :
2405 18127 : if (gimple_omp_parallel_combined_p (stmt))
2406 12520 : add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
2407 18127 : for (tree c = omp_find_clause (gimple_omp_parallel_clauses (stmt),
2408 : OMP_CLAUSE_REDUCTION);
2409 20954 : c; c = omp_find_clause (OMP_CLAUSE_CHAIN (c), OMP_CLAUSE_REDUCTION))
2410 3914 : if (OMP_CLAUSE_REDUCTION_TASK (c))
2411 : {
2412 67 : tree type = build_pointer_type (pointer_sized_int_node);
2413 67 : tree temp = create_tmp_var (type);
2414 67 : tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__REDUCTEMP_);
2415 67 : if (outer_ctx)
2416 18 : insert_decl_map (&outer_ctx->cb, temp, temp);
2417 67 : OMP_CLAUSE_DECL (c) = temp;
2418 67 : OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2419 67 : gimple_omp_parallel_set_clauses (stmt, c);
2420 67 : break;
2421 : }
2422 3847 : else if (OMP_CLAUSE_CHAIN (c) == NULL_TREE)
2423 : break;
2424 :
2425 18127 : ctx = new_omp_context (stmt, outer_ctx);
2426 18127 : taskreg_contexts.safe_push (ctx);
2427 18127 : if (taskreg_nesting_level > 1)
2428 6193 : ctx->is_nested = true;
2429 18127 : ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2430 18127 : ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2431 18127 : name = create_tmp_var_name (".omp_data_s");
2432 18127 : name = build_decl (gimple_location (stmt),
2433 : TYPE_DECL, name, ctx->record_type);
2434 18127 : DECL_ARTIFICIAL (name) = 1;
2435 18127 : DECL_NAMELESS (name) = 1;
2436 18127 : TYPE_NAME (ctx->record_type) = name;
2437 18127 : TYPE_ARTIFICIAL (ctx->record_type) = 1;
2438 18127 : create_omp_child_function (ctx, false);
2439 18127 : gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2440 :
2441 18127 : scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2442 18127 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
2443 :
2444 18127 : if (TYPE_FIELDS (ctx->record_type) == NULL)
2445 3575 : ctx->record_type = ctx->receiver_decl = NULL;
2446 : }
2447 :
2448 : /* Scan an OpenMP task directive. */
2449 :
2450 : static void
2451 5344 : scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2452 : {
2453 5344 : omp_context *ctx;
2454 5344 : tree name, t;
2455 5344 : gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2456 :
2457 : /* Ignore task directives with empty bodies, unless they have depend
2458 : clause. */
2459 5344 : if (optimize > 0
2460 2527 : && gimple_omp_body (stmt)
2461 2484 : && empty_body_p (gimple_omp_body (stmt))
2462 5398 : && !omp_find_clause (gimple_omp_task_clauses (stmt), OMP_CLAUSE_DEPEND))
2463 : {
2464 19 : gsi_replace (gsi, gimple_build_nop (), false);
2465 131 : return;
2466 : }
2467 :
2468 5325 : if (gimple_omp_task_taskloop_p (stmt))
2469 1567 : add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2470 :
2471 5325 : ctx = new_omp_context (stmt, outer_ctx);
2472 :
2473 5325 : if (gimple_omp_task_taskwait_p (stmt))
2474 : {
2475 93 : scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2476 93 : return;
2477 : }
2478 :
2479 5232 : taskreg_contexts.safe_push (ctx);
2480 5232 : if (taskreg_nesting_level > 1)
2481 2296 : ctx->is_nested = true;
2482 5232 : ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2483 5232 : ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2484 5232 : name = create_tmp_var_name (".omp_data_s");
2485 5232 : name = build_decl (gimple_location (stmt),
2486 : TYPE_DECL, name, ctx->record_type);
2487 5232 : DECL_ARTIFICIAL (name) = 1;
2488 5232 : DECL_NAMELESS (name) = 1;
2489 5232 : TYPE_NAME (ctx->record_type) = name;
2490 5232 : TYPE_ARTIFICIAL (ctx->record_type) = 1;
2491 5232 : create_omp_child_function (ctx, false);
2492 5232 : gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2493 :
2494 5232 : scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2495 :
2496 5232 : if (ctx->srecord_type)
2497 : {
2498 520 : name = create_tmp_var_name (".omp_data_a");
2499 520 : name = build_decl (gimple_location (stmt),
2500 : TYPE_DECL, name, ctx->srecord_type);
2501 520 : DECL_ARTIFICIAL (name) = 1;
2502 520 : DECL_NAMELESS (name) = 1;
2503 520 : TYPE_NAME (ctx->srecord_type) = name;
2504 520 : TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2505 520 : create_omp_child_function (ctx, true);
2506 : }
2507 :
2508 5232 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
2509 :
2510 5232 : if (TYPE_FIELDS (ctx->record_type) == NULL)
2511 : {
2512 1837 : ctx->record_type = ctx->receiver_decl = NULL;
2513 1837 : t = build_int_cst (long_integer_type_node, 0);
2514 1837 : gimple_omp_task_set_arg_size (stmt, t);
2515 1837 : t = build_int_cst (long_integer_type_node, 1);
2516 1837 : gimple_omp_task_set_arg_align (stmt, t);
2517 : }
2518 : }
2519 :
2520 : /* Helper function for finish_taskreg_scan, called through walk_tree.
2521 : If maybe_lookup_decl_in_outer_context returns non-NULL for some
2522 : tree, replace it in the expression. */
2523 :
2524 : static tree
2525 276 : finish_taskreg_remap (tree *tp, int *walk_subtrees, void *data)
2526 : {
2527 276 : if (VAR_P (*tp))
2528 : {
2529 96 : omp_context *ctx = (omp_context *) data;
2530 96 : tree t = maybe_lookup_decl_in_outer_ctx (*tp, ctx);
2531 96 : if (t != *tp)
2532 : {
2533 9 : if (DECL_HAS_VALUE_EXPR_P (t))
2534 0 : t = unshare_expr (DECL_VALUE_EXPR (t));
2535 9 : *tp = t;
2536 : }
2537 96 : *walk_subtrees = 0;
2538 : }
2539 180 : else if (IS_TYPE_OR_DECL_P (*tp))
2540 0 : *walk_subtrees = 0;
2541 276 : return NULL_TREE;
2542 : }
2543 :
2544 : /* If any decls have been made addressable during scan_omp,
2545 : adjust their fields if needed, and layout record types
2546 : of parallel/task constructs. */
2547 :
2548 : static void
2549 25999 : finish_taskreg_scan (omp_context *ctx)
2550 : {
2551 25999 : if (ctx->record_type == NULL_TREE)
2552 : return;
2553 :
2554 : /* If any make_addressable_vars were needed, verify all
2555 : OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK,TEAMS}
2556 : statements if use_pointer_for_field hasn't changed
2557 : because of that. If it did, update field types now. */
2558 19141 : if (make_addressable_vars)
2559 : {
2560 2211 : tree c;
2561 :
2562 12357 : for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2563 12357 : c; c = OMP_CLAUSE_CHAIN (c))
2564 10146 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2565 10146 : && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2566 : {
2567 2620 : tree decl = OMP_CLAUSE_DECL (c);
2568 :
2569 : /* Global variables don't need to be copied,
2570 : the receiver side will use them directly. */
2571 2620 : if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2572 282 : continue;
2573 2338 : if (!bitmap_bit_p (make_addressable_vars, DECL_UID (decl))
2574 2338 : || !use_pointer_for_field (decl, ctx))
2575 1787 : continue;
2576 551 : tree field = lookup_field (decl, ctx);
2577 551 : if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2578 551 : && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2579 497 : continue;
2580 54 : TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2581 54 : TREE_THIS_VOLATILE (field) = 0;
2582 54 : DECL_USER_ALIGN (field) = 0;
2583 54 : SET_DECL_ALIGN (field, TYPE_ALIGN (TREE_TYPE (field)));
2584 54 : if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2585 16 : SET_TYPE_ALIGN (ctx->record_type, DECL_ALIGN (field));
2586 54 : if (ctx->srecord_type)
2587 : {
2588 0 : tree sfield = lookup_sfield (decl, ctx);
2589 0 : TREE_TYPE (sfield) = TREE_TYPE (field);
2590 0 : TREE_THIS_VOLATILE (sfield) = 0;
2591 0 : DECL_USER_ALIGN (sfield) = 0;
2592 0 : SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
2593 0 : if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2594 0 : SET_TYPE_ALIGN (ctx->srecord_type, DECL_ALIGN (sfield));
2595 : }
2596 : }
2597 : }
2598 :
2599 19141 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2600 : {
2601 14552 : tree clauses = gimple_omp_parallel_clauses (ctx->stmt);
2602 14552 : tree c = omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_);
2603 14552 : if (c)
2604 : {
2605 : /* Move the _reductemp_ clause first. GOMP_parallel_reductions
2606 : expects to find it at the start of data. */
2607 67 : tree f = lookup_field (OMP_CLAUSE_DECL (c), ctx);
2608 67 : tree *p = &TYPE_FIELDS (ctx->record_type);
2609 153 : while (*p)
2610 153 : if (*p == f)
2611 : {
2612 67 : *p = DECL_CHAIN (*p);
2613 67 : break;
2614 : }
2615 : else
2616 86 : p = &DECL_CHAIN (*p);
2617 67 : DECL_CHAIN (f) = TYPE_FIELDS (ctx->record_type);
2618 67 : TYPE_FIELDS (ctx->record_type) = f;
2619 : }
2620 14552 : layout_type (ctx->record_type);
2621 14552 : fixup_child_record_type (ctx);
2622 : }
2623 4589 : else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2624 : {
2625 1194 : layout_type (ctx->record_type);
2626 1194 : fixup_child_record_type (ctx);
2627 : }
2628 : else
2629 : {
2630 3395 : location_t loc = gimple_location (ctx->stmt);
2631 3395 : tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2632 3395 : tree detach_clause
2633 3395 : = omp_find_clause (gimple_omp_task_clauses (ctx->stmt),
2634 : OMP_CLAUSE_DETACH);
2635 : /* Move VLA fields to the end. */
2636 3395 : p = &TYPE_FIELDS (ctx->record_type);
2637 15232 : while (*p)
2638 11837 : if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2639 11837 : || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2640 : {
2641 96 : *q = *p;
2642 96 : *p = TREE_CHAIN (*p);
2643 96 : TREE_CHAIN (*q) = NULL_TREE;
2644 96 : q = &TREE_CHAIN (*q);
2645 : }
2646 : else
2647 11741 : p = &DECL_CHAIN (*p);
2648 3395 : *p = vla_fields;
2649 3395 : if (gimple_omp_task_taskloop_p (ctx->stmt))
2650 : {
2651 : /* Move fields corresponding to first and second _looptemp_
2652 : clause first. There are filled by GOMP_taskloop
2653 : and thus need to be in specific positions. */
2654 1567 : tree clauses = gimple_omp_task_clauses (ctx->stmt);
2655 1567 : tree c1 = omp_find_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
2656 1567 : tree c2 = omp_find_clause (OMP_CLAUSE_CHAIN (c1),
2657 : OMP_CLAUSE__LOOPTEMP_);
2658 1567 : tree c3 = omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_);
2659 1567 : tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2660 1567 : tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2661 2084 : tree f3 = c3 ? lookup_field (OMP_CLAUSE_DECL (c3), ctx) : NULL_TREE;
2662 1567 : p = &TYPE_FIELDS (ctx->record_type);
2663 8873 : while (*p)
2664 7306 : if (*p == f1 || *p == f2 || *p == f3)
2665 3651 : *p = DECL_CHAIN (*p);
2666 : else
2667 3655 : p = &DECL_CHAIN (*p);
2668 1567 : DECL_CHAIN (f1) = f2;
2669 1567 : if (c3)
2670 : {
2671 517 : DECL_CHAIN (f2) = f3;
2672 517 : DECL_CHAIN (f3) = TYPE_FIELDS (ctx->record_type);
2673 : }
2674 : else
2675 1050 : DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2676 1567 : TYPE_FIELDS (ctx->record_type) = f1;
2677 1567 : if (ctx->srecord_type)
2678 : {
2679 389 : f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2680 389 : f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2681 389 : if (c3)
2682 186 : f3 = lookup_sfield (OMP_CLAUSE_DECL (c3), ctx);
2683 389 : p = &TYPE_FIELDS (ctx->srecord_type);
2684 2099 : while (*p)
2685 1710 : if (*p == f1 || *p == f2 || *p == f3)
2686 964 : *p = DECL_CHAIN (*p);
2687 : else
2688 746 : p = &DECL_CHAIN (*p);
2689 389 : DECL_CHAIN (f1) = f2;
2690 389 : DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2691 389 : if (c3)
2692 : {
2693 186 : DECL_CHAIN (f2) = f3;
2694 186 : DECL_CHAIN (f3) = TYPE_FIELDS (ctx->srecord_type);
2695 : }
2696 : else
2697 203 : DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2698 389 : TYPE_FIELDS (ctx->srecord_type) = f1;
2699 : }
2700 : }
2701 3395 : if (detach_clause)
2702 : {
2703 189 : tree c, field;
2704 :
2705 : /* Look for a firstprivate clause with the detach event handle. */
2706 540 : for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2707 540 : c; c = OMP_CLAUSE_CHAIN (c))
2708 : {
2709 540 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE)
2710 347 : continue;
2711 193 : if (maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_DECL (c), ctx)
2712 193 : == OMP_CLAUSE_DECL (detach_clause))
2713 : break;
2714 : }
2715 :
2716 189 : gcc_assert (c);
2717 189 : field = lookup_field (OMP_CLAUSE_DECL (c), ctx);
2718 :
2719 : /* Move field corresponding to the detach clause first.
2720 : This is filled by GOMP_task and needs to be in a
2721 : specific position. */
2722 189 : p = &TYPE_FIELDS (ctx->record_type);
2723 518 : while (*p)
2724 329 : if (*p == field)
2725 189 : *p = DECL_CHAIN (*p);
2726 : else
2727 140 : p = &DECL_CHAIN (*p);
2728 189 : DECL_CHAIN (field) = TYPE_FIELDS (ctx->record_type);
2729 189 : TYPE_FIELDS (ctx->record_type) = field;
2730 189 : if (ctx->srecord_type)
2731 : {
2732 3 : field = lookup_sfield (OMP_CLAUSE_DECL (c), ctx);
2733 3 : p = &TYPE_FIELDS (ctx->srecord_type);
2734 9 : while (*p)
2735 6 : if (*p == field)
2736 3 : *p = DECL_CHAIN (*p);
2737 : else
2738 3 : p = &DECL_CHAIN (*p);
2739 3 : DECL_CHAIN (field) = TYPE_FIELDS (ctx->srecord_type);
2740 3 : TYPE_FIELDS (ctx->srecord_type) = field;
2741 : }
2742 : }
2743 3395 : layout_type (ctx->record_type);
2744 3395 : fixup_child_record_type (ctx);
2745 3395 : if (ctx->srecord_type)
2746 520 : layout_type (ctx->srecord_type);
2747 3395 : tree t = fold_convert_loc (loc, long_integer_type_node,
2748 3395 : TYPE_SIZE_UNIT (ctx->record_type));
2749 3395 : if (TREE_CODE (t) != INTEGER_CST)
2750 : {
2751 21 : t = unshare_expr (t);
2752 21 : walk_tree (&t, finish_taskreg_remap, ctx, NULL);
2753 : }
2754 3395 : gimple_omp_task_set_arg_size (ctx->stmt, t);
2755 3395 : t = build_int_cst (long_integer_type_node,
2756 3395 : TYPE_ALIGN_UNIT (ctx->record_type));
2757 3395 : gimple_omp_task_set_arg_align (ctx->stmt, t);
2758 : }
2759 : }
2760 :
2761 : /* Find the enclosing offload context. */
2762 :
2763 : static omp_context *
2764 9665 : enclosing_target_ctx (omp_context *ctx)
2765 : {
2766 43359 : for (; ctx; ctx = ctx->outer)
2767 41745 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2768 : break;
2769 :
2770 22111 : return ctx;
2771 : }
2772 :
2773 : /* Return whether CTX's parent compute construct is an OpenACC 'kernels'
2774 : construct.
2775 : (This doesn't include OpenACC 'kernels' decomposed parts.) */
2776 :
2777 : static bool
2778 11325 : ctx_in_oacc_kernels_region (omp_context *ctx)
2779 : {
2780 39137 : for (;ctx != NULL; ctx = ctx->outer)
2781 : {
2782 29472 : gimple *stmt = ctx->stmt;
2783 29472 : if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2784 29472 : && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2785 : return true;
2786 : }
2787 :
2788 : return false;
2789 : }
2790 :
2791 : /* Check the parallelism clauses inside a OpenACC 'kernels' region.
2792 : (This doesn't include OpenACC 'kernels' decomposed parts.)
2793 : Until kernels handling moves to use the same loop indirection
2794 : scheme as parallel, we need to do this checking early. */
2795 :
2796 : static unsigned
2797 7151 : check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2798 : {
2799 7151 : bool checking = true;
2800 7151 : unsigned outer_mask = 0;
2801 7151 : unsigned this_mask = 0;
2802 7151 : bool has_seq = false, has_auto = false;
2803 :
2804 7151 : if (ctx->outer)
2805 4819 : outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
2806 7151 : if (!stmt)
2807 : {
2808 4819 : checking = false;
2809 4819 : if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2810 : return outer_mask;
2811 1730 : stmt = as_a <gomp_for *> (ctx->stmt);
2812 : }
2813 :
2814 11330 : for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2815 : {
2816 7268 : switch (OMP_CLAUSE_CODE (c))
2817 : {
2818 645 : case OMP_CLAUSE_GANG:
2819 645 : this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2820 645 : break;
2821 439 : case OMP_CLAUSE_WORKER:
2822 439 : this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2823 439 : break;
2824 342 : case OMP_CLAUSE_VECTOR:
2825 342 : this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2826 342 : break;
2827 63 : case OMP_CLAUSE_SEQ:
2828 63 : has_seq = true;
2829 63 : break;
2830 94 : case OMP_CLAUSE_AUTO:
2831 94 : has_auto = true;
2832 94 : break;
2833 : default:
2834 : break;
2835 : }
2836 : }
2837 :
2838 4062 : if (checking)
2839 : {
2840 2332 : if (has_seq && (this_mask || has_auto))
2841 36 : error_at (gimple_location (stmt), "%<seq%> overrides other"
2842 : " OpenACC loop specifiers");
2843 2296 : else if (has_auto && this_mask)
2844 30 : error_at (gimple_location (stmt), "%<auto%> conflicts with other"
2845 : " OpenACC loop specifiers");
2846 :
2847 2332 : if (this_mask & outer_mask)
2848 15 : error_at (gimple_location (stmt), "inner loop uses same"
2849 : " OpenACC parallelism as containing loop");
2850 : }
2851 :
2852 4062 : return outer_mask | this_mask;
2853 : }
2854 :
2855 : /* Scan a GIMPLE_OMP_FOR. */
2856 :
2857 : static omp_context *
2858 52612 : scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2859 : {
2860 52612 : omp_context *ctx;
2861 52612 : size_t i;
2862 52612 : tree clauses = gimple_omp_for_clauses (stmt);
2863 :
2864 52612 : ctx = new_omp_context (stmt, outer_ctx);
2865 :
2866 52612 : if (is_gimple_omp_oacc (stmt))
2867 : {
2868 12446 : omp_context *tgt = enclosing_target_ctx (outer_ctx);
2869 :
2870 12446 : if (!(tgt && is_oacc_kernels (tgt)))
2871 32251 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2872 : {
2873 22137 : tree c_op0;
2874 22137 : switch (OMP_CLAUSE_CODE (c))
2875 : {
2876 1952 : case OMP_CLAUSE_GANG:
2877 1952 : c_op0 = OMP_CLAUSE_GANG_EXPR (c);
2878 1952 : break;
2879 :
2880 1426 : case OMP_CLAUSE_WORKER:
2881 1426 : c_op0 = OMP_CLAUSE_WORKER_EXPR (c);
2882 1426 : break;
2883 :
2884 1627 : case OMP_CLAUSE_VECTOR:
2885 1627 : c_op0 = OMP_CLAUSE_VECTOR_EXPR (c);
2886 1627 : break;
2887 :
2888 17132 : default:
2889 17132 : continue;
2890 : }
2891 :
2892 5005 : if (c_op0)
2893 : {
2894 : /* By construction, this is impossible for OpenACC 'kernels'
2895 : decomposed parts. */
2896 210 : gcc_assert (!(tgt && is_oacc_kernels_decomposed_part (tgt)));
2897 :
2898 210 : error_at (OMP_CLAUSE_LOCATION (c),
2899 : "argument not permitted on %qs clause",
2900 210 : omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
2901 210 : if (tgt)
2902 180 : inform (gimple_location (tgt->stmt),
2903 : "enclosing parent compute construct");
2904 30 : else if (oacc_get_fn_attrib (current_function_decl))
2905 30 : inform (DECL_SOURCE_LOCATION (current_function_decl),
2906 : "enclosing routine");
2907 : else
2908 0 : gcc_unreachable ();
2909 : }
2910 : }
2911 :
2912 12446 : if (tgt && is_oacc_kernels (tgt))
2913 2332 : check_oacc_kernel_gwv (stmt, ctx);
2914 :
2915 : /* Collect all variables named in reductions on this loop. Ensure
2916 : that, if this loop has a reduction on some variable v, and there is
2917 : a reduction on v somewhere in an outer context, then there is a
2918 : reduction on v on all intervening loops as well. */
2919 12446 : tree local_reduction_clauses = NULL;
2920 39374 : for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2921 : {
2922 26928 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
2923 4712 : local_reduction_clauses
2924 4712 : = tree_cons (NULL, c, local_reduction_clauses);
2925 : }
2926 12446 : if (ctx->outer_reduction_clauses == NULL && ctx->outer != NULL)
2927 11920 : ctx->outer_reduction_clauses
2928 11920 : = chainon (unshare_expr (ctx->outer->local_reduction_clauses),
2929 : ctx->outer->outer_reduction_clauses);
2930 12446 : tree outer_reduction_clauses = ctx->outer_reduction_clauses;
2931 12446 : tree local_iter = local_reduction_clauses;
2932 17158 : for (; local_iter; local_iter = TREE_CHAIN (local_iter))
2933 : {
2934 4712 : tree local_clause = TREE_VALUE (local_iter);
2935 4712 : tree local_var = OMP_CLAUSE_DECL (local_clause);
2936 4712 : tree_code local_op = OMP_CLAUSE_REDUCTION_CODE (local_clause);
2937 4712 : bool have_outer_reduction = false;
2938 4712 : tree ctx_iter = outer_reduction_clauses;
2939 5826 : for (; ctx_iter; ctx_iter = TREE_CHAIN (ctx_iter))
2940 : {
2941 3325 : tree outer_clause = TREE_VALUE (ctx_iter);
2942 3325 : tree outer_var = OMP_CLAUSE_DECL (outer_clause);
2943 3325 : tree_code outer_op = OMP_CLAUSE_REDUCTION_CODE (outer_clause);
2944 3325 : if (outer_var == local_var && outer_op != local_op)
2945 : {
2946 535 : if (warning_at (OMP_CLAUSE_LOCATION (local_clause),
2947 535 : OPT_Wopenmp, "conflicting reduction "
2948 : "operations for %qE",
2949 : local_var))
2950 535 : inform (OMP_CLAUSE_LOCATION (outer_clause),
2951 : "location of the previous reduction for %qE",
2952 : outer_var);
2953 : }
2954 3325 : if (outer_var == local_var)
2955 : {
2956 : have_outer_reduction = true;
2957 : break;
2958 : }
2959 : }
2960 4712 : if (have_outer_reduction)
2961 : {
2962 : /* There is a reduction on outer_var both on this loop and on
2963 : some enclosing loop. Walk up the context tree until such a
2964 : loop with a reduction on outer_var is found, and complain
2965 : about all intervening loops that do not have such a
2966 : reduction. */
2967 2211 : struct omp_context *curr_loop = ctx->outer;
2968 2211 : bool found = false;
2969 2826 : while (curr_loop != NULL)
2970 : {
2971 2826 : tree curr_iter = curr_loop->local_reduction_clauses;
2972 3460 : for (; curr_iter; curr_iter = TREE_CHAIN (curr_iter))
2973 : {
2974 2845 : tree curr_clause = TREE_VALUE (curr_iter);
2975 2845 : tree curr_var = OMP_CLAUSE_DECL (curr_clause);
2976 2845 : if (curr_var == local_var)
2977 : {
2978 : found = true;
2979 : break;
2980 : }
2981 : }
2982 2826 : if (!found)
2983 615 : warning_at (gimple_location (curr_loop->stmt), OPT_Wopenmp,
2984 : "nested loop in reduction needs "
2985 : "reduction clause for %qE",
2986 : local_var);
2987 : else
2988 : break;
2989 615 : curr_loop = curr_loop->outer;
2990 : }
2991 : }
2992 : }
2993 12446 : ctx->local_reduction_clauses = local_reduction_clauses;
2994 12446 : ctx->outer_reduction_clauses
2995 12446 : = chainon (unshare_expr (ctx->local_reduction_clauses),
2996 : ctx->outer_reduction_clauses);
2997 :
2998 12446 : if (tgt && is_oacc_kernels (tgt))
2999 : {
3000 : /* Strip out reductions, as they are not handled yet. */
3001 : tree *prev_ptr = &clauses;
3002 :
3003 7123 : while (tree probe = *prev_ptr)
3004 : {
3005 4791 : tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
3006 :
3007 4791 : if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
3008 718 : *prev_ptr = *next_ptr;
3009 : else
3010 : prev_ptr = next_ptr;
3011 : }
3012 :
3013 2332 : gimple_omp_for_set_clauses (stmt, clauses);
3014 : }
3015 : }
3016 :
3017 52612 : scan_sharing_clauses (clauses, ctx);
3018 :
3019 52612 : scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
3020 179856 : for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
3021 : {
3022 74632 : scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
3023 74632 : scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
3024 74632 : scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
3025 74632 : scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
3026 : }
3027 52612 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
3028 52612 : return ctx;
3029 : }
3030 :
3031 : /* Duplicate #pragma omp simd, one for SIMT, another one for SIMD. */
3032 :
3033 : static void
3034 0 : scan_omp_simd (gimple_stmt_iterator *gsi, gomp_for *stmt,
3035 : omp_context *outer_ctx)
3036 : {
3037 0 : gbind *bind = gimple_build_bind (NULL, NULL, NULL);
3038 0 : gsi_replace (gsi, bind, false);
3039 0 : gimple_seq seq = NULL;
3040 0 : gimple *g = gimple_build_call_internal (IFN_GOMP_USE_SIMT, 0);
3041 0 : tree cond = create_tmp_var_raw (integer_type_node);
3042 0 : DECL_CONTEXT (cond) = current_function_decl;
3043 0 : DECL_SEEN_IN_BIND_EXPR_P (cond) = 1;
3044 0 : gimple_bind_set_vars (bind, cond);
3045 0 : gimple_call_set_lhs (g, cond);
3046 0 : gimple_seq_add_stmt (&seq, g);
3047 0 : tree lab1 = create_artificial_label (UNKNOWN_LOCATION);
3048 0 : tree lab2 = create_artificial_label (UNKNOWN_LOCATION);
3049 0 : tree lab3 = create_artificial_label (UNKNOWN_LOCATION);
3050 0 : g = gimple_build_cond (NE_EXPR, cond, integer_zero_node, lab1, lab2);
3051 0 : gimple_seq_add_stmt (&seq, g);
3052 0 : g = gimple_build_label (lab1);
3053 0 : gimple_seq_add_stmt (&seq, g);
3054 0 : gimple_seq new_seq = copy_gimple_seq_and_replace_locals (stmt);
3055 0 : gomp_for *new_stmt = as_a <gomp_for *> (new_seq);
3056 0 : tree clause = build_omp_clause (gimple_location (stmt), OMP_CLAUSE__SIMT_);
3057 0 : OMP_CLAUSE_CHAIN (clause) = gimple_omp_for_clauses (new_stmt);
3058 0 : gimple_omp_for_set_clauses (new_stmt, clause);
3059 0 : gimple_seq_add_stmt (&seq, new_stmt);
3060 0 : g = gimple_build_goto (lab3);
3061 0 : gimple_seq_add_stmt (&seq, g);
3062 0 : g = gimple_build_label (lab2);
3063 0 : gimple_seq_add_stmt (&seq, g);
3064 0 : gimple_seq_add_stmt (&seq, stmt);
3065 0 : g = gimple_build_label (lab3);
3066 0 : gimple_seq_add_stmt (&seq, g);
3067 0 : gimple_bind_set_body (bind, seq);
3068 0 : update_stmt (bind);
3069 0 : scan_omp_for (new_stmt, outer_ctx);
3070 0 : scan_omp_for (stmt, outer_ctx)->simt_stmt = new_stmt;
3071 0 : }
3072 :
3073 : static tree omp_find_scan (gimple_stmt_iterator *, bool *,
3074 : struct walk_stmt_info *);
3075 : static omp_context *maybe_lookup_ctx (gimple *);
3076 :
3077 : /* Duplicate #pragma omp simd, one for the scan input phase loop and one
3078 : for scan phase loop. */
3079 :
3080 : static void
3081 83 : scan_omp_simd_scan (gimple_stmt_iterator *gsi, gomp_for *stmt,
3082 : omp_context *outer_ctx)
3083 : {
3084 : /* The only change between inclusive and exclusive scan will be
3085 : within the first simd loop, so just use inclusive in the
3086 : worksharing loop. */
3087 83 : outer_ctx->scan_inclusive = true;
3088 83 : tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_INCLUSIVE);
3089 83 : OMP_CLAUSE_DECL (c) = integer_zero_node;
3090 :
3091 83 : gomp_scan *input_stmt = gimple_build_omp_scan (NULL, NULL_TREE);
3092 83 : gomp_scan *scan_stmt = gimple_build_omp_scan (NULL, c);
3093 83 : gsi_replace (gsi, input_stmt, false);
3094 83 : gimple_seq input_body = NULL;
3095 83 : gimple_seq_add_stmt (&input_body, stmt);
3096 83 : gsi_insert_after (gsi, scan_stmt, GSI_NEW_STMT);
3097 :
3098 83 : gimple_stmt_iterator input1_gsi = gsi_none ();
3099 83 : struct walk_stmt_info wi;
3100 83 : memset (&wi, 0, sizeof (wi));
3101 83 : wi.val_only = true;
3102 83 : wi.info = (void *) &input1_gsi;
3103 83 : walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), omp_find_scan, NULL, &wi);
3104 83 : gcc_assert (!gsi_end_p (input1_gsi));
3105 :
3106 83 : gimple *input_stmt1 = gsi_stmt (input1_gsi);
3107 83 : gsi_next (&input1_gsi);
3108 83 : gimple *scan_stmt1 = gsi_stmt (input1_gsi);
3109 83 : gcc_assert (scan_stmt1 && gimple_code (scan_stmt1) == GIMPLE_OMP_SCAN);
3110 83 : c = gimple_omp_scan_clauses (as_a <gomp_scan *> (scan_stmt1));
3111 166 : if (c && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_EXCLUSIVE)
3112 : std::swap (input_stmt1, scan_stmt1);
3113 :
3114 83 : gimple_seq input_body1 = gimple_omp_body (input_stmt1);
3115 83 : gimple_omp_set_body (input_stmt1, NULL);
3116 :
3117 83 : gimple_seq scan_body = copy_gimple_seq_and_replace_locals (stmt);
3118 83 : gomp_for *new_stmt = as_a <gomp_for *> (scan_body);
3119 :
3120 83 : gimple_omp_set_body (input_stmt1, input_body1);
3121 83 : gimple_omp_set_body (scan_stmt1, NULL);
3122 :
3123 83 : gimple_stmt_iterator input2_gsi = gsi_none ();
3124 83 : memset (&wi, 0, sizeof (wi));
3125 83 : wi.val_only = true;
3126 83 : wi.info = (void *) &input2_gsi;
3127 83 : walk_gimple_seq_mod (gimple_omp_body_ptr (new_stmt), omp_find_scan,
3128 : NULL, &wi);
3129 83 : gcc_assert (!gsi_end_p (input2_gsi));
3130 :
3131 83 : gimple *input_stmt2 = gsi_stmt (input2_gsi);
3132 83 : gsi_next (&input2_gsi);
3133 83 : gimple *scan_stmt2 = gsi_stmt (input2_gsi);
3134 83 : gcc_assert (scan_stmt2 && gimple_code (scan_stmt2) == GIMPLE_OMP_SCAN);
3135 166 : if (c && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_EXCLUSIVE)
3136 : std::swap (input_stmt2, scan_stmt2);
3137 :
3138 83 : gimple_omp_set_body (input_stmt2, NULL);
3139 :
3140 83 : gimple_omp_set_body (input_stmt, input_body);
3141 83 : gimple_omp_set_body (scan_stmt, scan_body);
3142 :
3143 83 : omp_context *ctx = new_omp_context (input_stmt, outer_ctx);
3144 83 : scan_omp (gimple_omp_body_ptr (input_stmt), ctx);
3145 :
3146 83 : ctx = new_omp_context (scan_stmt, outer_ctx);
3147 83 : scan_omp (gimple_omp_body_ptr (scan_stmt), ctx);
3148 :
3149 83 : maybe_lookup_ctx (new_stmt)->for_simd_scan_phase = true;
3150 83 : }
3151 :
3152 : /* Scan an OpenMP sections directive. */
3153 :
3154 : static void
3155 589 : scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
3156 : {
3157 589 : omp_context *ctx;
3158 :
3159 589 : ctx = new_omp_context (stmt, outer_ctx);
3160 589 : scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
3161 589 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
3162 589 : }
3163 :
3164 : /* Scan an OpenMP single directive. */
3165 :
3166 : static void
3167 1236 : scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
3168 : {
3169 1236 : omp_context *ctx;
3170 1236 : tree name;
3171 :
3172 1236 : ctx = new_omp_context (stmt, outer_ctx);
3173 1236 : ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3174 1236 : ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3175 1236 : name = create_tmp_var_name (".omp_copy_s");
3176 1236 : name = build_decl (gimple_location (stmt),
3177 : TYPE_DECL, name, ctx->record_type);
3178 1236 : TYPE_NAME (ctx->record_type) = name;
3179 :
3180 1236 : scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
3181 1236 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
3182 :
3183 1236 : if (TYPE_FIELDS (ctx->record_type) == NULL)
3184 1089 : ctx->record_type = NULL;
3185 : else
3186 147 : layout_type (ctx->record_type);
3187 1236 : }
3188 :
3189 : /* Scan a GIMPLE_OMP_TARGET. */
3190 :
3191 : static void
3192 41836 : scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
3193 : {
3194 41836 : omp_context *ctx;
3195 41836 : tree name;
3196 41836 : bool offloaded = is_gimple_omp_offloaded (stmt);
3197 41836 : tree clauses = gimple_omp_target_clauses (stmt);
3198 :
3199 41836 : ctx = new_omp_context (stmt, outer_ctx);
3200 41836 : ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3201 41836 : ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3202 41836 : name = create_tmp_var_name (".omp_data_t");
3203 41836 : name = build_decl (gimple_location (stmt),
3204 : TYPE_DECL, name, ctx->record_type);
3205 41836 : DECL_ARTIFICIAL (name) = 1;
3206 41836 : DECL_NAMELESS (name) = 1;
3207 41836 : TYPE_NAME (ctx->record_type) = name;
3208 41836 : TYPE_ARTIFICIAL (ctx->record_type) = 1;
3209 :
3210 41836 : if (offloaded)
3211 : {
3212 24807 : create_omp_child_function (ctx, false);
3213 24807 : gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
3214 : }
3215 :
3216 41836 : scan_sharing_clauses (clauses, ctx);
3217 41836 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
3218 :
3219 41836 : if (TYPE_FIELDS (ctx->record_type) == NULL)
3220 7765 : ctx->record_type = ctx->receiver_decl = NULL;
3221 : else
3222 : {
3223 34071 : TYPE_FIELDS (ctx->record_type)
3224 34071 : = nreverse (TYPE_FIELDS (ctx->record_type));
3225 34071 : if (flag_checking)
3226 : {
3227 34071 : unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3228 34071 : for (tree field = TYPE_FIELDS (ctx->record_type);
3229 131307 : field;
3230 97236 : field = DECL_CHAIN (field))
3231 97236 : gcc_assert (DECL_ALIGN (field) == align);
3232 : }
3233 34071 : layout_type (ctx->record_type);
3234 34071 : if (offloaded)
3235 17601 : fixup_child_record_type (ctx);
3236 : }
3237 :
3238 41836 : if (ctx->teams_nested_p && ctx->nonteams_nested_p)
3239 : {
3240 4 : error_at (gimple_location (stmt),
3241 : "%<target%> construct with nested %<teams%> construct "
3242 : "contains directives outside of the %<teams%> construct");
3243 4 : gimple_omp_set_body (stmt, gimple_build_bind (NULL, NULL, NULL));
3244 : }
3245 41836 : }
3246 :
3247 : /* Scan an OpenMP teams directive. */
3248 :
3249 : static void
3250 8761 : scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
3251 : {
3252 8761 : omp_context *ctx = new_omp_context (stmt, outer_ctx);
3253 :
3254 8761 : if (!gimple_omp_teams_host (stmt))
3255 : {
3256 6121 : scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3257 6121 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
3258 6121 : return;
3259 : }
3260 2640 : taskreg_contexts.safe_push (ctx);
3261 2640 : gcc_assert (taskreg_nesting_level == 1);
3262 2640 : ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3263 2640 : ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3264 2640 : tree name = create_tmp_var_name (".omp_data_s");
3265 2640 : name = build_decl (gimple_location (stmt),
3266 : TYPE_DECL, name, ctx->record_type);
3267 2640 : DECL_ARTIFICIAL (name) = 1;
3268 2640 : DECL_NAMELESS (name) = 1;
3269 2640 : TYPE_NAME (ctx->record_type) = name;
3270 2640 : TYPE_ARTIFICIAL (ctx->record_type) = 1;
3271 2640 : create_omp_child_function (ctx, false);
3272 2640 : gimple_omp_teams_set_child_fn (stmt, ctx->cb.dst_fn);
3273 :
3274 2640 : scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3275 2640 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
3276 :
3277 2640 : if (TYPE_FIELDS (ctx->record_type) == NULL)
3278 1446 : ctx->record_type = ctx->receiver_decl = NULL;
3279 : }
3280 :
3281 : /* Check nesting restrictions. */
3282 : static bool
3283 156699 : check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
3284 : {
3285 156699 : tree c;
3286 :
3287 : /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3288 : inside an OpenACC CTX. */
3289 156699 : if (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3290 156699 : || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE)
3291 : /* ..., except for the atomic codes that OpenACC shares with OpenMP. */
3292 : ;
3293 281799 : else if (!(is_gimple_omp (stmt)
3294 138840 : && is_gimple_omp_oacc (stmt)))
3295 : {
3296 112695 : if (oacc_get_fn_attrib (cfun->decl) != NULL)
3297 : {
3298 48 : error_at (gimple_location (stmt),
3299 : "non-OpenACC construct inside of OpenACC routine");
3300 48 : return false;
3301 : }
3302 : else
3303 235869 : for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
3304 246620 : if (is_gimple_omp (octx->stmt)
3305 123398 : && is_gimple_omp_oacc (octx->stmt))
3306 : {
3307 176 : error_at (gimple_location (stmt),
3308 : "non-OpenACC construct inside of OpenACC region");
3309 176 : return false;
3310 : }
3311 : }
3312 :
3313 156475 : if (ctx != NULL)
3314 : {
3315 83905 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
3316 83905 : && gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_REGION)
3317 : {
3318 8325 : c = omp_find_clause (gimple_omp_target_clauses (ctx->stmt),
3319 : OMP_CLAUSE_DEVICE);
3320 8325 : if (c && OMP_CLAUSE_DEVICE_ANCESTOR (c))
3321 : {
3322 9 : error_at (gimple_location (stmt),
3323 : "OpenMP constructs are not allowed in target region "
3324 : "with %<ancestor%>");
3325 9 : return false;
3326 : }
3327 :
3328 8316 : if (gimple_code (stmt) == GIMPLE_OMP_TEAMS && !ctx->teams_nested_p)
3329 6117 : ctx->teams_nested_p = true;
3330 : else
3331 2199 : ctx->nonteams_nested_p = true;
3332 : }
3333 83896 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_SCAN
3334 172 : && ctx->outer
3335 84068 : && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
3336 : ctx = ctx->outer;
3337 83896 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3338 28194 : && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD
3339 85705 : && !ctx->loop_p)
3340 : {
3341 1589 : c = NULL_TREE;
3342 1589 : if (ctx->order_concurrent
3343 1589 : && (gimple_code (stmt) == GIMPLE_OMP_ORDERED
3344 280 : || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3345 190 : || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
3346 : {
3347 210 : error_at (gimple_location (stmt),
3348 : "OpenMP constructs other than %<parallel%>, %<loop%>"
3349 : " or %<simd%> may not be nested inside a region with"
3350 : " the %<order(concurrent)%> clause");
3351 210 : return false;
3352 : }
3353 1379 : if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3354 : {
3355 133 : c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3356 133 : if (omp_find_clause (c, OMP_CLAUSE_SIMD))
3357 : {
3358 133 : if (omp_find_clause (c, OMP_CLAUSE_THREADS)
3359 133 : && (ctx->outer == NULL
3360 29 : || !gimple_omp_for_combined_into_p (ctx->stmt)
3361 25 : || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
3362 25 : || (gimple_omp_for_kind (ctx->outer->stmt)
3363 : != GF_OMP_FOR_KIND_FOR)
3364 25 : || !gimple_omp_for_combined_p (ctx->outer->stmt)))
3365 : {
3366 8 : error_at (gimple_location (stmt),
3367 : "%<ordered simd threads%> must be closely "
3368 : "nested inside of %<%s simd%> region",
3369 8 : lang_GNU_Fortran () ? "do" : "for");
3370 8 : return false;
3371 : }
3372 : return true;
3373 : }
3374 : }
3375 : else if (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3376 : || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE
3377 : || gimple_code (stmt) == GIMPLE_OMP_SCAN
3378 : || gimple_code (stmt) == GIMPLE_OMP_STRUCTURED_BLOCK)
3379 : return true;
3380 : else if (gimple_code (stmt) == GIMPLE_OMP_FOR
3381 : && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
3382 : return true;
3383 60 : error_at (gimple_location (stmt),
3384 : "OpenMP constructs other than "
3385 : "%<ordered simd%>, %<simd%>, %<loop%> or %<atomic%> may "
3386 : "not be nested inside %<simd%> region");
3387 60 : return false;
3388 : }
3389 82307 : else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3390 : {
3391 5848 : if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3392 5547 : || (gimple_omp_for_kind (stmt) != GF_OMP_FOR_KIND_DISTRIBUTE
3393 25 : && omp_find_clause (gimple_omp_for_clauses (stmt),
3394 : OMP_CLAUSE_BIND) == NULL_TREE))
3395 5864 : && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3396 : {
3397 132 : error_at (gimple_location (stmt),
3398 : "only %<distribute%>, %<parallel%> or %<loop%> "
3399 : "regions are allowed to be strictly nested inside "
3400 : "%<teams%> region");
3401 132 : return false;
3402 : }
3403 : }
3404 76459 : else if (ctx->order_concurrent
3405 1944 : && gimple_code (stmt) != GIMPLE_OMP_PARALLEL
3406 1465 : && (gimple_code (stmt) != GIMPLE_OMP_FOR
3407 1191 : || gimple_omp_for_kind (stmt) != GF_OMP_FOR_KIND_SIMD)
3408 289 : && gimple_code (stmt) != GIMPLE_OMP_SCAN
3409 76748 : && gimple_code (stmt) != GIMPLE_OMP_STRUCTURED_BLOCK)
3410 : {
3411 285 : if (ctx->loop_p)
3412 135 : error_at (gimple_location (stmt),
3413 : "OpenMP constructs other than %<parallel%>, %<loop%> or "
3414 : "%<simd%> may not be nested inside a %<loop%> region");
3415 : else
3416 150 : error_at (gimple_location (stmt),
3417 : "OpenMP constructs other than %<parallel%>, %<loop%> or "
3418 : "%<simd%> may not be nested inside a region with "
3419 : "the %<order(concurrent)%> clause");
3420 285 : return false;
3421 : }
3422 : }
3423 154460 : switch (gimple_code (stmt))
3424 : {
3425 52731 : case GIMPLE_OMP_FOR:
3426 52731 : if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_SIMD)
3427 : return true;
3428 41973 : if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3429 : {
3430 8238 : if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3431 : {
3432 0 : error_at (gimple_location (stmt),
3433 : "%<distribute%> region must be strictly nested "
3434 : "inside %<teams%> construct");
3435 0 : return false;
3436 : }
3437 : return true;
3438 : }
3439 : /* We split taskloop into task and nested taskloop in it. */
3440 33735 : if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3441 : return true;
3442 : /* For now, hope this will change and loop bind(parallel) will not
3443 : be allowed in lots of contexts. */
3444 30601 : if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
3445 48691 : && omp_find_clause (gimple_omp_for_clauses (stmt), OMP_CLAUSE_BIND))
3446 : return true;
3447 29972 : if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3448 : {
3449 12511 : bool ok = false;
3450 :
3451 12511 : if (ctx)
3452 11964 : switch (gimple_code (ctx->stmt))
3453 : {
3454 4049 : case GIMPLE_OMP_FOR:
3455 4049 : ok = (gimple_omp_for_kind (ctx->stmt)
3456 : == GF_OMP_FOR_KIND_OACC_LOOP);
3457 4049 : break;
3458 :
3459 7887 : case GIMPLE_OMP_TARGET:
3460 7887 : switch (gimple_omp_target_kind (ctx->stmt))
3461 : {
3462 : case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3463 : case GF_OMP_TARGET_KIND_OACC_KERNELS:
3464 : case GF_OMP_TARGET_KIND_OACC_SERIAL:
3465 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
3466 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
3467 : ok = true;
3468 : break;
3469 :
3470 : default:
3471 : break;
3472 : }
3473 :
3474 : default:
3475 : break;
3476 : }
3477 547 : else if (oacc_get_fn_attrib (current_function_decl))
3478 : ok = true;
3479 4049 : if (!ok)
3480 : {
3481 65 : error_at (gimple_location (stmt),
3482 : "OpenACC loop directive must be associated with"
3483 : " an OpenACC compute region");
3484 65 : return false;
3485 : }
3486 : }
3487 : /* FALLTHRU */
3488 33966 : case GIMPLE_CALL:
3489 33966 : if (is_gimple_call (stmt)
3490 33966 : && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3491 : == BUILT_IN_GOMP_CANCEL
3492 3033 : || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3493 : == BUILT_IN_GOMP_CANCELLATION_POINT))
3494 : {
3495 1829 : const char *bad = NULL;
3496 1829 : const char *kind = NULL;
3497 1829 : const char *construct
3498 1829 : = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3499 : == BUILT_IN_GOMP_CANCEL)
3500 1829 : ? "cancel"
3501 803 : : "cancellation point";
3502 1829 : if (ctx == NULL)
3503 : {
3504 41 : error_at (gimple_location (stmt), "orphaned %qs construct",
3505 : construct);
3506 41 : return false;
3507 : }
3508 1788 : switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3509 1788 : ? tree_to_shwi (gimple_call_arg (stmt, 0))
3510 : : 0)
3511 : {
3512 498 : case 1:
3513 498 : if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3514 : bad = "parallel";
3515 178 : else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3516 : == BUILT_IN_GOMP_CANCEL
3517 178 : && !integer_zerop (gimple_call_arg (stmt, 1)))
3518 134 : ctx->cancellable = true;
3519 134 : kind = "parallel";
3520 134 : break;
3521 379 : case 2:
3522 379 : if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3523 379 : || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3524 : bad = "for";
3525 69 : else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3526 : == BUILT_IN_GOMP_CANCEL
3527 69 : && !integer_zerop (gimple_call_arg (stmt, 1)))
3528 : {
3529 58 : ctx->cancellable = true;
3530 58 : if (omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
3531 : OMP_CLAUSE_NOWAIT))
3532 5 : warning_at (gimple_location (stmt), OPT_Wopenmp,
3533 : "%<cancel for%> inside "
3534 : "%<nowait%> for construct");
3535 58 : if (omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
3536 : OMP_CLAUSE_ORDERED))
3537 5 : warning_at (gimple_location (stmt), OPT_Wopenmp,
3538 : "%<cancel for%> inside "
3539 : "%<ordered%> for construct");
3540 : }
3541 5 : kind = "for";
3542 5 : break;
3543 383 : case 4:
3544 383 : if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3545 383 : && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3546 : bad = "sections";
3547 93 : else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3548 : == BUILT_IN_GOMP_CANCEL
3549 93 : && !integer_zerop (gimple_call_arg (stmt, 1)))
3550 : {
3551 73 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3552 : {
3553 0 : ctx->cancellable = true;
3554 0 : if (omp_find_clause (gimple_omp_sections_clauses
3555 0 : (ctx->stmt),
3556 : OMP_CLAUSE_NOWAIT))
3557 0 : warning_at (gimple_location (stmt), OPT_Wopenmp,
3558 : "%<cancel sections%> inside "
3559 : "%<nowait%> sections construct");
3560 : }
3561 : else
3562 : {
3563 73 : gcc_assert (ctx->outer
3564 : && gimple_code (ctx->outer->stmt)
3565 : == GIMPLE_OMP_SECTIONS);
3566 73 : ctx->outer->cancellable = true;
3567 73 : if (omp_find_clause (gimple_omp_sections_clauses
3568 73 : (ctx->outer->stmt),
3569 : OMP_CLAUSE_NOWAIT))
3570 10 : warning_at (gimple_location (stmt), OPT_Wopenmp,
3571 : "%<cancel sections%> inside "
3572 : "%<nowait%> sections construct");
3573 : }
3574 : }
3575 10 : kind = "sections";
3576 10 : break;
3577 528 : case 8:
3578 528 : if (!is_task_ctx (ctx)
3579 528 : && (!is_taskloop_ctx (ctx)
3580 54 : || ctx->outer == NULL
3581 54 : || !is_task_ctx (ctx->outer)))
3582 : bad = "task";
3583 : else
3584 : {
3585 248 : for (omp_context *octx = ctx->outer;
3586 439 : octx; octx = octx->outer)
3587 : {
3588 425 : switch (gimple_code (octx->stmt))
3589 : {
3590 : case GIMPLE_OMP_TASKGROUP:
3591 : break;
3592 40 : case GIMPLE_OMP_TARGET:
3593 40 : if (gimple_omp_target_kind (octx->stmt)
3594 : != GF_OMP_TARGET_KIND_REGION)
3595 20 : continue;
3596 : /* FALLTHRU */
3597 99 : case GIMPLE_OMP_PARALLEL:
3598 99 : case GIMPLE_OMP_TEAMS:
3599 99 : error_at (gimple_location (stmt),
3600 : "%<%s taskgroup%> construct not closely "
3601 : "nested inside of %<taskgroup%> region",
3602 : construct);
3603 99 : return false;
3604 104 : case GIMPLE_OMP_TASK:
3605 104 : if (gimple_omp_task_taskloop_p (octx->stmt)
3606 94 : && octx->outer
3607 198 : && is_taskloop_ctx (octx->outer))
3608 : {
3609 94 : tree clauses
3610 94 : = gimple_omp_for_clauses (octx->outer->stmt);
3611 94 : if (!omp_find_clause (clauses, OMP_CLAUSE_NOGROUP))
3612 : break;
3613 : }
3614 60 : continue;
3615 111 : default:
3616 111 : continue;
3617 171 : }
3618 : break;
3619 : }
3620 149 : ctx->cancellable = true;
3621 : }
3622 149 : kind = "taskgroup";
3623 149 : break;
3624 0 : default:
3625 0 : error_at (gimple_location (stmt), "invalid arguments");
3626 0 : return false;
3627 : }
3628 298 : if (bad)
3629 : {
3630 1200 : error_at (gimple_location (stmt),
3631 : "%<%s %s%> construct not closely nested inside of %qs",
3632 : construct, kind, bad);
3633 1200 : return false;
3634 : }
3635 : }
3636 : /* FALLTHRU */
3637 : case GIMPLE_OMP_SECTIONS:
3638 : case GIMPLE_OMP_SINGLE:
3639 55442 : for (; ctx != NULL; ctx = ctx->outer)
3640 37331 : switch (gimple_code (ctx->stmt))
3641 : {
3642 6825 : case GIMPLE_OMP_FOR:
3643 6825 : if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3644 6825 : && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3645 : break;
3646 : /* FALLTHRU */
3647 730 : case GIMPLE_OMP_SECTIONS:
3648 730 : case GIMPLE_OMP_SINGLE:
3649 730 : case GIMPLE_OMP_ORDERED:
3650 730 : case GIMPLE_OMP_MASTER:
3651 730 : case GIMPLE_OMP_MASKED:
3652 730 : case GIMPLE_OMP_TASK:
3653 730 : case GIMPLE_OMP_CRITICAL:
3654 730 : if (is_gimple_call (stmt))
3655 : {
3656 659 : if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3657 : != BUILT_IN_GOMP_BARRIER)
3658 : return true;
3659 23 : error_at (gimple_location (stmt),
3660 : "barrier region may not be closely nested inside "
3661 : "of work-sharing, %<loop%>, %<critical%>, "
3662 : "%<ordered%>, %<master%>, %<masked%>, explicit "
3663 : "%<task%> or %<taskloop%> region");
3664 23 : return false;
3665 : }
3666 71 : error_at (gimple_location (stmt),
3667 : "work-sharing region may not be closely nested inside "
3668 : "of work-sharing, %<loop%>, %<critical%>, %<ordered%>, "
3669 : "%<master%>, %<masked%>, explicit %<task%> or "
3670 : "%<taskloop%> region");
3671 71 : return false;
3672 : case GIMPLE_OMP_PARALLEL:
3673 : case GIMPLE_OMP_TEAMS:
3674 : return true;
3675 13437 : case GIMPLE_OMP_TARGET:
3676 13437 : if (gimple_omp_target_kind (ctx->stmt)
3677 : == GF_OMP_TARGET_KIND_REGION)
3678 : return true;
3679 : break;
3680 : default:
3681 : break;
3682 : }
3683 : break;
3684 : case GIMPLE_OMP_MASTER:
3685 : case GIMPLE_OMP_MASKED:
3686 1523 : for (; ctx != NULL; ctx = ctx->outer)
3687 1014 : switch (gimple_code (ctx->stmt))
3688 : {
3689 14 : case GIMPLE_OMP_FOR:
3690 14 : if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3691 14 : && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3692 : break;
3693 : /* FALLTHRU */
3694 30 : case GIMPLE_OMP_SECTIONS:
3695 30 : case GIMPLE_OMP_SINGLE:
3696 30 : case GIMPLE_OMP_TASK:
3697 60 : error_at (gimple_location (stmt),
3698 : "%qs region may not be closely nested inside "
3699 : "of work-sharing, %<loop%>, explicit %<task%> or "
3700 : "%<taskloop%> region",
3701 30 : gimple_code (stmt) == GIMPLE_OMP_MASTER
3702 : ? "master" : "masked");
3703 30 : return false;
3704 : case GIMPLE_OMP_PARALLEL:
3705 : case GIMPLE_OMP_TEAMS:
3706 : return true;
3707 10 : case GIMPLE_OMP_TARGET:
3708 10 : if (gimple_omp_target_kind (ctx->stmt)
3709 : == GF_OMP_TARGET_KIND_REGION)
3710 : return true;
3711 : break;
3712 : default:
3713 : break;
3714 : }
3715 : break;
3716 : case GIMPLE_OMP_SCOPE:
3717 286 : for (; ctx != NULL; ctx = ctx->outer)
3718 183 : switch (gimple_code (ctx->stmt))
3719 : {
3720 7 : case GIMPLE_OMP_FOR:
3721 7 : if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3722 7 : && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3723 : break;
3724 : /* FALLTHRU */
3725 25 : case GIMPLE_OMP_SECTIONS:
3726 25 : case GIMPLE_OMP_SINGLE:
3727 25 : case GIMPLE_OMP_TASK:
3728 25 : case GIMPLE_OMP_CRITICAL:
3729 25 : case GIMPLE_OMP_ORDERED:
3730 25 : case GIMPLE_OMP_MASTER:
3731 25 : case GIMPLE_OMP_MASKED:
3732 25 : error_at (gimple_location (stmt),
3733 : "%<scope%> region may not be closely nested inside "
3734 : "of work-sharing, %<loop%>, explicit %<task%>, "
3735 : "%<taskloop%>, %<critical%>, %<ordered%>, %<master%>, "
3736 : "or %<masked%> region");
3737 25 : return false;
3738 : case GIMPLE_OMP_PARALLEL:
3739 : case GIMPLE_OMP_TEAMS:
3740 : return true;
3741 5 : case GIMPLE_OMP_TARGET:
3742 5 : if (gimple_omp_target_kind (ctx->stmt)
3743 : == GF_OMP_TARGET_KIND_REGION)
3744 : return true;
3745 : break;
3746 : default:
3747 : break;
3748 : }
3749 : break;
3750 5348 : case GIMPLE_OMP_TASK:
3751 22761 : for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3752 17417 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS)
3753 : {
3754 4 : enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_KIND (c);
3755 4 : error_at (OMP_CLAUSE_LOCATION (c),
3756 : "%<%s(%s)%> is only allowed in %<omp ordered%>",
3757 4 : OMP_CLAUSE_DOACROSS_DEPEND (c) ? "depend" : "doacross",
3758 : kind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink");
3759 4 : return false;
3760 : }
3761 : break;
3762 1631 : case GIMPLE_OMP_ORDERED:
3763 2873 : for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3764 2873 : c; c = OMP_CLAUSE_CHAIN (c))
3765 : {
3766 1258 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DOACROSS)
3767 : {
3768 169 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
3769 : {
3770 4 : error_at (OMP_CLAUSE_LOCATION (c),
3771 : "invalid depend kind in omp %<ordered%> %<depend%>");
3772 4 : return false;
3773 : }
3774 165 : gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
3775 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
3776 165 : continue;
3777 : }
3778 :
3779 1089 : tree oclause;
3780 : /* Look for containing ordered(N) loop. */
3781 1089 : if (ctx == NULL
3782 1077 : || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3783 1089 : || (oclause
3784 1077 : = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
3785 : OMP_CLAUSE_ORDERED)) == NULL_TREE)
3786 : {
3787 12 : error_at (OMP_CLAUSE_LOCATION (c),
3788 : "%<ordered%> construct with %<depend%> clause "
3789 : "must be closely nested inside an %<ordered%> loop");
3790 12 : return false;
3791 : }
3792 : }
3793 1615 : c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3794 1615 : if (omp_find_clause (c, OMP_CLAUSE_SIMD))
3795 : {
3796 : /* ordered simd must be closely nested inside of simd region,
3797 : and simd region must not encounter constructs other than
3798 : ordered simd, therefore ordered simd may be either orphaned,
3799 : or ctx->stmt must be simd. The latter case is handled already
3800 : earlier. */
3801 34 : if (ctx != NULL)
3802 : {
3803 10 : error_at (gimple_location (stmt),
3804 : "%<ordered%> %<simd%> must be closely nested inside "
3805 : "%<simd%> region");
3806 10 : return false;
3807 : }
3808 : }
3809 1605 : for (; ctx != NULL; ctx = ctx->outer)
3810 1474 : switch (gimple_code (ctx->stmt))
3811 : {
3812 38 : case GIMPLE_OMP_CRITICAL:
3813 38 : case GIMPLE_OMP_TASK:
3814 38 : case GIMPLE_OMP_ORDERED:
3815 38 : ordered_in_taskloop:
3816 38 : error_at (gimple_location (stmt),
3817 : "%<ordered%> region may not be closely nested inside "
3818 : "of %<critical%>, %<ordered%>, explicit %<task%> or "
3819 : "%<taskloop%> region");
3820 38 : return false;
3821 1416 : case GIMPLE_OMP_FOR:
3822 1416 : if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3823 10 : goto ordered_in_taskloop;
3824 1406 : tree o;
3825 1406 : o = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
3826 : OMP_CLAUSE_ORDERED);
3827 1406 : if (o == NULL)
3828 : {
3829 22 : error_at (gimple_location (stmt),
3830 : "%<ordered%> region must be closely nested inside "
3831 : "a loop region with an %<ordered%> clause");
3832 22 : return false;
3833 : }
3834 1384 : if (!gimple_omp_ordered_standalone_p (stmt))
3835 : {
3836 375 : if (OMP_CLAUSE_ORDERED_DOACROSS (o))
3837 : {
3838 10 : error_at (gimple_location (stmt),
3839 : "%<ordered%> construct without %<doacross%> or "
3840 : "%<depend%> clauses must not have the same "
3841 : "binding region as %<ordered%> construct with "
3842 : "those clauses");
3843 10 : return false;
3844 : }
3845 365 : else if (OMP_CLAUSE_ORDERED_EXPR (o))
3846 : {
3847 23 : tree co
3848 23 : = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
3849 : OMP_CLAUSE_COLLAPSE);
3850 23 : HOST_WIDE_INT
3851 23 : o_n = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (o));
3852 23 : HOST_WIDE_INT c_n = 1;
3853 23 : if (co)
3854 5 : c_n = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (co));
3855 23 : if (o_n != c_n)
3856 : {
3857 10 : error_at (gimple_location (stmt),
3858 : "%<ordered%> construct without %<doacross%> "
3859 : "or %<depend%> clauses binds to loop where "
3860 : "%<collapse%> argument %wd is different from "
3861 : "%<ordered%> argument %wd", c_n, o_n);
3862 10 : return false;
3863 : }
3864 : }
3865 : }
3866 : return true;
3867 10 : case GIMPLE_OMP_TARGET:
3868 10 : if (gimple_omp_target_kind (ctx->stmt)
3869 : != GF_OMP_TARGET_KIND_REGION)
3870 : break;
3871 : /* FALLTHRU */
3872 30 : case GIMPLE_OMP_PARALLEL:
3873 30 : case GIMPLE_OMP_TEAMS:
3874 30 : error_at (gimple_location (stmt),
3875 : "%<ordered%> region must be closely nested inside "
3876 : "a loop region with an %<ordered%> clause");
3877 30 : return false;
3878 : default:
3879 : break;
3880 : }
3881 : break;
3882 462 : case GIMPLE_OMP_CRITICAL:
3883 462 : {
3884 462 : tree this_stmt_name
3885 462 : = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3886 888 : for (; ctx != NULL; ctx = ctx->outer)
3887 432 : if (gomp_critical *other_crit
3888 451 : = dyn_cast <gomp_critical *> (ctx->stmt))
3889 25 : if (this_stmt_name == gimple_omp_critical_name (other_crit))
3890 : {
3891 6 : error_at (gimple_location (stmt),
3892 : "%<critical%> region may not be nested inside "
3893 : "a %<critical%> region with the same name");
3894 6 : return false;
3895 : }
3896 : }
3897 : break;
3898 8805 : case GIMPLE_OMP_TEAMS:
3899 8805 : if (ctx == NULL)
3900 : break;
3901 6165 : else if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3902 6165 : || (gimple_omp_target_kind (ctx->stmt)
3903 : != GF_OMP_TARGET_KIND_REGION))
3904 : {
3905 : /* Teams construct can appear either strictly nested inside of
3906 : target construct with no intervening stmts, or can be encountered
3907 : only by initial task (so must not appear inside any OpenMP
3908 : construct. */
3909 44 : error_at (gimple_location (stmt),
3910 : "%<teams%> construct must be closely nested inside of "
3911 : "%<target%> construct or not nested in any OpenMP "
3912 : "construct");
3913 44 : return false;
3914 : }
3915 : break;
3916 42219 : case GIMPLE_OMP_TARGET:
3917 189290 : for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3918 147075 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS)
3919 : {
3920 4 : enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_KIND (c);
3921 4 : error_at (OMP_CLAUSE_LOCATION (c),
3922 : "%<depend(%s)%> is only allowed in %<omp ordered%>",
3923 : kind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink");
3924 4 : return false;
3925 : }
3926 42215 : if (is_gimple_omp_offloaded (stmt)
3927 42215 : && oacc_get_fn_attrib (cfun->decl) != NULL)
3928 : {
3929 4 : error_at (gimple_location (stmt),
3930 : "OpenACC region inside of OpenACC routine, nested "
3931 : "parallelism not supported yet");
3932 4 : return false;
3933 : }
3934 49625 : for (; ctx != NULL; ctx = ctx->outer)
3935 : {
3936 7820 : if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3937 : {
3938 768 : if (is_gimple_omp (stmt)
3939 768 : && is_gimple_omp_oacc (stmt)
3940 242 : && is_gimple_omp (ctx->stmt))
3941 : {
3942 242 : error_at (gimple_location (stmt),
3943 : "OpenACC construct inside of non-OpenACC region");
3944 242 : return false;
3945 : }
3946 526 : continue;
3947 : }
3948 :
3949 7052 : const char *stmt_name, *ctx_stmt_name;
3950 7052 : switch (gimple_omp_target_kind (stmt))
3951 : {
3952 : case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3953 399 : case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3954 1688 : case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3955 12 : case GF_OMP_TARGET_KIND_ENTER_DATA:
3956 12 : stmt_name = "target enter data"; break;
3957 18 : case GF_OMP_TARGET_KIND_EXIT_DATA:
3958 18 : stmt_name = "target exit data"; break;
3959 1442 : case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3960 1621 : case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3961 183 : case GF_OMP_TARGET_KIND_OACC_SERIAL: stmt_name = "serial"; break;
3962 386 : case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3963 256 : case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3964 94 : case GF_OMP_TARGET_KIND_OACC_ENTER_DATA:
3965 94 : stmt_name = "enter data"; break;
3966 86 : case GF_OMP_TARGET_KIND_OACC_EXIT_DATA:
3967 86 : stmt_name = "exit data"; break;
3968 64 : case GF_OMP_TARGET_KIND_OACC_DECLARE: stmt_name = "declare"; break;
3969 128 : case GF_OMP_TARGET_KIND_OACC_HOST_DATA: stmt_name = "host_data";
3970 128 : break;
3971 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
3972 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
3973 : case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
3974 : /* OpenACC 'kernels' decomposed parts. */
3975 1621 : stmt_name = "kernels"; break;
3976 0 : default: gcc_unreachable ();
3977 : }
3978 7052 : switch (gimple_omp_target_kind (ctx->stmt))
3979 : {
3980 : case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3981 2712 : case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3982 35 : case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3983 35 : ctx_stmt_name = "parallel"; break;
3984 : case GF_OMP_TARGET_KIND_OACC_KERNELS:
3985 1037 : ctx_stmt_name = "kernels"; break;
3986 35 : case GF_OMP_TARGET_KIND_OACC_SERIAL:
3987 35 : ctx_stmt_name = "serial"; break;
3988 3117 : case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3989 8 : case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
3990 8 : ctx_stmt_name = "host_data"; break;
3991 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
3992 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
3993 : case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
3994 : /* OpenACC 'kernels' decomposed parts. */
3995 1037 : ctx_stmt_name = "kernels"; break;
3996 0 : default: gcc_unreachable ();
3997 : }
3998 :
3999 : /* OpenACC/OpenMP mismatch? */
4000 14104 : if (is_gimple_omp_oacc (stmt)
4001 7052 : != is_gimple_omp_oacc (ctx->stmt))
4002 : {
4003 56 : error_at (gimple_location (stmt),
4004 : "%s %qs construct inside of %s %qs region",
4005 : (is_gimple_omp_oacc (stmt)
4006 : ? "OpenACC" : "OpenMP"), stmt_name,
4007 : (is_gimple_omp_oacc (ctx->stmt)
4008 : ? "OpenACC" : "OpenMP"), ctx_stmt_name);
4009 28 : return false;
4010 : }
4011 7024 : if (is_gimple_omp_offloaded (ctx->stmt))
4012 : {
4013 : /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
4014 185 : if (is_gimple_omp_oacc (ctx->stmt))
4015 : {
4016 105 : error_at (gimple_location (stmt),
4017 : "%qs construct inside of %qs region",
4018 : stmt_name, ctx_stmt_name);
4019 105 : return false;
4020 : }
4021 : else
4022 : {
4023 80 : if ((gimple_omp_target_kind (ctx->stmt)
4024 : == GF_OMP_TARGET_KIND_REGION)
4025 80 : && (gimple_omp_target_kind (stmt)
4026 : == GF_OMP_TARGET_KIND_REGION))
4027 : {
4028 58 : c = omp_find_clause (gimple_omp_target_clauses (stmt),
4029 : OMP_CLAUSE_DEVICE);
4030 58 : if (c && OMP_CLAUSE_DEVICE_ANCESTOR (c))
4031 : break;
4032 : }
4033 49 : warning_at (gimple_location (stmt), OPT_Wopenmp,
4034 : "%qs construct inside of %qs region",
4035 : stmt_name, ctx_stmt_name);
4036 : }
4037 : }
4038 : }
4039 : break;
4040 : default:
4041 : break;
4042 : }
4043 : return true;
4044 : }
4045 :
4046 :
4047 : /* Helper function scan_omp.
4048 :
4049 : Callback for walk_tree or operators in walk_gimple_stmt used to
4050 : scan for OMP directives in TP. */
4051 :
4052 : static tree
4053 9800862 : scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
4054 : {
4055 9800862 : struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
4056 9800862 : omp_context *ctx = (omp_context *) wi->info;
4057 9800862 : tree t = *tp;
4058 9800862 : tree tmp;
4059 :
4060 9800862 : switch (TREE_CODE (t))
4061 : {
4062 4148086 : case VAR_DECL:
4063 4148086 : case PARM_DECL:
4064 4148086 : case LABEL_DECL:
4065 4148086 : case RESULT_DECL:
4066 4148086 : if (ctx)
4067 : {
4068 2124189 : tmp = NULL_TREE;
4069 2124189 : if (TREE_CODE (t) == VAR_DECL
4070 3806649 : && (tmp = lookup_attribute ("omp allocate var",
4071 1682460 : DECL_ATTRIBUTES (t))) != NULL_TREE)
4072 61 : t = TREE_VALUE (TREE_VALUE (tmp));
4073 2124189 : tree repl = remap_decl (t, &ctx->cb);
4074 2124189 : gcc_checking_assert (TREE_CODE (repl) != ERROR_MARK);
4075 2124189 : if (tmp != NULL_TREE && t != repl)
4076 31 : *tp = build_fold_addr_expr (repl);
4077 2124158 : else if (tmp == NULL_TREE)
4078 2124128 : *tp = repl;
4079 : }
4080 : break;
4081 :
4082 192793 : case INDIRECT_REF:
4083 192793 : case MEM_REF:
4084 192793 : if (ctx
4085 77636 : && TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL
4086 251760 : && ((tmp = lookup_attribute ("omp allocate var",
4087 58967 : DECL_ATTRIBUTES (TREE_OPERAND (t, 0))))
4088 : != NULL_TREE))
4089 : {
4090 127 : tmp = TREE_VALUE (TREE_VALUE (tmp));
4091 127 : tree repl = remap_decl (tmp, &ctx->cb);
4092 127 : gcc_checking_assert (TREE_CODE (repl) != ERROR_MARK);
4093 127 : if (tmp != repl)
4094 118 : *tp = repl;
4095 : break;
4096 : }
4097 5652649 : gcc_fallthrough ();
4098 :
4099 5652649 : default:
4100 5652649 : if (ctx && TYPE_P (t))
4101 5 : *tp = remap_type (t, &ctx->cb);
4102 5652644 : else if (!DECL_P (t))
4103 : {
4104 4689245 : *walk_subtrees = 1;
4105 4689245 : if (ctx)
4106 : {
4107 1424797 : tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
4108 1424797 : if (tem != TREE_TYPE (t))
4109 : {
4110 9814 : if (TREE_CODE (t) == INTEGER_CST)
4111 4136 : *tp = wide_int_to_tree (tem, wi::to_wide (t));
4112 : else
4113 5678 : TREE_TYPE (t) = tem;
4114 : }
4115 : }
4116 : }
4117 : break;
4118 : }
4119 :
4120 9800862 : return NULL_TREE;
4121 : }
4122 :
4123 : /* Return true if FNDECL is a setjmp or a longjmp. */
4124 :
4125 : static bool
4126 3042 : setjmp_or_longjmp_p (const_tree fndecl)
4127 : {
4128 3042 : if (fndecl_built_in_p (fndecl, BUILT_IN_SETJMP, BUILT_IN_LONGJMP))
4129 : return true;
4130 :
4131 3042 : tree declname = DECL_NAME (fndecl);
4132 3042 : if (!declname
4133 3042 : || (DECL_CONTEXT (fndecl) != NULL_TREE
4134 2347 : && TREE_CODE (DECL_CONTEXT (fndecl)) != TRANSLATION_UNIT_DECL)
4135 5833 : || !TREE_PUBLIC (fndecl))
4136 : return false;
4137 :
4138 2629 : const char *name = IDENTIFIER_POINTER (declname);
4139 2629 : return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
4140 : }
4141 :
4142 : /* Helper function for scan_omp.
4143 :
4144 : Callback for walk_gimple_stmt used to scan for OMP directives in
4145 : the current statement in GSI. */
4146 :
4147 : static tree
4148 3404667 : scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
4149 : struct walk_stmt_info *wi)
4150 : {
4151 3404667 : gimple *stmt = gsi_stmt (*gsi);
4152 3404667 : omp_context *ctx = (omp_context *) wi->info;
4153 :
4154 3404667 : if (gimple_has_location (stmt))
4155 2778954 : input_location = gimple_location (stmt);
4156 :
4157 : /* Check the nesting restrictions. */
4158 3404667 : bool remove = false;
4159 3404667 : if (is_gimple_omp (stmt))
4160 152580 : remove = !check_omp_nesting_restrictions (stmt, ctx);
4161 3252087 : else if (is_gimple_call (stmt))
4162 : {
4163 230986 : tree fndecl = gimple_call_fndecl (stmt);
4164 230986 : if (fndecl)
4165 : {
4166 215158 : if (ctx
4167 67514 : && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4168 14457 : && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD
4169 3042 : && setjmp_or_longjmp_p (fndecl)
4170 215166 : && !ctx->loop_p)
4171 : {
4172 4 : remove = true;
4173 4 : error_at (gimple_location (stmt),
4174 : "setjmp/longjmp inside %<simd%> construct");
4175 : }
4176 215154 : else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
4177 63290 : switch (DECL_FUNCTION_CODE (fndecl))
4178 : {
4179 4119 : case BUILT_IN_GOMP_BARRIER:
4180 4119 : case BUILT_IN_GOMP_CANCEL:
4181 4119 : case BUILT_IN_GOMP_CANCELLATION_POINT:
4182 4119 : case BUILT_IN_GOMP_TASKYIELD:
4183 4119 : case BUILT_IN_GOMP_TASKWAIT:
4184 4119 : case BUILT_IN_GOMP_TASKGROUP_START:
4185 4119 : case BUILT_IN_GOMP_TASKGROUP_END:
4186 4119 : remove = !check_omp_nesting_restrictions (stmt, ctx);
4187 4119 : break;
4188 : default:
4189 : break;
4190 : }
4191 151864 : else if (ctx)
4192 : {
4193 45659 : omp_context *octx = ctx;
4194 45659 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_SCAN && ctx->outer)
4195 45659 : octx = ctx->outer;
4196 45659 : if (octx->order_concurrent && omp_runtime_api_call (fndecl))
4197 : {
4198 240 : remove = true;
4199 240 : error_at (gimple_location (stmt),
4200 : "OpenMP runtime API call %qD in a region with "
4201 : "%<order(concurrent)%> clause", fndecl);
4202 : }
4203 45659 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS
4204 3337 : && omp_runtime_api_call (fndecl)
4205 339 : && ((IDENTIFIER_LENGTH (DECL_NAME (fndecl))
4206 : != strlen ("omp_get_num_teams"))
4207 185 : || strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)),
4208 : "omp_get_num_teams") != 0)
4209 169 : && ((IDENTIFIER_LENGTH (DECL_NAME (fndecl))
4210 : != strlen ("omp_get_num_teams_dim"))
4211 6 : || strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)),
4212 : "omp_get_num_teams_dim") != 0)
4213 163 : && ((IDENTIFIER_LENGTH (DECL_NAME (fndecl))
4214 : != strlen ("omp_get_team_num"))
4215 124 : || strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)),
4216 : "omp_get_team_num") != 0)
4217 45698 : && ((IDENTIFIER_LENGTH (DECL_NAME (fndecl))
4218 : != strlen ("omp_get_team_num_dim"))
4219 12 : || strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)),
4220 : "omp_get_team_num_dim") != 0))
4221 : {
4222 27 : remove = true;
4223 27 : error_at (gimple_location (stmt),
4224 : "OpenMP runtime API call %qD strictly nested in a "
4225 : "%<teams%> region", fndecl);
4226 : }
4227 45659 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
4228 13340 : && (gimple_omp_target_kind (ctx->stmt)
4229 : == GF_OMP_TARGET_KIND_REGION)
4230 50613 : && omp_runtime_api_call (fndecl))
4231 : {
4232 379 : tree tgt_clauses = gimple_omp_target_clauses (ctx->stmt);
4233 379 : tree c = omp_find_clause (tgt_clauses, OMP_CLAUSE_DEVICE);
4234 379 : if (c && OMP_CLAUSE_DEVICE_ANCESTOR (c))
4235 5 : error_at (gimple_location (stmt),
4236 : "OpenMP runtime API call %qD in a region with "
4237 : "%<device(ancestor)%> clause", fndecl);
4238 : }
4239 : }
4240 : }
4241 : }
4242 202362 : if (remove)
4243 : {
4244 3326 : stmt = gimple_build_nop ();
4245 3326 : gsi_replace (gsi, stmt, false);
4246 : }
4247 :
4248 3404667 : *handled_ops_p = true;
4249 :
4250 3404667 : switch (gimple_code (stmt))
4251 : {
4252 18168 : case GIMPLE_OMP_PARALLEL:
4253 18168 : taskreg_nesting_level++;
4254 18168 : scan_omp_parallel (gsi, ctx);
4255 18168 : taskreg_nesting_level--;
4256 18168 : break;
4257 :
4258 5344 : case GIMPLE_OMP_TASK:
4259 5344 : taskreg_nesting_level++;
4260 5344 : scan_omp_task (gsi, ctx);
4261 5344 : taskreg_nesting_level--;
4262 5344 : break;
4263 :
4264 52695 : case GIMPLE_OMP_FOR:
4265 52695 : if ((gimple_omp_for_kind (as_a <gomp_for *> (stmt))
4266 : == GF_OMP_FOR_KIND_SIMD)
4267 10810 : && gimple_omp_for_combined_into_p (stmt)
4268 60387 : && gimple_code (ctx->stmt) != GIMPLE_OMP_SCAN)
4269 : {
4270 7526 : tree clauses = gimple_omp_for_clauses (as_a <gomp_for *> (stmt));
4271 7526 : tree c = omp_find_clause (clauses, OMP_CLAUSE_REDUCTION);
4272 7526 : if (c && OMP_CLAUSE_REDUCTION_INSCAN (c) && !seen_error ())
4273 : {
4274 83 : scan_omp_simd_scan (gsi, as_a <gomp_for *> (stmt), ctx);
4275 83 : break;
4276 : }
4277 : }
4278 52612 : if ((gimple_omp_for_kind (as_a <gomp_for *> (stmt))
4279 : == GF_OMP_FOR_KIND_SIMD)
4280 10727 : && omp_maybe_offloaded_ctx (ctx)
4281 3641 : && omp_max_simt_vf ()
4282 52612 : && gimple_omp_for_collapse (stmt) == 1)
4283 0 : scan_omp_simd (gsi, as_a <gomp_for *> (stmt), ctx);
4284 : else
4285 52612 : scan_omp_for (as_a <gomp_for *> (stmt), ctx);
4286 : break;
4287 :
4288 196 : case GIMPLE_OMP_SCOPE:
4289 196 : ctx = new_omp_context (stmt, ctx);
4290 196 : scan_sharing_clauses (gimple_omp_scope_clauses (stmt), ctx);
4291 196 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
4292 196 : break;
4293 :
4294 852 : case GIMPLE_OMP_DISPATCH:
4295 852 : ctx = new_omp_context (stmt, ctx);
4296 852 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
4297 852 : break;
4298 :
4299 612 : case GIMPLE_OMP_INTEROP:
4300 612 : ctx = new_omp_context (stmt, ctx);
4301 612 : break;
4302 :
4303 589 : case GIMPLE_OMP_SECTIONS:
4304 589 : scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
4305 589 : break;
4306 :
4307 1236 : case GIMPLE_OMP_SINGLE:
4308 1236 : scan_omp_single (as_a <gomp_single *> (stmt), ctx);
4309 1236 : break;
4310 :
4311 1292 : case GIMPLE_OMP_SCAN:
4312 1292 : if (tree clauses = gimple_omp_scan_clauses (as_a <gomp_scan *> (stmt)))
4313 : {
4314 610 : if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_INCLUSIVE)
4315 308 : ctx->scan_inclusive = true;
4316 302 : else if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_EXCLUSIVE)
4317 302 : ctx->scan_exclusive = true;
4318 : }
4319 : /* FALLTHRU */
4320 6223 : case GIMPLE_OMP_SECTION:
4321 6223 : case GIMPLE_OMP_STRUCTURED_BLOCK:
4322 6223 : case GIMPLE_OMP_MASTER:
4323 6223 : case GIMPLE_OMP_ORDERED:
4324 6223 : case GIMPLE_OMP_CRITICAL:
4325 6223 : ctx = new_omp_context (stmt, ctx);
4326 6223 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
4327 6223 : break;
4328 :
4329 457 : case GIMPLE_OMP_MASKED:
4330 457 : ctx = new_omp_context (stmt, ctx);
4331 457 : scan_sharing_clauses (gimple_omp_masked_clauses (stmt), ctx);
4332 457 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
4333 457 : break;
4334 :
4335 607 : case GIMPLE_OMP_TASKGROUP:
4336 607 : ctx = new_omp_context (stmt, ctx);
4337 607 : scan_sharing_clauses (gimple_omp_taskgroup_clauses (stmt), ctx);
4338 607 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
4339 607 : break;
4340 :
4341 41836 : case GIMPLE_OMP_TARGET:
4342 41836 : if (is_gimple_omp_offloaded (stmt))
4343 : {
4344 24807 : taskreg_nesting_level++;
4345 24807 : scan_omp_target (as_a <gomp_target *> (stmt), ctx);
4346 24807 : taskreg_nesting_level--;
4347 : }
4348 : else
4349 17029 : scan_omp_target (as_a <gomp_target *> (stmt), ctx);
4350 : break;
4351 :
4352 8761 : case GIMPLE_OMP_TEAMS:
4353 8761 : if (gimple_omp_teams_host (as_a <gomp_teams *> (stmt)))
4354 : {
4355 2640 : taskreg_nesting_level++;
4356 2640 : scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
4357 2640 : taskreg_nesting_level--;
4358 : }
4359 : else
4360 6121 : scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
4361 : break;
4362 :
4363 281271 : case GIMPLE_BIND:
4364 281271 : {
4365 281271 : tree var;
4366 :
4367 281271 : *handled_ops_p = false;
4368 281271 : if (ctx)
4369 152322 : for (var = gimple_bind_vars (as_a <gbind *> (stmt));
4370 578133 : var ;
4371 425811 : var = DECL_CHAIN (var))
4372 425811 : insert_decl_map (&ctx->cb, var, var);
4373 : }
4374 : break;
4375 2985820 : default:
4376 2985820 : *handled_ops_p = false;
4377 2985820 : break;
4378 : }
4379 :
4380 3404667 : return NULL_TREE;
4381 : }
4382 :
4383 :
4384 : /* Scan all the statements starting at the current statement. CTX
4385 : contains context information about the OMP directives and
4386 : clauses found during the scan. */
4387 :
4388 : static void
4389 258541 : scan_omp (gimple_seq *body_p, omp_context *ctx)
4390 : {
4391 258541 : location_t saved_location;
4392 258541 : struct walk_stmt_info wi;
4393 :
4394 258541 : memset (&wi, 0, sizeof (wi));
4395 258541 : wi.info = ctx;
4396 258541 : wi.want_locations = true;
4397 :
4398 258541 : saved_location = input_location;
4399 258541 : walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
4400 258541 : input_location = saved_location;
4401 258541 : }
4402 :
4403 : /* Re-gimplification and code generation routines. */
4404 :
4405 : /* Remove omp_member_access_dummy_var variables from gimple_bind_vars
4406 : of BIND if in a method. */
4407 :
4408 : static void
4409 258383 : maybe_remove_omp_member_access_dummy_vars (gbind *bind)
4410 : {
4411 258383 : if (DECL_ARGUMENTS (current_function_decl)
4412 97552 : && DECL_ARTIFICIAL (DECL_ARGUMENTS (current_function_decl))
4413 269133 : && (TREE_CODE (TREE_TYPE (DECL_ARGUMENTS (current_function_decl)))
4414 : == POINTER_TYPE))
4415 : {
4416 3520 : tree vars = gimple_bind_vars (bind);
4417 19340 : for (tree *pvar = &vars; *pvar; )
4418 15820 : if (omp_member_access_dummy_var (*pvar))
4419 719 : *pvar = DECL_CHAIN (*pvar);
4420 : else
4421 15101 : pvar = &DECL_CHAIN (*pvar);
4422 3520 : gimple_bind_set_vars (bind, vars);
4423 : }
4424 258383 : }
4425 :
4426 : /* Remove omp_member_access_dummy_var variables from BLOCK_VARS of
4427 : block and its subblocks. */
4428 :
4429 : static void
4430 12852 : remove_member_access_dummy_vars (tree block)
4431 : {
4432 22413 : for (tree *pvar = &BLOCK_VARS (block); *pvar; )
4433 9561 : if (omp_member_access_dummy_var (*pvar))
4434 108 : *pvar = DECL_CHAIN (*pvar);
4435 : else
4436 9453 : pvar = &DECL_CHAIN (*pvar);
4437 :
4438 16737 : for (block = BLOCK_SUBBLOCKS (block); block; block = BLOCK_CHAIN (block))
4439 3885 : remove_member_access_dummy_vars (block);
4440 12852 : }
4441 :
4442 : /* If a context was created for STMT when it was scanned, return it. */
4443 :
4444 : static omp_context *
4445 121281 : maybe_lookup_ctx (gimple *stmt)
4446 : {
4447 121281 : splay_tree_node n;
4448 121281 : n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
4449 121281 : return n ? (omp_context *) n->value : NULL;
4450 : }
4451 :
4452 :
4453 : /* Find the mapping for DECL in CTX or the immediately enclosing
4454 : context that has a mapping for DECL.
4455 :
4456 : If CTX is a nested parallel directive, we may have to use the decl
4457 : mappings created in CTX's parent context. Suppose that we have the
4458 : following parallel nesting (variable UIDs showed for clarity):
4459 :
4460 : iD.1562 = 0;
4461 : #omp parallel shared(iD.1562) -> outer parallel
4462 : iD.1562 = iD.1562 + 1;
4463 :
4464 : #omp parallel shared (iD.1562) -> inner parallel
4465 : iD.1562 = iD.1562 - 1;
4466 :
4467 : Each parallel structure will create a distinct .omp_data_s structure
4468 : for copying iD.1562 in/out of the directive:
4469 :
4470 : outer parallel .omp_data_s.1.i -> iD.1562
4471 : inner parallel .omp_data_s.2.i -> iD.1562
4472 :
4473 : A shared variable mapping will produce a copy-out operation before
4474 : the parallel directive and a copy-in operation after it. So, in
4475 : this case we would have:
4476 :
4477 : iD.1562 = 0;
4478 : .omp_data_o.1.i = iD.1562;
4479 : #omp parallel shared(iD.1562) -> outer parallel
4480 : .omp_data_i.1 = &.omp_data_o.1
4481 : .omp_data_i.1->i = .omp_data_i.1->i + 1;
4482 :
4483 : .omp_data_o.2.i = iD.1562; -> **
4484 : #omp parallel shared(iD.1562) -> inner parallel
4485 : .omp_data_i.2 = &.omp_data_o.2
4486 : .omp_data_i.2->i = .omp_data_i.2->i - 1;
4487 :
4488 :
4489 : ** This is a problem. The symbol iD.1562 cannot be referenced
4490 : inside the body of the outer parallel region. But since we are
4491 : emitting this copy operation while expanding the inner parallel
4492 : directive, we need to access the CTX structure of the outer
4493 : parallel directive to get the correct mapping:
4494 :
4495 : .omp_data_o.2.i = .omp_data_i.1->i
4496 :
4497 : Since there may be other workshare or parallel directives enclosing
4498 : the parallel directive, it may be necessary to walk up the context
4499 : parent chain. This is not a problem in general because nested
4500 : parallelism happens only rarely. */
4501 :
4502 : static tree
4503 126033 : lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4504 : {
4505 126033 : tree t;
4506 126033 : omp_context *up;
4507 :
4508 182685 : for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4509 56652 : t = maybe_lookup_decl (decl, up);
4510 :
4511 126033 : gcc_assert (!ctx->is_nested || t || is_global_var (decl));
4512 :
4513 97784 : return t ? t : decl;
4514 : }
4515 :
4516 :
4517 : /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
4518 : in outer contexts. */
4519 :
4520 : static tree
4521 355624 : maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4522 : {
4523 355624 : tree t = NULL;
4524 355624 : omp_context *up;
4525 :
4526 626198 : for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4527 270574 : t = maybe_lookup_decl (decl, up);
4528 :
4529 355624 : return t ? t : decl;
4530 : }
4531 :
4532 :
4533 : /* Construct the initialization value for reduction operation OP. */
4534 :
4535 : tree
4536 13101 : omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
4537 : {
4538 13101 : switch (op)
4539 : {
4540 10766 : case PLUS_EXPR:
4541 10766 : case MINUS_EXPR:
4542 10766 : case BIT_IOR_EXPR:
4543 10766 : case BIT_XOR_EXPR:
4544 10766 : case TRUTH_OR_EXPR:
4545 10766 : case TRUTH_ORIF_EXPR:
4546 10766 : case TRUTH_XOR_EXPR:
4547 10766 : case NE_EXPR:
4548 10766 : return build_zero_cst (type);
4549 :
4550 1431 : case MULT_EXPR:
4551 1431 : case TRUTH_AND_EXPR:
4552 1431 : case TRUTH_ANDIF_EXPR:
4553 1431 : case EQ_EXPR:
4554 1431 : return fold_convert_loc (loc, type, integer_one_node);
4555 :
4556 208 : case BIT_AND_EXPR:
4557 208 : return fold_convert_loc (loc, type, integer_minus_one_node);
4558 :
4559 388 : case MAX_EXPR:
4560 388 : if (SCALAR_FLOAT_TYPE_P (type))
4561 : {
4562 158 : REAL_VALUE_TYPE min;
4563 158 : if (HONOR_INFINITIES (type))
4564 158 : real_arithmetic (&min, NEGATE_EXPR, &dconstinf, NULL);
4565 : else
4566 0 : real_maxval (&min, 1, TYPE_MODE (type));
4567 158 : return build_real (type, min);
4568 : }
4569 230 : else if (POINTER_TYPE_P (type))
4570 : {
4571 2 : wide_int min
4572 2 : = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4573 2 : return wide_int_to_tree (type, min);
4574 2 : }
4575 : else
4576 : {
4577 228 : gcc_assert (INTEGRAL_TYPE_P (type));
4578 228 : return TYPE_MIN_VALUE (type);
4579 : }
4580 :
4581 308 : case MIN_EXPR:
4582 308 : if (SCALAR_FLOAT_TYPE_P (type))
4583 : {
4584 108 : REAL_VALUE_TYPE max;
4585 108 : if (HONOR_INFINITIES (type))
4586 108 : max = dconstinf;
4587 : else
4588 0 : real_maxval (&max, 0, TYPE_MODE (type));
4589 108 : return build_real (type, max);
4590 : }
4591 200 : else if (POINTER_TYPE_P (type))
4592 : {
4593 2 : wide_int max
4594 2 : = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4595 2 : return wide_int_to_tree (type, max);
4596 2 : }
4597 : else
4598 : {
4599 198 : gcc_assert (INTEGRAL_TYPE_P (type));
4600 198 : return TYPE_MAX_VALUE (type);
4601 : }
4602 :
4603 0 : default:
4604 0 : gcc_unreachable ();
4605 : }
4606 : }
4607 :
4608 : /* Construct the initialization value for reduction CLAUSE. */
4609 :
4610 : tree
4611 10480 : omp_reduction_init (tree clause, tree type)
4612 : {
4613 10480 : return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4614 10480 : OMP_CLAUSE_REDUCTION_CODE (clause), type);
4615 : }
4616 :
4617 : /* Return alignment to be assumed for var in CLAUSE, which should be
4618 : OMP_CLAUSE_ALIGNED. */
4619 :
4620 : static tree
4621 140 : omp_clause_aligned_alignment (tree clause)
4622 : {
4623 140 : if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4624 123 : return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4625 :
4626 : /* Otherwise return implementation defined alignment. */
4627 17 : unsigned int al = 1;
4628 17 : opt_scalar_mode mode_iter;
4629 17 : auto_vector_modes modes;
4630 17 : targetm.vectorize.autovectorize_vector_modes (&modes, true);
4631 17 : static enum mode_class classes[]
4632 : = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4633 51 : for (int i = 0; i < 4; i += 2)
4634 : /* The for loop above dictates that we only walk through scalar classes. */
4635 255 : FOR_EACH_MODE_IN_CLASS (mode_iter, classes[i])
4636 : {
4637 221 : scalar_mode mode = mode_iter.require ();
4638 221 : machine_mode vmode = targetm.vectorize.preferred_simd_mode (mode);
4639 221 : if (GET_MODE_CLASS (vmode) != classes[i + 1])
4640 323 : continue;
4641 : machine_mode alt_vmode;
4642 476 : for (unsigned int j = 0; j < modes.length (); ++j)
4643 527 : if (related_vector_mode (modes[j], mode).exists (&alt_vmode)
4644 578 : && known_ge (GET_MODE_SIZE (alt_vmode), GET_MODE_SIZE (vmode)))
4645 119 : vmode = alt_vmode;
4646 :
4647 119 : tree type = lang_hooks.types.type_for_mode (mode, 1);
4648 119 : if (type == NULL_TREE || TYPE_MODE (type) != mode)
4649 17 : continue;
4650 102 : type = build_vector_type_for_mode (type, vmode);
4651 102 : if (TYPE_MODE (type) != vmode)
4652 0 : continue;
4653 102 : if (TYPE_ALIGN_UNIT (type) > al)
4654 17 : al = TYPE_ALIGN_UNIT (type);
4655 : }
4656 17 : return build_int_cst (integer_type_node, al);
4657 17 : }
4658 :
4659 :
4660 : /* This structure is part of the interface between lower_rec_simd_input_clauses
4661 : and lower_rec_input_clauses. */
4662 :
4663 : class omplow_simd_context {
4664 : public:
4665 77138 : omplow_simd_context () { memset (this, 0, sizeof (*this)); }
4666 : tree idx;
4667 : tree lane;
4668 : tree lastlane;
4669 : vec<tree, va_heap> simt_eargs;
4670 : gimple_seq simt_dlist;
4671 : poly_uint64 max_vf;
4672 : bool is_simt;
4673 : };
4674 :
4675 : /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4676 : privatization. */
4677 :
4678 : static bool
4679 10228 : lower_rec_simd_input_clauses (tree new_var, omp_context *ctx,
4680 : omplow_simd_context *sctx, tree &ivar,
4681 : tree &lvar, tree *rvar = NULL,
4682 : tree *rvar2 = NULL)
4683 : {
4684 10228 : if (known_eq (sctx->max_vf, 0U))
4685 : {
4686 4790 : sctx->max_vf = (sctx->is_simt ? omp_max_simt_vf ()
4687 4790 : : omp_max_vf (omp_maybe_offloaded_ctx (ctx)));
4688 4790 : if (maybe_gt (sctx->max_vf, 1U))
4689 : {
4690 3452 : tree c = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
4691 : OMP_CLAUSE_SAFELEN);
4692 3452 : if (c)
4693 : {
4694 89 : poly_uint64 safe_len;
4695 89 : if (!poly_int_tree_p (OMP_CLAUSE_SAFELEN_EXPR (c), &safe_len)
4696 89 : || maybe_lt (safe_len, 1U))
4697 6 : sctx->max_vf = 1;
4698 : else
4699 83 : sctx->max_vf = lower_bound (sctx->max_vf, safe_len);
4700 : }
4701 : }
4702 4790 : if (sctx->is_simt && !known_eq (sctx->max_vf, 1U))
4703 : {
4704 0 : for (tree c = gimple_omp_for_clauses (ctx->stmt); c;
4705 0 : c = OMP_CLAUSE_CHAIN (c))
4706 : {
4707 0 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4708 0 : continue;
4709 :
4710 0 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4711 : {
4712 : /* UDR reductions are not supported yet for SIMT, disable
4713 : SIMT. */
4714 0 : sctx->max_vf = 1;
4715 0 : break;
4716 : }
4717 :
4718 0 : if (truth_value_p (OMP_CLAUSE_REDUCTION_CODE (c))
4719 0 : && !INTEGRAL_TYPE_P (TREE_TYPE (new_var)))
4720 : {
4721 : /* Doing boolean operations on non-integral types is
4722 : for conformance only, it's not worth supporting this
4723 : for SIMT. */
4724 0 : sctx->max_vf = 1;
4725 0 : break;
4726 : }
4727 : }
4728 : }
4729 4790 : if (maybe_gt (sctx->max_vf, 1U))
4730 : {
4731 3433 : sctx->idx = create_tmp_var (unsigned_type_node);
4732 3433 : sctx->lane = create_tmp_var (unsigned_type_node);
4733 : }
4734 : }
4735 10228 : if (known_eq (sctx->max_vf, 1U))
4736 : return false;
4737 :
4738 7174 : if (sctx->is_simt)
4739 : {
4740 0 : if (is_gimple_reg (new_var))
4741 : {
4742 0 : ivar = lvar = new_var;
4743 0 : return true;
4744 : }
4745 0 : tree type = TREE_TYPE (new_var), ptype = build_pointer_type (type);
4746 0 : ivar = lvar = create_tmp_var (type);
4747 0 : TREE_ADDRESSABLE (ivar) = 1;
4748 0 : DECL_ATTRIBUTES (ivar) = tree_cons (get_identifier ("omp simt private"),
4749 0 : NULL, DECL_ATTRIBUTES (ivar));
4750 0 : sctx->simt_eargs.safe_push (build1 (ADDR_EXPR, ptype, ivar));
4751 0 : tree clobber = build_clobber (type);
4752 0 : gimple *g = gimple_build_assign (ivar, clobber);
4753 0 : gimple_seq_add_stmt (&sctx->simt_dlist, g);
4754 : }
4755 : else
4756 : {
4757 7174 : tree atype = build_array_type_nelts (TREE_TYPE (new_var), sctx->max_vf);
4758 7174 : tree avar = create_tmp_var_raw (atype);
4759 7174 : if (TREE_ADDRESSABLE (new_var))
4760 912 : TREE_ADDRESSABLE (avar) = 1;
4761 7174 : DECL_ATTRIBUTES (avar)
4762 7174 : = tree_cons (get_identifier ("omp simd array"), NULL,
4763 7174 : DECL_ATTRIBUTES (avar));
4764 7174 : gimple_add_tmp_var (avar);
4765 7174 : tree iavar = avar;
4766 7174 : if (rvar && !ctx->for_simd_scan_phase)
4767 : {
4768 : /* For inscan reductions, create another array temporary,
4769 : which will hold the reduced value. */
4770 232 : iavar = create_tmp_var_raw (atype);
4771 232 : if (TREE_ADDRESSABLE (new_var))
4772 33 : TREE_ADDRESSABLE (iavar) = 1;
4773 232 : DECL_ATTRIBUTES (iavar)
4774 232 : = tree_cons (get_identifier ("omp simd array"), NULL,
4775 : tree_cons (get_identifier ("omp simd inscan"), NULL,
4776 232 : DECL_ATTRIBUTES (iavar)));
4777 232 : gimple_add_tmp_var (iavar);
4778 232 : ctx->cb.decl_map->put (avar, iavar);
4779 232 : if (sctx->lastlane == NULL_TREE)
4780 184 : sctx->lastlane = create_tmp_var (unsigned_type_node);
4781 232 : *rvar = build4 (ARRAY_REF, TREE_TYPE (new_var), iavar,
4782 : sctx->lastlane, NULL_TREE, NULL_TREE);
4783 232 : TREE_THIS_NOTRAP (*rvar) = 1;
4784 :
4785 232 : if (ctx->scan_exclusive)
4786 : {
4787 : /* And for exclusive scan yet another one, which will
4788 : hold the value during the scan phase. */
4789 114 : tree savar = create_tmp_var_raw (atype);
4790 114 : if (TREE_ADDRESSABLE (new_var))
4791 17 : TREE_ADDRESSABLE (savar) = 1;
4792 114 : DECL_ATTRIBUTES (savar)
4793 114 : = tree_cons (get_identifier ("omp simd array"), NULL,
4794 : tree_cons (get_identifier ("omp simd inscan "
4795 : "exclusive"), NULL,
4796 114 : DECL_ATTRIBUTES (savar)));
4797 114 : gimple_add_tmp_var (savar);
4798 114 : ctx->cb.decl_map->put (iavar, savar);
4799 114 : *rvar2 = build4 (ARRAY_REF, TREE_TYPE (new_var), savar,
4800 : sctx->idx, NULL_TREE, NULL_TREE);
4801 114 : TREE_THIS_NOTRAP (*rvar2) = 1;
4802 : }
4803 : }
4804 7174 : ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), iavar, sctx->idx,
4805 : NULL_TREE, NULL_TREE);
4806 7174 : lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, sctx->lane,
4807 : NULL_TREE, NULL_TREE);
4808 7174 : TREE_THIS_NOTRAP (ivar) = 1;
4809 7174 : TREE_THIS_NOTRAP (lvar) = 1;
4810 : }
4811 7174 : if (DECL_P (new_var))
4812 : {
4813 7020 : SET_DECL_VALUE_EXPR (new_var, lvar);
4814 7020 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4815 : }
4816 : return true;
4817 : }
4818 :
4819 : /* Helper function of lower_rec_input_clauses. For a reference
4820 : in simd reduction, add an underlying variable it will reference. */
4821 :
4822 : static void
4823 64 : handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4824 : {
4825 64 : tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4826 64 : if (TREE_CONSTANT (z))
4827 : {
4828 64 : z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4829 : get_name (new_vard));
4830 64 : gimple_add_tmp_var (z);
4831 64 : TREE_ADDRESSABLE (z) = 1;
4832 64 : z = build_fold_addr_expr_loc (loc, z);
4833 64 : gimplify_assign (new_vard, z, ilist);
4834 : }
4835 64 : }
4836 :
4837 : /* Helper function for lower_rec_input_clauses. Emit into ilist sequence
4838 : code to emit (type) (tskred_temp[idx]). */
4839 :
4840 : static tree
4841 1120 : task_reduction_read (gimple_seq *ilist, tree tskred_temp, tree type,
4842 : unsigned idx)
4843 : {
4844 1120 : unsigned HOST_WIDE_INT sz
4845 1120 : = tree_to_uhwi (TYPE_SIZE_UNIT (pointer_sized_int_node));
4846 1120 : tree r = build2 (MEM_REF, pointer_sized_int_node,
4847 1120 : tskred_temp, build_int_cst (TREE_TYPE (tskred_temp),
4848 1120 : idx * sz));
4849 1120 : tree v = create_tmp_var (pointer_sized_int_node);
4850 1120 : gimple *g = gimple_build_assign (v, r);
4851 1120 : gimple_seq_add_stmt (ilist, g);
4852 1120 : if (!useless_type_conversion_p (type, pointer_sized_int_node))
4853 : {
4854 872 : v = create_tmp_var (type);
4855 872 : g = gimple_build_assign (v, NOP_EXPR, gimple_assign_lhs (g));
4856 872 : gimple_seq_add_stmt (ilist, g);
4857 : }
4858 1120 : return v;
4859 : }
4860 :
4861 : /* Lower early initialization of privatized variable NEW_VAR
4862 : if it needs an allocator (has allocate clause). */
4863 :
4864 : static bool
4865 144318 : lower_private_allocate (tree var, tree new_var, tree &allocator,
4866 : tree &allocate_ptr, gimple_seq *ilist,
4867 : omp_context *ctx, bool is_ref, tree size)
4868 : {
4869 144318 : if (allocator)
4870 : return false;
4871 144266 : gcc_assert (allocate_ptr == NULL_TREE);
4872 144266 : if (ctx->allocate_map
4873 2798 : && (DECL_P (new_var) || (TYPE_P (new_var) && size)))
4874 2795 : if (tree *allocatorp = ctx->allocate_map->get (var))
4875 953 : allocator = *allocatorp;
4876 144266 : if (allocator == NULL_TREE)
4877 : return false;
4878 953 : if (!is_ref && omp_privatize_by_reference (var))
4879 : {
4880 0 : allocator = NULL_TREE;
4881 0 : return false;
4882 : }
4883 :
4884 953 : unsigned HOST_WIDE_INT ialign = 0;
4885 953 : if (TREE_CODE (allocator) == TREE_LIST)
4886 : {
4887 248 : ialign = tree_to_uhwi (TREE_VALUE (allocator));
4888 248 : allocator = TREE_PURPOSE (allocator);
4889 : }
4890 953 : if (TREE_CODE (allocator) != INTEGER_CST)
4891 295 : allocator = build_outer_var_ref (allocator, ctx, OMP_CLAUSE_ALLOCATE);
4892 953 : allocator = fold_convert (pointer_sized_int_node, allocator);
4893 953 : if (TREE_CODE (allocator) != INTEGER_CST)
4894 : {
4895 295 : tree var = create_tmp_var (TREE_TYPE (allocator));
4896 295 : gimplify_assign (var, allocator, ilist);
4897 295 : allocator = var;
4898 : }
4899 :
4900 953 : tree ptr_type, align, sz = size;
4901 953 : if (TYPE_P (new_var))
4902 : {
4903 225 : ptr_type = build_pointer_type (new_var);
4904 225 : ialign = MAX (ialign, TYPE_ALIGN_UNIT (new_var));
4905 : }
4906 728 : else if (is_ref)
4907 : {
4908 72 : ptr_type = build_pointer_type (TREE_TYPE (TREE_TYPE (new_var)));
4909 72 : ialign = MAX (ialign, TYPE_ALIGN_UNIT (TREE_TYPE (ptr_type)));
4910 : }
4911 : else
4912 : {
4913 656 : ptr_type = build_pointer_type (TREE_TYPE (new_var));
4914 656 : ialign = MAX (ialign, DECL_ALIGN_UNIT (new_var));
4915 656 : if (sz == NULL_TREE)
4916 558 : sz = fold_convert (size_type_node, DECL_SIZE_UNIT (new_var));
4917 : }
4918 953 : align = build_int_cst (size_type_node, ialign);
4919 953 : if (TREE_CODE (sz) != INTEGER_CST)
4920 : {
4921 42 : tree szvar = create_tmp_var (size_type_node);
4922 42 : gimplify_assign (szvar, sz, ilist);
4923 42 : sz = szvar;
4924 : }
4925 953 : allocate_ptr = create_tmp_var (ptr_type);
4926 953 : tree a = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
4927 953 : gimple *g = gimple_build_call (a, 3, align, sz, allocator);
4928 953 : gimple_call_set_lhs (g, allocate_ptr);
4929 953 : gimple_seq_add_stmt (ilist, g);
4930 953 : if (!is_ref)
4931 : {
4932 656 : tree x = build_simple_mem_ref (allocate_ptr);
4933 656 : TREE_THIS_NOTRAP (x) = 1;
4934 656 : SET_DECL_VALUE_EXPR (new_var, x);
4935 656 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4936 : }
4937 : return true;
4938 : }
4939 :
4940 : /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4941 : from the receiver (aka child) side and initializers for REFERENCE_TYPE
4942 : private variables. Initialization statements go in ILIST, while calls
4943 : to destructors go in DLIST. */
4944 :
4945 : static void
4946 77138 : lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
4947 : omp_context *ctx, struct omp_for_data *fd)
4948 : {
4949 77138 : tree c, copyin_seq, x, ptr;
4950 77138 : bool copyin_by_ref = false;
4951 77138 : bool lastprivate_firstprivate = false;
4952 77138 : bool reduction_omp_orig_ref = false;
4953 77138 : int pass;
4954 77138 : bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4955 77138 : && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD);
4956 77138 : omplow_simd_context sctx = omplow_simd_context ();
4957 77138 : tree simt_lane = NULL_TREE, simtrec = NULL_TREE;
4958 77138 : tree ivar = NULL_TREE, lvar = NULL_TREE, uid = NULL_TREE;
4959 77138 : gimple_seq llist[4] = { };
4960 77138 : tree nonconst_simd_if = NULL_TREE;
4961 :
4962 77138 : copyin_seq = NULL;
4963 77138 : sctx.is_simt = is_simd && omp_find_clause (clauses, OMP_CLAUSE__SIMT_);
4964 :
4965 : /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4966 : with data sharing clauses referencing variable sized vars. That
4967 : is unnecessarily hard to support and very unlikely to result in
4968 : vectorized code anyway. */
4969 9355 : if (is_simd)
4970 61463 : for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4971 52108 : switch (OMP_CLAUSE_CODE (c))
4972 : {
4973 7579 : case OMP_CLAUSE_LINEAR:
4974 7579 : if (OMP_CLAUSE_LINEAR_ARRAY (c))
4975 216 : sctx.max_vf = 1;
4976 : /* FALLTHRU */
4977 25155 : case OMP_CLAUSE_PRIVATE:
4978 25155 : case OMP_CLAUSE_FIRSTPRIVATE:
4979 25155 : case OMP_CLAUSE_LASTPRIVATE:
4980 25155 : if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4981 0 : sctx.max_vf = 1;
4982 25155 : else if (omp_privatize_by_reference (OMP_CLAUSE_DECL (c)))
4983 : {
4984 279 : tree rtype = TREE_TYPE (TREE_TYPE (OMP_CLAUSE_DECL (c)));
4985 279 : if (!TREE_CONSTANT (TYPE_SIZE_UNIT (rtype)))
4986 96 : sctx.max_vf = 1;
4987 : }
4988 : break;
4989 2578 : case OMP_CLAUSE_REDUCTION:
4990 2578 : case OMP_CLAUSE_IN_REDUCTION:
4991 2578 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4992 2578 : || is_variable_sized (OMP_CLAUSE_DECL (c)))
4993 180 : sctx.max_vf = 1;
4994 2398 : else if (omp_privatize_by_reference (OMP_CLAUSE_DECL (c)))
4995 : {
4996 144 : tree rtype = TREE_TYPE (TREE_TYPE (OMP_CLAUSE_DECL (c)));
4997 144 : if (!TREE_CONSTANT (TYPE_SIZE_UNIT (rtype)))
4998 0 : sctx.max_vf = 1;
4999 : }
5000 : break;
5001 759 : case OMP_CLAUSE_IF:
5002 759 : if (integer_zerop (OMP_CLAUSE_IF_EXPR (c)))
5003 124 : sctx.max_vf = 1;
5004 635 : else if (TREE_CODE (OMP_CLAUSE_IF_EXPR (c)) != INTEGER_CST)
5005 625 : nonconst_simd_if = OMP_CLAUSE_IF_EXPR (c);
5006 : break;
5007 626 : case OMP_CLAUSE_SIMDLEN:
5008 626 : if (integer_onep (OMP_CLAUSE_SIMDLEN_EXPR (c)))
5009 110 : sctx.max_vf = 1;
5010 : break;
5011 184 : case OMP_CLAUSE__CONDTEMP_:
5012 : /* FIXME: lastprivate(conditional:) not handled for SIMT yet. */
5013 184 : if (sctx.is_simt)
5014 0 : sctx.max_vf = 1;
5015 : break;
5016 22806 : default:
5017 22806 : continue;
5018 22806 : }
5019 :
5020 : /* Add a placeholder for simduid. */
5021 77138 : if (sctx.is_simt && maybe_ne (sctx.max_vf, 1U))
5022 0 : sctx.simt_eargs.safe_push (NULL_TREE);
5023 :
5024 : unsigned task_reduction_cnt = 0;
5025 : unsigned task_reduction_cntorig = 0;
5026 : unsigned task_reduction_cnt_full = 0;
5027 : unsigned task_reduction_cntorig_full = 0;
5028 : unsigned task_reduction_other_cnt = 0;
5029 234469 : tree tskred_atype = NULL_TREE, tskred_avar = NULL_TREE;
5030 : tree tskred_base = NULL_TREE, tskred_temp = NULL_TREE;
5031 : /* Do all the fixed sized types in the first pass, and the variable sized
5032 : types in the second pass. This makes sure that the scalar arguments to
5033 : the variable sized types are processed before we use them in the
5034 : variable sized operations. For task reductions we use 4 passes, in the
5035 : first two we ignore them, in the third one gather arguments for
5036 : GOMP_task_reduction_remap call and in the last pass actually handle
5037 : the task reductions. */
5038 391800 : for (pass = 0; pass < ((task_reduction_cnt || task_reduction_other_cnt)
5039 234469 : ? 4 : 2); ++pass)
5040 : {
5041 157335 : if (pass == 2 && task_reduction_cnt)
5042 : {
5043 871 : tskred_atype
5044 871 : = build_array_type_nelts (ptr_type_node, task_reduction_cnt
5045 871 : + task_reduction_cntorig);
5046 871 : tskred_avar = create_tmp_var_raw (tskred_atype);
5047 871 : gimple_add_tmp_var (tskred_avar);
5048 871 : TREE_ADDRESSABLE (tskred_avar) = 1;
5049 871 : task_reduction_cnt_full = task_reduction_cnt;
5050 871 : task_reduction_cntorig_full = task_reduction_cntorig;
5051 : }
5052 156464 : else if (pass == 3 && task_reduction_cnt)
5053 : {
5054 871 : x = builtin_decl_explicit (BUILT_IN_GOMP_TASK_REDUCTION_REMAP);
5055 871 : gimple *g
5056 871 : = gimple_build_call (x, 3, size_int (task_reduction_cnt),
5057 871 : size_int (task_reduction_cntorig),
5058 : build_fold_addr_expr (tskred_avar));
5059 871 : gimple_seq_add_stmt (ilist, g);
5060 : }
5061 157335 : if (pass == 3 && task_reduction_other_cnt)
5062 : {
5063 : /* For reduction clauses, build
5064 : tskred_base = (void *) tskred_temp[2]
5065 : + omp_get_thread_num () * tskred_temp[1]
5066 : or if tskred_temp[1] is known to be constant, that constant
5067 : directly. This is the start of the private reduction copy block
5068 : for the current thread. */
5069 838 : tree v = create_tmp_var (integer_type_node);
5070 838 : x = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5071 838 : gimple *g = gimple_build_call (x, 0);
5072 838 : gimple_call_set_lhs (g, v);
5073 838 : gimple_seq_add_stmt (ilist, g);
5074 838 : c = omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_);
5075 838 : tskred_temp = OMP_CLAUSE_DECL (c);
5076 838 : if (is_taskreg_ctx (ctx))
5077 557 : tskred_temp = lookup_decl (tskred_temp, ctx);
5078 838 : tree v2 = create_tmp_var (sizetype);
5079 838 : g = gimple_build_assign (v2, NOP_EXPR, v);
5080 838 : gimple_seq_add_stmt (ilist, g);
5081 838 : if (ctx->task_reductions[0])
5082 821 : v = fold_convert (sizetype, ctx->task_reductions[0]);
5083 : else
5084 17 : v = task_reduction_read (ilist, tskred_temp, sizetype, 1);
5085 838 : tree v3 = create_tmp_var (sizetype);
5086 838 : g = gimple_build_assign (v3, MULT_EXPR, v2, v);
5087 838 : gimple_seq_add_stmt (ilist, g);
5088 838 : v = task_reduction_read (ilist, tskred_temp, ptr_type_node, 2);
5089 838 : tskred_base = create_tmp_var (ptr_type_node);
5090 838 : g = gimple_build_assign (tskred_base, POINTER_PLUS_EXPR, v, v3);
5091 838 : gimple_seq_add_stmt (ilist, g);
5092 : }
5093 157335 : task_reduction_cnt = 0;
5094 157335 : task_reduction_cntorig = 0;
5095 157335 : task_reduction_other_cnt = 0;
5096 760130 : for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5097 : {
5098 602799 : enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
5099 602799 : tree var, new_var;
5100 602799 : bool by_ref;
5101 602799 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5102 602799 : bool task_reduction_p = false;
5103 602799 : bool task_reduction_needs_orig_p = false;
5104 602799 : tree cond = NULL_TREE;
5105 602799 : tree allocator, allocate_ptr;
5106 :
5107 602799 : switch (c_kind)
5108 : {
5109 135788 : case OMP_CLAUSE_PRIVATE:
5110 135788 : if (OMP_CLAUSE_PRIVATE_DEBUG (c))
5111 434804 : continue;
5112 : break;
5113 59602 : case OMP_CLAUSE_SHARED:
5114 : /* Ignore shared directives in teams construct inside
5115 : of target construct. */
5116 59602 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS
5117 59602 : && !is_host_teams_ctx (ctx))
5118 23496 : continue;
5119 36106 : if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
5120 : {
5121 12080 : gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
5122 : || is_global_var (OMP_CLAUSE_DECL (c)));
5123 12080 : continue;
5124 : }
5125 : case OMP_CLAUSE_FIRSTPRIVATE:
5126 : case OMP_CLAUSE_COPYIN:
5127 : break;
5128 15564 : case OMP_CLAUSE_LINEAR:
5129 15564 : if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
5130 15564 : && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
5131 : lastprivate_firstprivate = true;
5132 : break;
5133 37216 : case OMP_CLAUSE_REDUCTION:
5134 37216 : case OMP_CLAUSE_IN_REDUCTION:
5135 37216 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
5136 28968 : || is_task_ctx (ctx)
5137 63844 : || OMP_CLAUSE_REDUCTION_TASK (c))
5138 : {
5139 12780 : task_reduction_p = true;
5140 12780 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5141 : {
5142 4532 : task_reduction_other_cnt++;
5143 4532 : if (pass == 2)
5144 1133 : continue;
5145 : }
5146 : else
5147 8248 : task_reduction_cnt++;
5148 11647 : if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
5149 : {
5150 696 : var = OMP_CLAUSE_DECL (c);
5151 : /* If var is a global variable that isn't privatized
5152 : in outer contexts, we don't need to look up the
5153 : original address, it is always the address of the
5154 : global variable itself. */
5155 696 : if (!DECL_P (var)
5156 272 : || omp_privatize_by_reference (var)
5157 923 : || !is_global_var
5158 227 : (maybe_lookup_decl_in_outer_ctx (var, ctx)))
5159 : {
5160 594 : task_reduction_needs_orig_p = true;
5161 594 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5162 492 : task_reduction_cntorig++;
5163 : }
5164 : }
5165 : }
5166 24436 : else if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
5167 356681 : reduction_omp_orig_ref = true;
5168 : break;
5169 3352 : case OMP_CLAUSE__REDUCTEMP_:
5170 3352 : if (!is_taskreg_ctx (ctx))
5171 1124 : continue;
5172 : /* FALLTHRU */
5173 111456 : case OMP_CLAUSE__LOOPTEMP_:
5174 : /* Handle _looptemp_/_reductemp_ clauses only on
5175 : parallel/task. */
5176 111456 : if (fd)
5177 69210 : continue;
5178 : break;
5179 43558 : case OMP_CLAUSE_LASTPRIVATE:
5180 43558 : if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
5181 : {
5182 2066 : lastprivate_firstprivate = true;
5183 2066 : if (pass != 0 || is_taskloop_ctx (ctx))
5184 1347 : continue;
5185 : }
5186 : /* Even without corresponding firstprivate, if
5187 : decl is Fortran allocatable, it needs outer var
5188 : reference. */
5189 41492 : else if (pass == 0
5190 62202 : && lang_hooks.decls.omp_private_outer_ref
5191 20710 : (OMP_CLAUSE_DECL (c)))
5192 : lastprivate_firstprivate = true;
5193 : break;
5194 280 : case OMP_CLAUSE_ALIGNED:
5195 280 : if (pass != 1)
5196 140 : continue;
5197 140 : var = OMP_CLAUSE_DECL (c);
5198 140 : if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
5199 140 : && !is_global_var (var))
5200 : {
5201 76 : new_var = maybe_lookup_decl (var, ctx);
5202 76 : if (new_var == NULL_TREE)
5203 6 : new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
5204 76 : x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
5205 76 : tree alarg = omp_clause_aligned_alignment (c);
5206 76 : alarg = fold_convert_loc (clause_loc, size_type_node, alarg);
5207 76 : x = build_call_expr_loc (clause_loc, x, 2, new_var, alarg);
5208 76 : x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
5209 76 : x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
5210 76 : gimplify_and_add (x, ilist);
5211 : }
5212 64 : else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
5213 64 : && is_global_var (var))
5214 : {
5215 64 : tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
5216 64 : new_var = lookup_decl (var, ctx);
5217 64 : t = maybe_lookup_decl_in_outer_ctx (var, ctx);
5218 64 : t = build_fold_addr_expr_loc (clause_loc, t);
5219 64 : t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
5220 64 : tree alarg = omp_clause_aligned_alignment (c);
5221 64 : alarg = fold_convert_loc (clause_loc, size_type_node, alarg);
5222 64 : t = build_call_expr_loc (clause_loc, t2, 2, t, alarg);
5223 64 : t = fold_convert_loc (clause_loc, ptype, t);
5224 64 : x = create_tmp_var (ptype);
5225 64 : t = build2 (MODIFY_EXPR, ptype, x, t);
5226 64 : gimplify_and_add (t, ilist);
5227 64 : t = build_simple_mem_ref_loc (clause_loc, x);
5228 64 : SET_DECL_VALUE_EXPR (new_var, t);
5229 64 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5230 : }
5231 140 : continue;
5232 1478 : case OMP_CLAUSE__CONDTEMP_:
5233 1478 : if (is_parallel_ctx (ctx)
5234 1478 : || (is_simd && !OMP_CLAUSE__CONDTEMP__ITER (c)))
5235 : break;
5236 1070 : continue;
5237 135456 : default:
5238 135456 : continue;
5239 136666 : }
5240 :
5241 356681 : if (task_reduction_p != (pass >= 2))
5242 15616 : continue;
5243 :
5244 341065 : allocator = NULL_TREE;
5245 341065 : allocate_ptr = NULL_TREE;
5246 341065 : new_var = var = OMP_CLAUSE_DECL (c);
5247 341065 : if ((c_kind == OMP_CLAUSE_REDUCTION
5248 341065 : || c_kind == OMP_CLAUSE_IN_REDUCTION)
5249 29639 : && TREE_CODE (var) == MEM_REF)
5250 : {
5251 4356 : var = TREE_OPERAND (var, 0);
5252 4356 : if (TREE_CODE (var) == POINTER_PLUS_EXPR)
5253 773 : var = TREE_OPERAND (var, 0);
5254 4356 : if (TREE_CODE (var) == INDIRECT_REF
5255 4168 : || TREE_CODE (var) == ADDR_EXPR)
5256 2506 : var = TREE_OPERAND (var, 0);
5257 4356 : if (is_variable_sized (var))
5258 : {
5259 179 : gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5260 179 : var = DECL_VALUE_EXPR (var);
5261 179 : gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5262 179 : var = TREE_OPERAND (var, 0);
5263 179 : gcc_assert (DECL_P (var));
5264 : }
5265 4356 : new_var = var;
5266 : }
5267 29639 : if (c_kind == OMP_CLAUSE_IN_REDUCTION && is_omp_target (ctx->stmt))
5268 : {
5269 844 : splay_tree_key key = (splay_tree_key) &DECL_CONTEXT (var);
5270 844 : new_var = (tree) splay_tree_lookup (ctx->field_map, key)->value;
5271 : }
5272 340221 : else if (c_kind != OMP_CLAUSE_COPYIN)
5273 339193 : new_var = lookup_decl (var, ctx);
5274 :
5275 341065 : if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
5276 : {
5277 24378 : if (pass != 0)
5278 12188 : continue;
5279 : }
5280 : /* C/C++ array section reductions. */
5281 316687 : else if ((c_kind == OMP_CLAUSE_REDUCTION
5282 : || c_kind == OMP_CLAUSE_IN_REDUCTION)
5283 316687 : && var != OMP_CLAUSE_DECL (c))
5284 : {
5285 4356 : if (pass == 0)
5286 873 : continue;
5287 :
5288 3483 : tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
5289 3483 : tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
5290 :
5291 3483 : if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
5292 : {
5293 723 : tree b = TREE_OPERAND (orig_var, 1);
5294 723 : if (is_omp_target (ctx->stmt))
5295 : b = NULL_TREE;
5296 : else
5297 723 : b = maybe_lookup_decl (b, ctx);
5298 723 : if (b == NULL)
5299 : {
5300 17 : b = TREE_OPERAND (orig_var, 1);
5301 17 : b = maybe_lookup_decl_in_outer_ctx (b, ctx);
5302 : }
5303 723 : if (integer_zerop (bias))
5304 : bias = b;
5305 : else
5306 : {
5307 0 : bias = fold_convert_loc (clause_loc,
5308 0 : TREE_TYPE (b), bias);
5309 0 : bias = fold_build2_loc (clause_loc, PLUS_EXPR,
5310 0 : TREE_TYPE (b), b, bias);
5311 : }
5312 723 : orig_var = TREE_OPERAND (orig_var, 0);
5313 : }
5314 3483 : if (pass == 2)
5315 : {
5316 1149 : tree out = maybe_lookup_decl_in_outer_ctx (var, ctx);
5317 1149 : if (is_global_var (out)
5318 241 : && TREE_CODE (TREE_TYPE (out)) != POINTER_TYPE
5319 1336 : && (TREE_CODE (TREE_TYPE (out)) != REFERENCE_TYPE
5320 0 : || (TREE_CODE (TREE_TYPE (TREE_TYPE (out)))
5321 : != POINTER_TYPE)))
5322 : x = var;
5323 962 : else if (is_omp_target (ctx->stmt))
5324 : x = out;
5325 : else
5326 : {
5327 866 : bool by_ref = use_pointer_for_field (var, NULL);
5328 866 : x = build_receiver_ref (var, by_ref, ctx);
5329 866 : if (TREE_CODE (TREE_TYPE (var)) == REFERENCE_TYPE
5330 866 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (var)))
5331 : == POINTER_TYPE))
5332 32 : x = build_fold_addr_expr (x);
5333 : }
5334 1149 : if (TREE_CODE (orig_var) == INDIRECT_REF)
5335 40 : x = build_simple_mem_ref (x);
5336 1109 : else if (TREE_CODE (orig_var) == ADDR_EXPR)
5337 : {
5338 646 : if (var == TREE_OPERAND (orig_var, 0))
5339 583 : x = build_fold_addr_expr (x);
5340 : }
5341 1149 : bias = fold_convert (sizetype, bias);
5342 1149 : x = fold_convert (ptr_type_node, x);
5343 1149 : x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5344 1149 : TREE_TYPE (x), x, bias);
5345 1149 : unsigned cnt = task_reduction_cnt - 1;
5346 1149 : if (!task_reduction_needs_orig_p)
5347 1061 : cnt += (task_reduction_cntorig_full
5348 1061 : - task_reduction_cntorig);
5349 : else
5350 88 : cnt = task_reduction_cntorig - 1;
5351 1149 : tree r = build4 (ARRAY_REF, ptr_type_node, tskred_avar,
5352 1149 : size_int (cnt), NULL_TREE, NULL_TREE);
5353 1149 : gimplify_assign (r, x, ilist);
5354 1149 : continue;
5355 1149 : }
5356 :
5357 2334 : if (TREE_CODE (orig_var) == INDIRECT_REF
5358 2240 : || TREE_CODE (orig_var) == ADDR_EXPR)
5359 1362 : orig_var = TREE_OPERAND (orig_var, 0);
5360 2334 : tree d = OMP_CLAUSE_DECL (c);
5361 2334 : tree type = TREE_TYPE (d);
5362 2334 : gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
5363 2334 : tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5364 2334 : tree sz = v;
5365 2334 : const char *name = get_name (orig_var);
5366 2334 : if (pass != 3 && !TREE_CONSTANT (v))
5367 : {
5368 93 : tree t;
5369 93 : if (is_omp_target (ctx->stmt))
5370 : t = NULL_TREE;
5371 : else
5372 93 : t = maybe_lookup_decl (v, ctx);
5373 93 : if (t)
5374 88 : v = t;
5375 : else
5376 5 : v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5377 93 : gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
5378 186 : t = fold_build2_loc (clause_loc, PLUS_EXPR,
5379 93 : TREE_TYPE (v), v,
5380 93 : build_int_cst (TREE_TYPE (v), 1));
5381 93 : sz = fold_build2_loc (clause_loc, MULT_EXPR,
5382 93 : TREE_TYPE (v), t,
5383 93 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
5384 : }
5385 2334 : if (pass == 3)
5386 : {
5387 1461 : tree xv = create_tmp_var (ptr_type_node);
5388 1461 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5389 : {
5390 1149 : unsigned cnt = task_reduction_cnt - 1;
5391 1149 : if (!task_reduction_needs_orig_p)
5392 1061 : cnt += (task_reduction_cntorig_full
5393 1061 : - task_reduction_cntorig);
5394 : else
5395 88 : cnt = task_reduction_cntorig - 1;
5396 1149 : x = build4 (ARRAY_REF, ptr_type_node, tskred_avar,
5397 1149 : size_int (cnt), NULL_TREE, NULL_TREE);
5398 :
5399 1149 : gimple *g = gimple_build_assign (xv, x);
5400 1149 : gimple_seq_add_stmt (ilist, g);
5401 : }
5402 : else
5403 : {
5404 312 : unsigned int idx = *ctx->task_reduction_map->get (c);
5405 312 : tree off;
5406 312 : if (ctx->task_reductions[1 + idx])
5407 81 : off = fold_convert (sizetype,
5408 : ctx->task_reductions[1 + idx]);
5409 : else
5410 231 : off = task_reduction_read (ilist, tskred_temp, sizetype,
5411 231 : 7 + 3 * idx + 1);
5412 312 : gimple *g = gimple_build_assign (xv, POINTER_PLUS_EXPR,
5413 : tskred_base, off);
5414 312 : gimple_seq_add_stmt (ilist, g);
5415 : }
5416 1461 : x = fold_convert (build_pointer_type (boolean_type_node),
5417 : xv);
5418 1461 : if (TREE_CONSTANT (v))
5419 1065 : x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (x), x,
5420 : TYPE_SIZE_UNIT (type));
5421 : else
5422 : {
5423 396 : tree t;
5424 396 : if (is_omp_target (ctx->stmt))
5425 : t = NULL_TREE;
5426 : else
5427 336 : t = maybe_lookup_decl (v, ctx);
5428 336 : if (t)
5429 316 : v = t;
5430 : else
5431 80 : v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5432 396 : gimplify_expr (&v, ilist, NULL, is_gimple_val,
5433 : fb_rvalue);
5434 792 : t = fold_build2_loc (clause_loc, PLUS_EXPR,
5435 396 : TREE_TYPE (v), v,
5436 396 : build_int_cst (TREE_TYPE (v), 1));
5437 396 : t = fold_build2_loc (clause_loc, MULT_EXPR,
5438 396 : TREE_TYPE (v), t,
5439 396 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
5440 396 : x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (x), x, t);
5441 : }
5442 1461 : cond = create_tmp_var (TREE_TYPE (x));
5443 1461 : gimplify_assign (cond, x, ilist);
5444 1461 : x = xv;
5445 : }
5446 873 : else if (lower_private_allocate (var, type, allocator,
5447 : allocate_ptr, ilist, ctx,
5448 : true,
5449 873 : TREE_CONSTANT (v)
5450 780 : ? TYPE_SIZE_UNIT (type)
5451 : : sz))
5452 225 : x = allocate_ptr;
5453 648 : else if (TREE_CONSTANT (v))
5454 : {
5455 560 : x = create_tmp_var_raw (type, name);
5456 560 : gimple_add_tmp_var (x);
5457 560 : TREE_ADDRESSABLE (x) = 1;
5458 560 : x = build_fold_addr_expr_loc (clause_loc, x);
5459 : }
5460 : else
5461 : {
5462 88 : tree atmp
5463 88 : = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
5464 88 : tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
5465 88 : x = build_call_expr_loc (clause_loc, atmp, 2, sz, al);
5466 : }
5467 :
5468 2334 : tree ptype = build_pointer_type (TREE_TYPE (type));
5469 2334 : x = fold_convert_loc (clause_loc, ptype, x);
5470 2334 : tree y = create_tmp_var (ptype, name);
5471 2334 : gimplify_assign (y, x, ilist);
5472 2334 : x = y;
5473 2334 : tree yb = y;
5474 :
5475 2334 : if (!integer_zerop (bias))
5476 : {
5477 1512 : bias = fold_convert_loc (clause_loc, pointer_sized_int_node,
5478 : bias);
5479 1512 : yb = fold_convert_loc (clause_loc, pointer_sized_int_node,
5480 : x);
5481 1512 : yb = fold_build2_loc (clause_loc, MINUS_EXPR,
5482 : pointer_sized_int_node, yb, bias);
5483 1512 : x = fold_convert_loc (clause_loc, TREE_TYPE (x), yb);
5484 1512 : yb = create_tmp_var (ptype, name);
5485 1512 : gimplify_assign (yb, x, ilist);
5486 1512 : x = yb;
5487 : }
5488 :
5489 2334 : d = TREE_OPERAND (d, 0);
5490 2334 : if (TREE_CODE (d) == POINTER_PLUS_EXPR)
5491 420 : d = TREE_OPERAND (d, 0);
5492 2334 : if (TREE_CODE (d) == ADDR_EXPR)
5493 : {
5494 1268 : if (orig_var != var)
5495 : {
5496 91 : gcc_assert (is_variable_sized (orig_var));
5497 91 : x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
5498 : x);
5499 91 : gimplify_assign (new_var, x, ilist);
5500 91 : tree new_orig_var = lookup_decl (orig_var, ctx);
5501 91 : tree t = build_fold_indirect_ref (new_var);
5502 91 : DECL_IGNORED_P (new_var) = 0;
5503 91 : TREE_THIS_NOTRAP (t) = 1;
5504 91 : SET_DECL_VALUE_EXPR (new_orig_var, t);
5505 91 : DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
5506 : }
5507 : else
5508 : {
5509 1177 : x = build2 (MEM_REF, TREE_TYPE (new_var), x,
5510 : build_int_cst (ptype, 0));
5511 1177 : SET_DECL_VALUE_EXPR (new_var, x);
5512 1177 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5513 : }
5514 : }
5515 : else
5516 : {
5517 1066 : gcc_assert (orig_var == var);
5518 1066 : if (TREE_CODE (d) == INDIRECT_REF)
5519 : {
5520 94 : x = create_tmp_var (ptype, name);
5521 94 : TREE_ADDRESSABLE (x) = 1;
5522 94 : gimplify_assign (x, yb, ilist);
5523 94 : x = build_fold_addr_expr_loc (clause_loc, x);
5524 : }
5525 1066 : x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
5526 1066 : gimplify_assign (new_var, x, ilist);
5527 : }
5528 : /* GOMP_taskgroup_reduction_register memsets the whole
5529 : array to zero. If the initializer is zero, we don't
5530 : need to initialize it again, just mark it as ever
5531 : used unconditionally, i.e. cond = true. */
5532 2334 : if (cond
5533 1461 : && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) == NULL_TREE
5534 3267 : && initializer_zerop (omp_reduction_init (c,
5535 933 : TREE_TYPE (type))))
5536 : {
5537 624 : gimple *g = gimple_build_assign (build_simple_mem_ref (cond),
5538 : boolean_true_node);
5539 624 : gimple_seq_add_stmt (ilist, g);
5540 624 : continue;
5541 624 : }
5542 1710 : tree end = create_artificial_label (UNKNOWN_LOCATION);
5543 1710 : if (cond)
5544 : {
5545 837 : gimple *g;
5546 837 : if (!is_parallel_ctx (ctx))
5547 : {
5548 786 : tree condv = create_tmp_var (boolean_type_node);
5549 786 : g = gimple_build_assign (condv,
5550 : build_simple_mem_ref (cond));
5551 786 : gimple_seq_add_stmt (ilist, g);
5552 786 : tree lab1 = create_artificial_label (UNKNOWN_LOCATION);
5553 786 : g = gimple_build_cond (NE_EXPR, condv,
5554 : boolean_false_node, end, lab1);
5555 786 : gimple_seq_add_stmt (ilist, g);
5556 786 : gimple_seq_add_stmt (ilist, gimple_build_label (lab1));
5557 : }
5558 837 : g = gimple_build_assign (build_simple_mem_ref (cond),
5559 : boolean_true_node);
5560 837 : gimple_seq_add_stmt (ilist, g);
5561 : }
5562 :
5563 1710 : tree y1 = create_tmp_var (ptype);
5564 1710 : gimplify_assign (y1, y, ilist);
5565 1710 : tree i2 = NULL_TREE, y2 = NULL_TREE;
5566 1710 : tree body2 = NULL_TREE, end2 = NULL_TREE;
5567 1710 : tree y3 = NULL_TREE, y4 = NULL_TREE;
5568 1710 : if (task_reduction_needs_orig_p)
5569 : {
5570 112 : y3 = create_tmp_var (ptype);
5571 112 : tree ref;
5572 112 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5573 88 : ref = build4 (ARRAY_REF, ptr_type_node, tskred_avar,
5574 88 : size_int (task_reduction_cnt_full
5575 : + task_reduction_cntorig - 1),
5576 : NULL_TREE, NULL_TREE);
5577 : else
5578 : {
5579 24 : unsigned int idx = *ctx->task_reduction_map->get (c);
5580 24 : ref = task_reduction_read (ilist, tskred_temp, ptype,
5581 24 : 7 + 3 * idx);
5582 : }
5583 112 : gimplify_assign (y3, ref, ilist);
5584 : }
5585 1598 : else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
5586 : {
5587 668 : if (pass != 3)
5588 : {
5589 252 : y2 = create_tmp_var (ptype);
5590 252 : gimplify_assign (y2, y, ilist);
5591 : }
5592 668 : if (is_simd || OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
5593 : {
5594 188 : tree ref = build_outer_var_ref (var, ctx);
5595 : /* For ref build_outer_var_ref already performs this. */
5596 188 : if (TREE_CODE (d) == INDIRECT_REF)
5597 0 : gcc_assert (omp_privatize_by_reference (var));
5598 188 : else if (TREE_CODE (d) == ADDR_EXPR)
5599 96 : ref = build_fold_addr_expr (ref);
5600 92 : else if (omp_privatize_by_reference (var))
5601 8 : ref = build_fold_addr_expr (ref);
5602 188 : ref = fold_convert_loc (clause_loc, ptype, ref);
5603 188 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5604 188 : && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
5605 : {
5606 8 : y3 = create_tmp_var (ptype);
5607 8 : gimplify_assign (y3, unshare_expr (ref), ilist);
5608 : }
5609 188 : if (is_simd)
5610 : {
5611 180 : y4 = create_tmp_var (ptype);
5612 180 : gimplify_assign (y4, ref, dlist);
5613 : }
5614 : }
5615 : }
5616 1710 : tree i = create_tmp_var (TREE_TYPE (v));
5617 1710 : gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
5618 1710 : tree body = create_artificial_label (UNKNOWN_LOCATION);
5619 1710 : gimple_seq_add_stmt (ilist, gimple_build_label (body));
5620 1710 : if (y2)
5621 : {
5622 252 : i2 = create_tmp_var (TREE_TYPE (v));
5623 252 : gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
5624 252 : body2 = create_artificial_label (UNKNOWN_LOCATION);
5625 252 : end2 = create_artificial_label (UNKNOWN_LOCATION);
5626 252 : gimple_seq_add_stmt (dlist, gimple_build_label (body2));
5627 : }
5628 1710 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5629 : {
5630 600 : tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5631 600 : tree decl_placeholder
5632 600 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5633 600 : SET_DECL_VALUE_EXPR (decl_placeholder,
5634 : build_simple_mem_ref (y1));
5635 600 : DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5636 600 : SET_DECL_VALUE_EXPR (placeholder,
5637 : y3 ? build_simple_mem_ref (y3)
5638 : : error_mark_node);
5639 600 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5640 600 : x = lang_hooks.decls.omp_clause_default_ctor
5641 720 : (c, build_simple_mem_ref (y1),
5642 120 : y3 ? build_simple_mem_ref (y3) : NULL_TREE);
5643 600 : if (x)
5644 152 : gimplify_and_add (x, ilist);
5645 600 : if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5646 : {
5647 576 : gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5648 576 : lower_omp (&tseq, ctx);
5649 576 : gimple_seq_add_seq (ilist, tseq);
5650 : }
5651 600 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5652 600 : if (is_simd)
5653 : {
5654 0 : SET_DECL_VALUE_EXPR (decl_placeholder,
5655 : build_simple_mem_ref (y2));
5656 0 : SET_DECL_VALUE_EXPR (placeholder,
5657 : build_simple_mem_ref (y4));
5658 0 : gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5659 0 : lower_omp (&tseq, ctx);
5660 0 : gimple_seq_add_seq (dlist, tseq);
5661 0 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5662 : }
5663 600 : DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5664 600 : DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
5665 600 : if (y2)
5666 : {
5667 72 : x = lang_hooks.decls.omp_clause_dtor
5668 72 : (c, build_simple_mem_ref (y2));
5669 72 : if (x)
5670 40 : gimplify_and_add (x, dlist);
5671 : }
5672 : }
5673 : else
5674 : {
5675 1110 : x = omp_reduction_init (c, TREE_TYPE (type));
5676 1110 : enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5677 :
5678 : /* reduction(-:var) sums up the partial results, so it
5679 : acts identically to reduction(+:var). */
5680 1110 : if (code == MINUS_EXPR)
5681 0 : code = PLUS_EXPR;
5682 :
5683 1110 : gimplify_assign (build_simple_mem_ref (y1), x, ilist);
5684 1110 : if (is_simd)
5685 : {
5686 180 : x = build2 (code, TREE_TYPE (type),
5687 : build_simple_mem_ref (y4),
5688 : build_simple_mem_ref (y2));
5689 180 : gimplify_assign (build_simple_mem_ref (y4), x, dlist);
5690 : }
5691 : }
5692 1710 : gimple *g
5693 1710 : = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
5694 1710 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
5695 1710 : gimple_seq_add_stmt (ilist, g);
5696 1710 : if (y3)
5697 : {
5698 120 : g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
5699 120 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
5700 120 : gimple_seq_add_stmt (ilist, g);
5701 : }
5702 1710 : g = gimple_build_assign (i, PLUS_EXPR, i,
5703 1710 : build_int_cst (TREE_TYPE (i), 1));
5704 1710 : gimple_seq_add_stmt (ilist, g);
5705 1710 : g = gimple_build_cond (LE_EXPR, i, v, body, end);
5706 1710 : gimple_seq_add_stmt (ilist, g);
5707 1710 : gimple_seq_add_stmt (ilist, gimple_build_label (end));
5708 1710 : if (y2)
5709 : {
5710 252 : g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
5711 252 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
5712 252 : gimple_seq_add_stmt (dlist, g);
5713 252 : if (y4)
5714 : {
5715 180 : g = gimple_build_assign
5716 180 : (y4, POINTER_PLUS_EXPR, y4,
5717 180 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
5718 180 : gimple_seq_add_stmt (dlist, g);
5719 : }
5720 252 : g = gimple_build_assign (i2, PLUS_EXPR, i2,
5721 252 : build_int_cst (TREE_TYPE (i2), 1));
5722 252 : gimple_seq_add_stmt (dlist, g);
5723 252 : g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
5724 252 : gimple_seq_add_stmt (dlist, g);
5725 252 : gimple_seq_add_stmt (dlist, gimple_build_label (end2));
5726 : }
5727 1710 : if (allocator)
5728 : {
5729 225 : tree f = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
5730 225 : g = gimple_build_call (f, 2, allocate_ptr, allocator);
5731 225 : gimple_seq_add_stmt (dlist, g);
5732 : }
5733 1710 : continue;
5734 1710 : }
5735 312331 : else if (pass == 2)
5736 : {
5737 913 : tree out = maybe_lookup_decl_in_outer_ctx (var, ctx);
5738 913 : if (is_global_var (out))
5739 : x = var;
5740 361 : else if (is_omp_target (ctx->stmt))
5741 : x = out;
5742 : else
5743 : {
5744 301 : bool by_ref = use_pointer_for_field (var, ctx);
5745 301 : x = build_receiver_ref (var, by_ref, ctx);
5746 : }
5747 913 : if (!omp_privatize_by_reference (var))
5748 823 : x = build_fold_addr_expr (x);
5749 913 : x = fold_convert (ptr_type_node, x);
5750 913 : unsigned cnt = task_reduction_cnt - 1;
5751 913 : if (!task_reduction_needs_orig_p)
5752 878 : cnt += task_reduction_cntorig_full - task_reduction_cntorig;
5753 : else
5754 35 : cnt = task_reduction_cntorig - 1;
5755 913 : tree r = build4 (ARRAY_REF, ptr_type_node, tskred_avar,
5756 913 : size_int (cnt), NULL_TREE, NULL_TREE);
5757 913 : gimplify_assign (r, x, ilist);
5758 913 : continue;
5759 913 : }
5760 311418 : else if (pass == 3)
5761 : {
5762 1734 : tree type = TREE_TYPE (new_var);
5763 1734 : if (!omp_privatize_by_reference (var))
5764 1628 : type = build_pointer_type (type);
5765 1734 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5766 : {
5767 913 : unsigned cnt = task_reduction_cnt - 1;
5768 913 : if (!task_reduction_needs_orig_p)
5769 878 : cnt += (task_reduction_cntorig_full
5770 878 : - task_reduction_cntorig);
5771 : else
5772 35 : cnt = task_reduction_cntorig - 1;
5773 913 : x = build4 (ARRAY_REF, ptr_type_node, tskred_avar,
5774 913 : size_int (cnt), NULL_TREE, NULL_TREE);
5775 : }
5776 : else
5777 : {
5778 821 : unsigned int idx = *ctx->task_reduction_map->get (c);
5779 821 : tree off;
5780 821 : if (ctx->task_reductions[1 + idx])
5781 821 : off = fold_convert (sizetype,
5782 : ctx->task_reductions[1 + idx]);
5783 : else
5784 0 : off = task_reduction_read (ilist, tskred_temp, sizetype,
5785 0 : 7 + 3 * idx + 1);
5786 821 : x = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
5787 : tskred_base, off);
5788 : }
5789 1734 : x = fold_convert (type, x);
5790 1734 : tree t;
5791 1734 : if (omp_privatize_by_reference (var))
5792 : {
5793 106 : gimplify_assign (new_var, x, ilist);
5794 106 : t = new_var;
5795 106 : new_var = build_simple_mem_ref (new_var);
5796 : }
5797 : else
5798 : {
5799 1628 : t = create_tmp_var (type);
5800 1628 : gimplify_assign (t, x, ilist);
5801 1628 : SET_DECL_VALUE_EXPR (new_var, build_simple_mem_ref (t));
5802 1628 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5803 : }
5804 1734 : t = fold_convert (build_pointer_type (boolean_type_node), t);
5805 1734 : t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t,
5806 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
5807 1734 : cond = create_tmp_var (TREE_TYPE (t));
5808 1734 : gimplify_assign (cond, t, ilist);
5809 : }
5810 309684 : else if (is_variable_sized (var))
5811 : {
5812 : /* For variable sized types, we need to allocate the
5813 : actual storage here. Call alloca and store the
5814 : result in the pointer decl that we created elsewhere. */
5815 262 : if (pass == 0)
5816 134 : continue;
5817 :
5818 128 : if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
5819 : {
5820 114 : tree tmp;
5821 :
5822 114 : ptr = DECL_VALUE_EXPR (new_var);
5823 114 : gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
5824 114 : ptr = TREE_OPERAND (ptr, 0);
5825 114 : gcc_assert (DECL_P (ptr));
5826 114 : x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
5827 :
5828 114 : if (lower_private_allocate (var, new_var, allocator,
5829 : allocate_ptr, ilist, ctx,
5830 : false, x))
5831 8 : tmp = allocate_ptr;
5832 : else
5833 : {
5834 : /* void *tmp = __builtin_alloca */
5835 106 : tree atmp
5836 106 : = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
5837 106 : gcall *stmt
5838 106 : = gimple_build_call (atmp, 2, x,
5839 106 : size_int (DECL_ALIGN (var)));
5840 106 : cfun->calls_alloca = 1;
5841 106 : tmp = create_tmp_var_raw (ptr_type_node);
5842 106 : gimple_add_tmp_var (tmp);
5843 106 : gimple_call_set_lhs (stmt, tmp);
5844 :
5845 106 : gimple_seq_add_stmt (ilist, stmt);
5846 : }
5847 :
5848 114 : x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
5849 114 : gimplify_assign (ptr, x, ilist);
5850 : }
5851 : }
5852 309422 : else if (omp_privatize_by_reference (var)
5853 309422 : && (c_kind != OMP_CLAUSE_FIRSTPRIVATE
5854 1944 : || !OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c)))
5855 : {
5856 : /* For references that are being privatized for Fortran,
5857 : allocate new backing storage for the new pointer
5858 : variable. This allows us to avoid changing all the
5859 : code that expects a pointer to something that expects
5860 : a direct variable. */
5861 4787 : if (pass == 0)
5862 2496 : continue;
5863 :
5864 2291 : x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
5865 2291 : if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
5866 : {
5867 134 : x = build_receiver_ref (var, false, ctx);
5868 134 : if (ctx->allocate_map)
5869 4 : if (tree *allocatep = ctx->allocate_map->get (var))
5870 : {
5871 4 : allocator = *allocatep;
5872 4 : if (TREE_CODE (allocator) == TREE_LIST)
5873 0 : allocator = TREE_PURPOSE (allocator);
5874 4 : if (TREE_CODE (allocator) != INTEGER_CST)
5875 2 : allocator = build_outer_var_ref (allocator, ctx);
5876 4 : allocator = fold_convert (pointer_sized_int_node,
5877 : allocator);
5878 4 : allocate_ptr = unshare_expr (x);
5879 : }
5880 134 : if (allocator == NULL_TREE)
5881 130 : x = build_fold_addr_expr_loc (clause_loc, x);
5882 : }
5883 2157 : else if (lower_private_allocate (var, new_var, allocator,
5884 : allocate_ptr,
5885 : ilist, ctx, true, x))
5886 44 : x = allocate_ptr;
5887 2113 : else if (TREE_CONSTANT (x))
5888 : {
5889 : /* For reduction in SIMD loop, defer adding the
5890 : initialization of the reference, because if we decide
5891 : to use SIMD array for it, the initialization could cause
5892 : expansion ICE. Ditto for other privatization clauses. */
5893 1404 : if (is_simd)
5894 : x = NULL_TREE;
5895 : else
5896 : {
5897 1077 : x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
5898 : get_name (var));
5899 1077 : gimple_add_tmp_var (x);
5900 1077 : TREE_ADDRESSABLE (x) = 1;
5901 1077 : x = build_fold_addr_expr_loc (clause_loc, x);
5902 : }
5903 : }
5904 : else
5905 : {
5906 709 : tree atmp
5907 709 : = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
5908 709 : tree rtype = TREE_TYPE (TREE_TYPE (new_var));
5909 709 : tree al = size_int (TYPE_ALIGN (rtype));
5910 709 : x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
5911 : }
5912 :
5913 1964 : if (x)
5914 : {
5915 1964 : x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
5916 1964 : gimplify_assign (new_var, x, ilist);
5917 : }
5918 :
5919 2291 : new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5920 : }
5921 304635 : else if ((c_kind == OMP_CLAUSE_REDUCTION
5922 : || c_kind == OMP_CLAUSE_IN_REDUCTION)
5923 304635 : && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5924 : {
5925 1968 : if (pass == 0)
5926 984 : continue;
5927 : }
5928 302667 : else if (pass != 0)
5929 151077 : continue;
5930 :
5931 168917 : switch (OMP_CLAUSE_CODE (c))
5932 : {
5933 11676 : case OMP_CLAUSE_SHARED:
5934 : /* Ignore shared directives in teams construct inside
5935 : target construct. */
5936 11676 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS
5937 11676 : && !is_host_teams_ctx (ctx))
5938 0 : continue;
5939 : /* Shared global vars are just accessed directly. */
5940 11676 : if (is_global_var (new_var))
5941 : break;
5942 : /* For taskloop firstprivate/lastprivate, represented
5943 : as firstprivate and shared clause on the task, new_var
5944 : is the firstprivate var. */
5945 11522 : if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
5946 : break;
5947 : /* Set up the DECL_VALUE_EXPR for shared variables now. This
5948 : needs to be delayed until after fixup_child_record_type so
5949 : that we get the correct type during the dereference. */
5950 11210 : by_ref = use_pointer_for_field (var, ctx);
5951 11210 : x = build_receiver_ref (var, by_ref, ctx);
5952 11210 : SET_DECL_VALUE_EXPR (new_var, x);
5953 11210 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5954 :
5955 : /* ??? If VAR is not passed by reference, and the variable
5956 : hasn't been initialized yet, then we'll get a warning for
5957 : the store into the omp_data_s structure. Ideally, we'd be
5958 : able to notice this and not store anything at all, but
5959 : we're generating code too early. Suppress the warning. */
5960 11210 : if (!by_ref)
5961 5116 : suppress_warning (var, OPT_Wuninitialized);
5962 : break;
5963 :
5964 204 : case OMP_CLAUSE__CONDTEMP_:
5965 204 : if (is_parallel_ctx (ctx))
5966 : {
5967 97 : x = build_receiver_ref (var, false, ctx);
5968 97 : SET_DECL_VALUE_EXPR (new_var, x);
5969 97 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5970 : }
5971 107 : else if (is_simd && !OMP_CLAUSE__CONDTEMP__ITER (c))
5972 : {
5973 107 : x = build_zero_cst (TREE_TYPE (var));
5974 107 : goto do_private;
5975 : }
5976 : break;
5977 :
5978 21218 : case OMP_CLAUSE_LASTPRIVATE:
5979 21218 : if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
5980 : break;
5981 : /* FALLTHRU */
5982 :
5983 87200 : case OMP_CLAUSE_PRIVATE:
5984 87200 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
5985 20710 : x = build_outer_var_ref (var, ctx);
5986 66490 : else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
5987 : {
5988 163 : if (is_task_ctx (ctx))
5989 12 : x = build_receiver_ref (var, false, ctx);
5990 : else
5991 151 : x = build_outer_var_ref (var, ctx, OMP_CLAUSE_PRIVATE);
5992 : }
5993 : else
5994 : x = NULL;
5995 93844 : do_private:
5996 93844 : tree nx;
5997 93844 : bool copy_ctor;
5998 93844 : copy_ctor = false;
5999 93844 : lower_private_allocate (var, new_var, allocator, allocate_ptr,
6000 : ilist, ctx, false, NULL_TREE);
6001 93844 : nx = unshare_expr (new_var);
6002 93844 : if (is_simd
6003 24199 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
6004 101230 : && OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c))
6005 22 : copy_ctor = true;
6006 93844 : if (copy_ctor)
6007 22 : nx = lang_hooks.decls.omp_clause_copy_ctor (c, nx, x);
6008 : else
6009 93822 : nx = lang_hooks.decls.omp_clause_default_ctor (c, nx, x);
6010 93844 : if (is_simd)
6011 : {
6012 24199 : tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
6013 23517 : if ((TREE_ADDRESSABLE (new_var) || nx || y
6014 23501 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
6015 7010 : && (gimple_omp_for_collapse (ctx->stmt) != 1
6016 1375 : || (gimple_omp_for_index (ctx->stmt, 0)
6017 : != new_var)))
6018 16793 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE__CONDTEMP_
6019 16686 : || omp_privatize_by_reference (var))
6020 31064 : && lower_rec_simd_input_clauses (new_var, ctx, &sctx,
6021 : ivar, lvar))
6022 : {
6023 5981 : if (omp_privatize_by_reference (var))
6024 : {
6025 52 : gcc_assert (TREE_CODE (new_var) == MEM_REF);
6026 52 : tree new_vard = TREE_OPERAND (new_var, 0);
6027 52 : gcc_assert (DECL_P (new_vard));
6028 52 : SET_DECL_VALUE_EXPR (new_vard,
6029 : build_fold_addr_expr (lvar));
6030 52 : DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
6031 : }
6032 :
6033 5981 : if (nx)
6034 : {
6035 30 : tree iv = unshare_expr (ivar);
6036 30 : if (copy_ctor)
6037 22 : x = lang_hooks.decls.omp_clause_copy_ctor (c, iv,
6038 : x);
6039 : else
6040 8 : x = lang_hooks.decls.omp_clause_default_ctor (c,
6041 : iv,
6042 : x);
6043 : }
6044 5951 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE__CONDTEMP_)
6045 : {
6046 37 : x = build2 (MODIFY_EXPR, TREE_TYPE (ivar),
6047 : unshare_expr (ivar), x);
6048 37 : nx = x;
6049 : }
6050 5981 : if (nx && x)
6051 67 : gimplify_and_add (x, &llist[0]);
6052 5981 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
6053 5981 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
6054 : {
6055 37 : tree v = new_var;
6056 37 : if (!DECL_P (v))
6057 : {
6058 4 : gcc_assert (TREE_CODE (v) == MEM_REF);
6059 4 : v = TREE_OPERAND (v, 0);
6060 4 : gcc_assert (DECL_P (v));
6061 : }
6062 37 : v = *ctx->lastprivate_conditional_map->get (v);
6063 37 : tree t = create_tmp_var (TREE_TYPE (v));
6064 37 : tree z = build_zero_cst (TREE_TYPE (v));
6065 37 : tree orig_v
6066 37 : = build_outer_var_ref (var, ctx,
6067 : OMP_CLAUSE_LASTPRIVATE);
6068 37 : gimple_seq_add_stmt (dlist,
6069 37 : gimple_build_assign (t, z));
6070 37 : gcc_assert (DECL_HAS_VALUE_EXPR_P (v));
6071 37 : tree civar = DECL_VALUE_EXPR (v);
6072 37 : gcc_assert (TREE_CODE (civar) == ARRAY_REF);
6073 37 : civar = unshare_expr (civar);
6074 37 : TREE_OPERAND (civar, 1) = sctx.idx;
6075 37 : x = build2 (MODIFY_EXPR, TREE_TYPE (t), t,
6076 : unshare_expr (civar));
6077 74 : x = build2 (COMPOUND_EXPR, TREE_TYPE (orig_v), x,
6078 37 : build2 (MODIFY_EXPR, TREE_TYPE (orig_v),
6079 : orig_v, unshare_expr (ivar)));
6080 37 : tree cond = build2 (LT_EXPR, boolean_type_node, t,
6081 : civar);
6082 37 : x = build3 (COND_EXPR, void_type_node, cond, x,
6083 : void_node);
6084 37 : gimple_seq tseq = NULL;
6085 37 : gimplify_and_add (x, &tseq);
6086 37 : if (ctx->outer)
6087 27 : lower_omp (&tseq, ctx->outer);
6088 37 : gimple_seq_add_seq (&llist[1], tseq);
6089 : }
6090 5981 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
6091 5981 : && ctx->for_simd_scan_phase)
6092 : {
6093 9 : x = unshare_expr (ivar);
6094 9 : tree orig_v
6095 9 : = build_outer_var_ref (var, ctx,
6096 : OMP_CLAUSE_LASTPRIVATE);
6097 9 : x = lang_hooks.decls.omp_clause_assign_op (c, x,
6098 : orig_v);
6099 9 : gimplify_and_add (x, &llist[0]);
6100 : }
6101 5981 : if (y)
6102 : {
6103 30 : y = lang_hooks.decls.omp_clause_dtor (c, ivar);
6104 30 : if (y)
6105 30 : gimplify_and_add (y, &llist[1]);
6106 : }
6107 : break;
6108 : }
6109 18218 : if (omp_privatize_by_reference (var))
6110 : {
6111 28 : gcc_assert (TREE_CODE (new_var) == MEM_REF);
6112 28 : tree new_vard = TREE_OPERAND (new_var, 0);
6113 28 : gcc_assert (DECL_P (new_vard));
6114 28 : tree type = TREE_TYPE (TREE_TYPE (new_vard));
6115 28 : x = TYPE_SIZE_UNIT (type);
6116 28 : if (TREE_CONSTANT (x))
6117 : {
6118 28 : x = create_tmp_var_raw (type, get_name (var));
6119 28 : gimple_add_tmp_var (x);
6120 28 : TREE_ADDRESSABLE (x) = 1;
6121 28 : x = build_fold_addr_expr_loc (clause_loc, x);
6122 28 : x = fold_convert_loc (clause_loc,
6123 28 : TREE_TYPE (new_vard), x);
6124 28 : gimplify_assign (new_vard, x, ilist);
6125 : }
6126 : }
6127 : }
6128 87863 : if (nx)
6129 488 : gimplify_and_add (nx, ilist);
6130 87863 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
6131 15087 : && is_simd
6132 89626 : && ctx->for_simd_scan_phase)
6133 : {
6134 5 : tree orig_v = build_outer_var_ref (var, ctx,
6135 : OMP_CLAUSE_LASTPRIVATE);
6136 5 : x = lang_hooks.decls.omp_clause_assign_op (c, new_var,
6137 : orig_v);
6138 5 : gimplify_and_add (x, ilist);
6139 : }
6140 : /* FALLTHRU */
6141 :
6142 118607 : do_dtor:
6143 118607 : x = lang_hooks.decls.omp_clause_dtor (c, new_var);
6144 118607 : if (x)
6145 1134 : gimplify_and_add (x, dlist);
6146 118607 : if (allocator)
6147 : {
6148 636 : if (!is_gimple_val (allocator))
6149 : {
6150 10 : tree avar = create_tmp_var (TREE_TYPE (allocator));
6151 10 : gimplify_assign (avar, allocator, dlist);
6152 10 : allocator = avar;
6153 : }
6154 636 : if (!is_gimple_val (allocate_ptr))
6155 : {
6156 26 : tree apvar = create_tmp_var (TREE_TYPE (allocate_ptr));
6157 26 : gimplify_assign (apvar, allocate_ptr, dlist);
6158 26 : allocate_ptr = apvar;
6159 : }
6160 636 : tree f = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
6161 636 : gimple *g
6162 636 : = gimple_build_call (f, 2, allocate_ptr, allocator);
6163 636 : gimple_seq_add_stmt (dlist, g);
6164 : }
6165 : break;
6166 :
6167 7782 : case OMP_CLAUSE_LINEAR:
6168 7782 : if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
6169 1245 : goto do_firstprivate;
6170 6537 : if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
6171 : x = NULL;
6172 : else
6173 3598 : x = build_outer_var_ref (var, ctx);
6174 6537 : goto do_private;
6175 :
6176 28629 : case OMP_CLAUSE_FIRSTPRIVATE:
6177 28629 : if (is_task_ctx (ctx))
6178 : {
6179 4589 : if ((omp_privatize_by_reference (var)
6180 134 : && !OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c))
6181 4589 : || is_variable_sized (var))
6182 148 : goto do_dtor;
6183 4441 : else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
6184 : ctx))
6185 4441 : || use_pointer_for_field (var, NULL))
6186 : {
6187 409 : x = build_receiver_ref (var, false, ctx);
6188 409 : if (ctx->allocate_map)
6189 22 : if (tree *allocatep = ctx->allocate_map->get (var))
6190 : {
6191 22 : allocator = *allocatep;
6192 22 : if (TREE_CODE (allocator) == TREE_LIST)
6193 4 : allocator = TREE_PURPOSE (allocator);
6194 22 : if (TREE_CODE (allocator) != INTEGER_CST)
6195 8 : allocator = build_outer_var_ref (allocator, ctx);
6196 22 : allocator = fold_convert (pointer_sized_int_node,
6197 : allocator);
6198 22 : allocate_ptr = unshare_expr (x);
6199 22 : x = build_simple_mem_ref (x);
6200 22 : TREE_THIS_NOTRAP (x) = 1;
6201 : }
6202 409 : SET_DECL_VALUE_EXPR (new_var, x);
6203 409 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
6204 409 : goto do_dtor;
6205 : }
6206 : }
6207 28072 : if (OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c)
6208 28072 : && omp_privatize_by_reference (var))
6209 : {
6210 0 : x = build_outer_var_ref (var, ctx);
6211 0 : gcc_assert (TREE_CODE (x) == MEM_REF
6212 : && integer_zerop (TREE_OPERAND (x, 1)));
6213 0 : x = TREE_OPERAND (x, 0);
6214 0 : x = lang_hooks.decls.omp_clause_copy_ctor
6215 0 : (c, unshare_expr (new_var), x);
6216 0 : gimplify_and_add (x, ilist);
6217 0 : goto do_dtor;
6218 : }
6219 29317 : do_firstprivate:
6220 29317 : lower_private_allocate (var, new_var, allocator, allocate_ptr,
6221 : ilist, ctx, false, NULL_TREE);
6222 29317 : x = build_outer_var_ref (var, ctx);
6223 29317 : if (is_simd)
6224 : {
6225 1063 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
6226 1063 : && gimple_omp_for_combined_into_p (ctx->stmt))
6227 : {
6228 668 : tree t = OMP_CLAUSE_LINEAR_STEP (c);
6229 668 : if (DECL_P (t))
6230 114 : t = build_outer_var_ref (t, ctx);
6231 668 : tree stept = TREE_TYPE (t);
6232 668 : tree ct = omp_find_clause (clauses,
6233 : OMP_CLAUSE__LOOPTEMP_);
6234 668 : gcc_assert (ct);
6235 668 : tree l = OMP_CLAUSE_DECL (ct);
6236 668 : tree n1 = fd->loop.n1;
6237 668 : tree step = fd->loop.step;
6238 668 : tree itype = TREE_TYPE (l);
6239 668 : if (POINTER_TYPE_P (itype))
6240 0 : itype = signed_type_for (itype);
6241 668 : l = fold_build2 (MINUS_EXPR, itype, l, n1);
6242 668 : if (TYPE_UNSIGNED (itype)
6243 668 : && fd->loop.cond_code == GT_EXPR)
6244 0 : l = fold_build2 (TRUNC_DIV_EXPR, itype,
6245 : fold_build1 (NEGATE_EXPR, itype, l),
6246 : fold_build1 (NEGATE_EXPR,
6247 : itype, step));
6248 : else
6249 668 : l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
6250 668 : t = fold_build2 (MULT_EXPR, stept,
6251 : fold_convert (stept, l), t);
6252 :
6253 668 : if (OMP_CLAUSE_LINEAR_ARRAY (c))
6254 : {
6255 108 : if (omp_privatize_by_reference (var))
6256 : {
6257 72 : gcc_assert (TREE_CODE (new_var) == MEM_REF);
6258 72 : tree new_vard = TREE_OPERAND (new_var, 0);
6259 72 : gcc_assert (DECL_P (new_vard));
6260 72 : tree type = TREE_TYPE (TREE_TYPE (new_vard));
6261 72 : nx = TYPE_SIZE_UNIT (type);
6262 72 : if (TREE_CONSTANT (nx))
6263 : {
6264 24 : nx = create_tmp_var_raw (type,
6265 : get_name (var));
6266 24 : gimple_add_tmp_var (nx);
6267 24 : TREE_ADDRESSABLE (nx) = 1;
6268 24 : nx = build_fold_addr_expr_loc (clause_loc,
6269 : nx);
6270 24 : nx = fold_convert_loc (clause_loc,
6271 24 : TREE_TYPE (new_vard),
6272 : nx);
6273 24 : gimplify_assign (new_vard, nx, ilist);
6274 : }
6275 : }
6276 :
6277 108 : x = lang_hooks.decls.omp_clause_linear_ctor
6278 108 : (c, new_var, x, t);
6279 108 : gimplify_and_add (x, ilist);
6280 108 : goto do_dtor;
6281 : }
6282 :
6283 560 : if (POINTER_TYPE_P (TREE_TYPE (x)))
6284 11 : x = fold_build_pointer_plus (x, t);
6285 : else
6286 549 : x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x,
6287 : fold_convert (TREE_TYPE (x), t));
6288 : }
6289 :
6290 955 : if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
6291 934 : || TREE_ADDRESSABLE (new_var)
6292 799 : || omp_privatize_by_reference (var))
6293 1217 : && lower_rec_simd_input_clauses (new_var, ctx, &sctx,
6294 : ivar, lvar))
6295 : {
6296 152 : if (omp_privatize_by_reference (var))
6297 : {
6298 22 : gcc_assert (TREE_CODE (new_var) == MEM_REF);
6299 22 : tree new_vard = TREE_OPERAND (new_var, 0);
6300 22 : gcc_assert (DECL_P (new_vard));
6301 22 : SET_DECL_VALUE_EXPR (new_vard,
6302 : build_fold_addr_expr (lvar));
6303 22 : DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
6304 : }
6305 152 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
6306 : {
6307 131 : tree iv = create_tmp_var (TREE_TYPE (new_var));
6308 131 : x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
6309 131 : gimplify_and_add (x, ilist);
6310 131 : gimple_stmt_iterator gsi
6311 131 : = gsi_start (*gimple_omp_body_ptr (ctx->stmt));
6312 131 : gassign *g
6313 131 : = gimple_build_assign (unshare_expr (lvar), iv);
6314 131 : gsi_insert_before_without_update (&gsi, g,
6315 : GSI_SAME_STMT);
6316 131 : tree t = OMP_CLAUSE_LINEAR_STEP (c);
6317 131 : enum tree_code code = PLUS_EXPR;
6318 131 : if (POINTER_TYPE_P (TREE_TYPE (new_var)))
6319 : code = POINTER_PLUS_EXPR;
6320 131 : g = gimple_build_assign (iv, code, iv, t);
6321 131 : gsi_insert_before_without_update (&gsi, g,
6322 : GSI_SAME_STMT);
6323 131 : break;
6324 : }
6325 21 : x = lang_hooks.decls.omp_clause_copy_ctor
6326 21 : (c, unshare_expr (ivar), x);
6327 21 : gimplify_and_add (x, &llist[0]);
6328 21 : x = lang_hooks.decls.omp_clause_dtor (c, ivar);
6329 21 : if (x)
6330 21 : gimplify_and_add (x, &llist[1]);
6331 : break;
6332 : }
6333 803 : if (omp_privatize_by_reference (var))
6334 : {
6335 105 : gcc_assert (TREE_CODE (new_var) == MEM_REF);
6336 105 : tree new_vard = TREE_OPERAND (new_var, 0);
6337 105 : gcc_assert (DECL_P (new_vard));
6338 105 : tree type = TREE_TYPE (TREE_TYPE (new_vard));
6339 105 : nx = TYPE_SIZE_UNIT (type);
6340 105 : if (TREE_CONSTANT (nx))
6341 : {
6342 57 : nx = create_tmp_var_raw (type, get_name (var));
6343 57 : gimple_add_tmp_var (nx);
6344 57 : TREE_ADDRESSABLE (nx) = 1;
6345 57 : nx = build_fold_addr_expr_loc (clause_loc, nx);
6346 57 : nx = fold_convert_loc (clause_loc,
6347 57 : TREE_TYPE (new_vard), nx);
6348 57 : gimplify_assign (new_vard, nx, ilist);
6349 : }
6350 : }
6351 : }
6352 29057 : x = lang_hooks.decls.omp_clause_copy_ctor
6353 29057 : (c, unshare_expr (new_var), x);
6354 29053 : gimplify_and_add (x, ilist);
6355 29053 : goto do_dtor;
6356 :
6357 19352 : case OMP_CLAUSE__LOOPTEMP_:
6358 19352 : case OMP_CLAUSE__REDUCTEMP_:
6359 19352 : gcc_assert (is_taskreg_ctx (ctx));
6360 19352 : x = build_outer_var_ref (var, ctx);
6361 19352 : x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
6362 19352 : gimplify_and_add (x, ilist);
6363 19352 : break;
6364 :
6365 514 : case OMP_CLAUSE_COPYIN:
6366 514 : by_ref = use_pointer_for_field (var, NULL);
6367 514 : x = build_receiver_ref (var, by_ref, ctx);
6368 514 : x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
6369 514 : append_to_statement_list (x, ©in_seq);
6370 514 : copyin_by_ref |= by_ref;
6371 514 : break;
6372 :
6373 13052 : case OMP_CLAUSE_REDUCTION:
6374 13052 : case OMP_CLAUSE_IN_REDUCTION:
6375 : /* OpenACC reductions are initialized using the
6376 : GOACC_REDUCTION internal function. */
6377 13052 : if (is_gimple_omp_oacc (ctx->stmt))
6378 : break;
6379 9070 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
6380 : {
6381 1440 : tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
6382 1440 : gimple *tseq;
6383 1440 : tree ptype = TREE_TYPE (placeholder);
6384 1440 : if (cond)
6385 : {
6386 295 : x = error_mark_node;
6387 295 : if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c)
6388 295 : && !task_reduction_needs_orig_p)
6389 28 : x = var;
6390 267 : else if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
6391 : {
6392 45 : tree pptype = build_pointer_type (ptype);
6393 45 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
6394 35 : x = build4 (ARRAY_REF, ptr_type_node, tskred_avar,
6395 35 : size_int (task_reduction_cnt_full
6396 : + task_reduction_cntorig - 1),
6397 : NULL_TREE, NULL_TREE);
6398 : else
6399 : {
6400 10 : unsigned int idx
6401 10 : = *ctx->task_reduction_map->get (c);
6402 10 : x = task_reduction_read (ilist, tskred_temp,
6403 10 : pptype, 7 + 3 * idx);
6404 : }
6405 45 : x = fold_convert (pptype, x);
6406 45 : x = build_simple_mem_ref (x);
6407 : }
6408 : }
6409 : else
6410 : {
6411 1145 : lower_private_allocate (var, new_var, allocator,
6412 : allocate_ptr, ilist, ctx, false,
6413 : NULL_TREE);
6414 1145 : x = build_outer_var_ref (var, ctx);
6415 :
6416 1145 : if (omp_privatize_by_reference (var)
6417 1145 : && !useless_type_conversion_p (ptype, TREE_TYPE (x)))
6418 37 : x = build_fold_addr_expr_loc (clause_loc, x);
6419 : }
6420 1440 : SET_DECL_VALUE_EXPR (placeholder, x);
6421 1440 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
6422 1440 : tree new_vard = new_var;
6423 1440 : if (omp_privatize_by_reference (var))
6424 : {
6425 191 : gcc_assert (TREE_CODE (new_var) == MEM_REF);
6426 191 : new_vard = TREE_OPERAND (new_var, 0);
6427 191 : gcc_assert (DECL_P (new_vard));
6428 : }
6429 1440 : tree rvar = NULL_TREE, *rvarp = NULL, rvar2 = NULL_TREE;
6430 1440 : if (is_simd
6431 311 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6432 1751 : && OMP_CLAUSE_REDUCTION_INSCAN (c))
6433 : rvarp = &rvar;
6434 1440 : if (is_simd
6435 1440 : && lower_rec_simd_input_clauses (new_var, ctx, &sctx,
6436 : ivar, lvar, rvarp,
6437 : &rvar2))
6438 : {
6439 174 : if (new_vard == new_var)
6440 : {
6441 128 : gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
6442 128 : SET_DECL_VALUE_EXPR (new_var, ivar);
6443 : }
6444 : else
6445 : {
6446 46 : SET_DECL_VALUE_EXPR (new_vard,
6447 : build_fold_addr_expr (ivar));
6448 46 : DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
6449 : }
6450 174 : x = lang_hooks.decls.omp_clause_default_ctor
6451 174 : (c, unshare_expr (ivar),
6452 : build_outer_var_ref (var, ctx));
6453 174 : if (rvarp && ctx->for_simd_scan_phase)
6454 : {
6455 16 : if (x)
6456 8 : gimplify_and_add (x, &llist[0]);
6457 16 : x = lang_hooks.decls.omp_clause_dtor (c, ivar);
6458 16 : if (x)
6459 8 : gimplify_and_add (x, &llist[1]);
6460 469 : break;
6461 : }
6462 78 : else if (rvarp)
6463 : {
6464 78 : if (x)
6465 : {
6466 38 : gimplify_and_add (x, &llist[0]);
6467 :
6468 38 : tree ivar2 = unshare_expr (lvar);
6469 38 : TREE_OPERAND (ivar2, 1) = sctx.idx;
6470 38 : x = lang_hooks.decls.omp_clause_default_ctor
6471 38 : (c, ivar2, build_outer_var_ref (var, ctx));
6472 38 : gimplify_and_add (x, &llist[0]);
6473 :
6474 38 : if (rvar2)
6475 : {
6476 16 : x = lang_hooks.decls.omp_clause_default_ctor
6477 16 : (c, unshare_expr (rvar2),
6478 : build_outer_var_ref (var, ctx));
6479 16 : gimplify_and_add (x, &llist[0]);
6480 : }
6481 :
6482 : /* For types that need construction, add another
6483 : private var which will be default constructed
6484 : and optionally initialized with
6485 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT, as in the
6486 : loop we want to assign this value instead of
6487 : constructing and destructing it in each
6488 : iteration. */
6489 38 : tree nv = create_tmp_var_raw (TREE_TYPE (ivar));
6490 38 : gimple_add_tmp_var (nv);
6491 60 : ctx->cb.decl_map->put (TREE_OPERAND (rvar2
6492 : ? rvar2
6493 : : ivar, 0),
6494 : nv);
6495 38 : x = lang_hooks.decls.omp_clause_default_ctor
6496 38 : (c, nv, build_outer_var_ref (var, ctx));
6497 38 : gimplify_and_add (x, ilist);
6498 :
6499 38 : if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
6500 : {
6501 19 : tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
6502 19 : x = DECL_VALUE_EXPR (new_vard);
6503 19 : tree vexpr = nv;
6504 19 : if (new_vard != new_var)
6505 11 : vexpr = build_fold_addr_expr (nv);
6506 19 : SET_DECL_VALUE_EXPR (new_vard, vexpr);
6507 19 : lower_omp (&tseq, ctx);
6508 19 : SET_DECL_VALUE_EXPR (new_vard, x);
6509 19 : gimple_seq_add_seq (ilist, tseq);
6510 19 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
6511 : }
6512 :
6513 38 : x = lang_hooks.decls.omp_clause_dtor (c, nv);
6514 38 : if (x)
6515 38 : gimplify_and_add (x, dlist);
6516 : }
6517 :
6518 78 : tree ref = build_outer_var_ref (var, ctx);
6519 78 : x = unshare_expr (ivar);
6520 78 : x = lang_hooks.decls.omp_clause_assign_op (c, x,
6521 : ref);
6522 78 : gimplify_and_add (x, &llist[0]);
6523 :
6524 78 : ref = build_outer_var_ref (var, ctx);
6525 78 : x = lang_hooks.decls.omp_clause_assign_op (c, ref,
6526 : rvar);
6527 78 : gimplify_and_add (x, &llist[3]);
6528 :
6529 78 : DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
6530 78 : if (new_vard == new_var)
6531 48 : SET_DECL_VALUE_EXPR (new_var, lvar);
6532 : else
6533 30 : SET_DECL_VALUE_EXPR (new_vard,
6534 : build_fold_addr_expr (lvar));
6535 :
6536 78 : x = lang_hooks.decls.omp_clause_dtor (c, ivar);
6537 78 : if (x)
6538 38 : gimplify_and_add (x, &llist[1]);
6539 :
6540 78 : tree ivar2 = unshare_expr (lvar);
6541 78 : TREE_OPERAND (ivar2, 1) = sctx.idx;
6542 78 : x = lang_hooks.decls.omp_clause_dtor (c, ivar2);
6543 78 : if (x)
6544 38 : gimplify_and_add (x, &llist[1]);
6545 :
6546 78 : if (rvar2)
6547 : {
6548 36 : x = lang_hooks.decls.omp_clause_dtor (c, rvar2);
6549 36 : if (x)
6550 16 : gimplify_and_add (x, &llist[1]);
6551 : }
6552 : break;
6553 : }
6554 80 : if (x)
6555 34 : gimplify_and_add (x, &llist[0]);
6556 80 : if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
6557 : {
6558 76 : tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
6559 76 : lower_omp (&tseq, ctx);
6560 76 : gimple_seq_add_seq (&llist[0], tseq);
6561 : }
6562 80 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
6563 80 : tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
6564 80 : lower_omp (&tseq, ctx);
6565 80 : gimple_seq_add_seq (&llist[1], tseq);
6566 80 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
6567 80 : DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
6568 80 : if (new_vard == new_var)
6569 70 : SET_DECL_VALUE_EXPR (new_var, lvar);
6570 : else
6571 10 : SET_DECL_VALUE_EXPR (new_vard,
6572 : build_fold_addr_expr (lvar));
6573 80 : x = lang_hooks.decls.omp_clause_dtor (c, ivar);
6574 80 : if (x)
6575 38 : gimplify_and_add (x, &llist[1]);
6576 : break;
6577 : }
6578 : /* If this is a reference to constant size reduction var
6579 : with placeholder, we haven't emitted the initializer
6580 : for it because it is undesirable if SIMD arrays are used.
6581 : But if they aren't used, we need to emit the deferred
6582 : initialization now. */
6583 1266 : else if (omp_privatize_by_reference (var) && is_simd)
6584 46 : handle_simd_reference (clause_loc, new_vard, ilist);
6585 :
6586 1266 : tree lab2 = NULL_TREE;
6587 1266 : if (cond)
6588 : {
6589 295 : gimple *g;
6590 295 : if (!is_parallel_ctx (ctx))
6591 : {
6592 278 : tree condv = create_tmp_var (boolean_type_node);
6593 278 : tree m = build_simple_mem_ref (cond);
6594 278 : g = gimple_build_assign (condv, m);
6595 278 : gimple_seq_add_stmt (ilist, g);
6596 278 : tree lab1
6597 278 : = create_artificial_label (UNKNOWN_LOCATION);
6598 278 : lab2 = create_artificial_label (UNKNOWN_LOCATION);
6599 278 : g = gimple_build_cond (NE_EXPR, condv,
6600 : boolean_false_node,
6601 : lab2, lab1);
6602 278 : gimple_seq_add_stmt (ilist, g);
6603 278 : gimple_seq_add_stmt (ilist,
6604 278 : gimple_build_label (lab1));
6605 : }
6606 295 : g = gimple_build_assign (build_simple_mem_ref (cond),
6607 : boolean_true_node);
6608 295 : gimple_seq_add_stmt (ilist, g);
6609 : }
6610 295 : x = lang_hooks.decls.omp_clause_default_ctor
6611 1266 : (c, unshare_expr (new_var),
6612 : cond ? NULL_TREE
6613 971 : : build_outer_var_ref (var, ctx));
6614 1266 : if (x)
6615 286 : gimplify_and_add (x, ilist);
6616 :
6617 1266 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6618 1266 : && OMP_CLAUSE_REDUCTION_INSCAN (c))
6619 : {
6620 158 : if (ctx->for_simd_scan_phase)
6621 971 : goto do_dtor;
6622 142 : if (x || (!is_simd
6623 32 : && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c)))
6624 : {
6625 70 : tree nv = create_tmp_var_raw (TREE_TYPE (new_var));
6626 70 : gimple_add_tmp_var (nv);
6627 70 : ctx->cb.decl_map->put (new_vard, nv);
6628 70 : x = lang_hooks.decls.omp_clause_default_ctor
6629 70 : (c, nv, build_outer_var_ref (var, ctx));
6630 70 : if (x)
6631 70 : gimplify_and_add (x, ilist);
6632 70 : if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
6633 : {
6634 35 : tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
6635 35 : tree vexpr = nv;
6636 35 : if (new_vard != new_var)
6637 19 : vexpr = build_fold_addr_expr (nv);
6638 35 : SET_DECL_VALUE_EXPR (new_vard, vexpr);
6639 35 : DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
6640 35 : lower_omp (&tseq, ctx);
6641 35 : SET_DECL_VALUE_EXPR (new_vard, NULL_TREE);
6642 35 : DECL_HAS_VALUE_EXPR_P (new_vard) = 0;
6643 35 : gimple_seq_add_seq (ilist, tseq);
6644 : }
6645 70 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
6646 70 : if (is_simd && ctx->scan_exclusive)
6647 : {
6648 16 : tree nv2
6649 16 : = create_tmp_var_raw (TREE_TYPE (new_var));
6650 16 : gimple_add_tmp_var (nv2);
6651 16 : ctx->cb.decl_map->put (nv, nv2);
6652 16 : x = lang_hooks.decls.omp_clause_default_ctor
6653 16 : (c, nv2, build_outer_var_ref (var, ctx));
6654 16 : gimplify_and_add (x, ilist);
6655 16 : x = lang_hooks.decls.omp_clause_dtor (c, nv2);
6656 16 : if (x)
6657 16 : gimplify_and_add (x, dlist);
6658 : }
6659 70 : x = lang_hooks.decls.omp_clause_dtor (c, nv);
6660 70 : if (x)
6661 70 : gimplify_and_add (x, dlist);
6662 : }
6663 72 : else if (is_simd
6664 40 : && ctx->scan_exclusive
6665 92 : && TREE_ADDRESSABLE (TREE_TYPE (new_var)))
6666 : {
6667 0 : tree nv2 = create_tmp_var_raw (TREE_TYPE (new_var));
6668 0 : gimple_add_tmp_var (nv2);
6669 0 : ctx->cb.decl_map->put (new_vard, nv2);
6670 0 : x = lang_hooks.decls.omp_clause_dtor (c, nv2);
6671 0 : if (x)
6672 0 : gimplify_and_add (x, dlist);
6673 : }
6674 142 : DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
6675 142 : goto do_dtor;
6676 : }
6677 :
6678 1108 : if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
6679 : {
6680 1060 : tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
6681 1060 : if (c_kind == OMP_CLAUSE_IN_REDUCTION
6682 1060 : && is_omp_target (ctx->stmt))
6683 : {
6684 12 : tree d = maybe_lookup_decl_in_outer_ctx (var, ctx);
6685 12 : tree oldv = NULL_TREE;
6686 12 : gcc_assert (d);
6687 12 : if (DECL_HAS_VALUE_EXPR_P (d))
6688 6 : oldv = DECL_VALUE_EXPR (d);
6689 12 : SET_DECL_VALUE_EXPR (d, new_vard);
6690 12 : DECL_HAS_VALUE_EXPR_P (d) = 1;
6691 12 : lower_omp (&tseq, ctx);
6692 12 : if (oldv)
6693 6 : SET_DECL_VALUE_EXPR (d, oldv);
6694 : else
6695 : {
6696 6 : SET_DECL_VALUE_EXPR (d, NULL_TREE);
6697 6 : DECL_HAS_VALUE_EXPR_P (d) = 0;
6698 : }
6699 : }
6700 : else
6701 1048 : lower_omp (&tseq, ctx);
6702 1060 : gimple_seq_add_seq (ilist, tseq);
6703 : }
6704 1108 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
6705 1108 : if (is_simd)
6706 : {
6707 43 : tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
6708 43 : lower_omp (&tseq, ctx);
6709 43 : gimple_seq_add_seq (dlist, tseq);
6710 43 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
6711 : }
6712 1108 : DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
6713 1108 : if (cond)
6714 : {
6715 295 : if (lab2)
6716 278 : gimple_seq_add_stmt (ilist, gimple_build_label (lab2));
6717 : break;
6718 : }
6719 813 : goto do_dtor;
6720 : }
6721 : else
6722 : {
6723 7630 : x = omp_reduction_init (c, TREE_TYPE (new_var));
6724 7630 : gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
6725 7630 : enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
6726 :
6727 7630 : if (cond)
6728 : {
6729 1439 : gimple *g;
6730 1439 : tree lab2 = NULL_TREE;
6731 : /* GOMP_taskgroup_reduction_register memsets the whole
6732 : array to zero. If the initializer is zero, we don't
6733 : need to initialize it again, just mark it as ever
6734 : used unconditionally, i.e. cond = true. */
6735 1439 : if (initializer_zerop (x))
6736 : {
6737 1258 : g = gimple_build_assign (build_simple_mem_ref (cond),
6738 : boolean_true_node);
6739 1258 : gimple_seq_add_stmt (ilist, g);
6740 3227 : break;
6741 : }
6742 :
6743 : /* Otherwise, emit
6744 : if (!cond) { cond = true; new_var = x; } */
6745 181 : if (!is_parallel_ctx (ctx))
6746 : {
6747 177 : tree condv = create_tmp_var (boolean_type_node);
6748 177 : tree m = build_simple_mem_ref (cond);
6749 177 : g = gimple_build_assign (condv, m);
6750 177 : gimple_seq_add_stmt (ilist, g);
6751 177 : tree lab1
6752 177 : = create_artificial_label (UNKNOWN_LOCATION);
6753 177 : lab2 = create_artificial_label (UNKNOWN_LOCATION);
6754 177 : g = gimple_build_cond (NE_EXPR, condv,
6755 : boolean_false_node,
6756 : lab2, lab1);
6757 177 : gimple_seq_add_stmt (ilist, g);
6758 177 : gimple_seq_add_stmt (ilist,
6759 177 : gimple_build_label (lab1));
6760 : }
6761 181 : g = gimple_build_assign (build_simple_mem_ref (cond),
6762 : boolean_true_node);
6763 181 : gimple_seq_add_stmt (ilist, g);
6764 181 : gimplify_assign (new_var, x, ilist);
6765 181 : if (lab2)
6766 177 : gimple_seq_add_stmt (ilist, gimple_build_label (lab2));
6767 : break;
6768 : }
6769 :
6770 : /* reduction(-:var) sums up the partial results, so it
6771 : acts identically to reduction(+:var). */
6772 6191 : if (code == MINUS_EXPR)
6773 33 : code = PLUS_EXPR;
6774 :
6775 6191 : bool is_truth_op
6776 6191 : = (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR);
6777 6191 : tree new_vard = new_var;
6778 6191 : if (is_simd && omp_privatize_by_reference (var))
6779 : {
6780 52 : gcc_assert (TREE_CODE (new_var) == MEM_REF);
6781 52 : new_vard = TREE_OPERAND (new_var, 0);
6782 52 : gcc_assert (DECL_P (new_vard));
6783 : }
6784 6191 : tree rvar = NULL_TREE, *rvarp = NULL, rvar2 = NULL_TREE;
6785 6191 : if (is_simd
6786 2087 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6787 8278 : && OMP_CLAUSE_REDUCTION_INSCAN (c))
6788 : rvarp = &rvar;
6789 6191 : if (is_simd
6790 6191 : && lower_rec_simd_input_clauses (new_var, ctx, &sctx,
6791 : ivar, lvar, rvarp,
6792 : &rvar2))
6793 : {
6794 867 : if (new_vard != new_var)
6795 : {
6796 34 : SET_DECL_VALUE_EXPR (new_vard,
6797 : build_fold_addr_expr (lvar));
6798 34 : DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
6799 : }
6800 :
6801 867 : tree ref = build_outer_var_ref (var, ctx);
6802 :
6803 867 : if (rvarp)
6804 : {
6805 193 : if (ctx->for_simd_scan_phase)
6806 : break;
6807 154 : gimplify_assign (ivar, ref, &llist[0]);
6808 154 : ref = build_outer_var_ref (var, ctx);
6809 154 : gimplify_assign (ref, rvar, &llist[3]);
6810 154 : break;
6811 : }
6812 :
6813 674 : gimplify_assign (unshare_expr (ivar), x, &llist[0]);
6814 :
6815 674 : if (sctx.is_simt)
6816 : {
6817 0 : if (!simt_lane)
6818 0 : simt_lane = create_tmp_var (unsigned_type_node);
6819 0 : x = build_call_expr_internal_loc
6820 0 : (UNKNOWN_LOCATION, IFN_GOMP_SIMT_XCHG_BFLY,
6821 0 : TREE_TYPE (ivar), 2, ivar, simt_lane);
6822 : /* Make sure x is evaluated unconditionally. */
6823 0 : tree bfly_var = create_tmp_var (TREE_TYPE (ivar));
6824 0 : gimplify_assign (bfly_var, x, &llist[2]);
6825 0 : x = build2 (code, TREE_TYPE (ivar), ivar, bfly_var);
6826 0 : gimplify_assign (ivar, x, &llist[2]);
6827 : }
6828 674 : tree ivar2 = ivar;
6829 674 : tree ref2 = ref;
6830 674 : if (is_truth_op)
6831 : {
6832 99 : tree zero = build_zero_cst (TREE_TYPE (ivar));
6833 99 : ivar2 = fold_build2_loc (clause_loc, NE_EXPR,
6834 : boolean_type_node, ivar,
6835 : zero);
6836 99 : ref2 = fold_build2_loc (clause_loc, NE_EXPR,
6837 : boolean_type_node, ref,
6838 : zero);
6839 : }
6840 674 : x = build2 (code, TREE_TYPE (ref), ref2, ivar2);
6841 674 : if (is_truth_op)
6842 99 : x = fold_convert (TREE_TYPE (ref), x);
6843 674 : ref = build_outer_var_ref (var, ctx);
6844 674 : gimplify_assign (ref, x, &llist[1]);
6845 :
6846 : }
6847 : else
6848 : {
6849 5324 : lower_private_allocate (var, new_var, allocator,
6850 : allocate_ptr, ilist, ctx,
6851 : false, NULL_TREE);
6852 5324 : if (omp_privatize_by_reference (var) && is_simd)
6853 18 : handle_simd_reference (clause_loc, new_vard, ilist);
6854 5324 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6855 5324 : && OMP_CLAUSE_REDUCTION_INSCAN (c))
6856 : break;
6857 4987 : gimplify_assign (new_var, x, ilist);
6858 4987 : if (is_simd)
6859 : {
6860 1028 : tree ref = build_outer_var_ref (var, ctx);
6861 1028 : tree new_var2 = new_var;
6862 1028 : tree ref2 = ref;
6863 1028 : if (is_truth_op)
6864 : {
6865 24 : tree zero = build_zero_cst (TREE_TYPE (new_var));
6866 24 : new_var2
6867 24 : = fold_build2_loc (clause_loc, NE_EXPR,
6868 : boolean_type_node, new_var,
6869 : zero);
6870 24 : ref2 = fold_build2_loc (clause_loc, NE_EXPR,
6871 : boolean_type_node, ref,
6872 : zero);
6873 : }
6874 1028 : x = build2 (code, TREE_TYPE (ref2), ref2, new_var2);
6875 1028 : if (is_truth_op)
6876 24 : x = fold_convert (TREE_TYPE (new_var), x);
6877 1028 : ref = build_outer_var_ref (var, ctx);
6878 1028 : gimplify_assign (ref, x, dlist);
6879 : }
6880 4987 : if (allocator)
6881 55 : goto do_dtor;
6882 : }
6883 : }
6884 5606 : break;
6885 :
6886 0 : default:
6887 0 : gcc_unreachable ();
6888 : }
6889 : }
6890 : }
6891 77134 : if (tskred_avar)
6892 : {
6893 871 : tree clobber = build_clobber (TREE_TYPE (tskred_avar));
6894 871 : gimple_seq_add_stmt (ilist, gimple_build_assign (tskred_avar, clobber));
6895 : }
6896 :
6897 77134 : if (known_eq (sctx.max_vf, 1U))
6898 : {
6899 1779 : sctx.is_simt = false;
6900 1779 : if (ctx->lastprivate_conditional_map)
6901 : {
6902 52 : if (gimple_omp_for_combined_into_p (ctx->stmt))
6903 : {
6904 : /* Signal to lower_omp_1 that it should use parent context. */
6905 43 : ctx->combined_into_simd_safelen1 = true;
6906 370 : for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6907 327 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
6908 327 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
6909 : {
6910 57 : tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
6911 57 : omp_context *outer = ctx->outer;
6912 57 : if (gimple_code (outer->stmt) == GIMPLE_OMP_SCAN)
6913 6 : outer = outer->outer;
6914 57 : tree *v = ctx->lastprivate_conditional_map->get (o);
6915 57 : tree po = lookup_decl (OMP_CLAUSE_DECL (c), outer);
6916 57 : tree *pv = outer->lastprivate_conditional_map->get (po);
6917 57 : *v = *pv;
6918 : }
6919 : }
6920 : else
6921 : {
6922 : /* When not vectorized, treat lastprivate(conditional:) like
6923 : normal lastprivate, as there will be just one simd lane
6924 : writing the privatized variable. */
6925 9 : delete ctx->lastprivate_conditional_map;
6926 9 : ctx->lastprivate_conditional_map = NULL;
6927 : }
6928 : }
6929 : }
6930 :
6931 77134 : if (nonconst_simd_if)
6932 : {
6933 625 : if (sctx.lane == NULL_TREE)
6934 : {
6935 570 : sctx.idx = create_tmp_var (unsigned_type_node);
6936 570 : sctx.lane = create_tmp_var (unsigned_type_node);
6937 : }
6938 : /* FIXME: For now. */
6939 625 : sctx.is_simt = false;
6940 : }
6941 :
6942 77134 : if (sctx.lane || sctx.is_simt)
6943 : {
6944 4003 : uid = create_tmp_var (ptr_type_node, "simduid");
6945 : /* Don't want uninit warnings on simduid, it is always uninitialized,
6946 : but we use it not for the value, but for the DECL_UID only. */
6947 4003 : suppress_warning (uid, OPT_Wuninitialized);
6948 4003 : c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
6949 4003 : OMP_CLAUSE__SIMDUID__DECL (c) = uid;
6950 4003 : OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
6951 4003 : gimple_omp_for_set_clauses (ctx->stmt, c);
6952 : }
6953 : /* Emit calls denoting privatized variables and initializing a pointer to
6954 : structure that holds private variables as fields after ompdevlow pass. */
6955 77134 : if (sctx.is_simt)
6956 : {
6957 0 : sctx.simt_eargs[0] = uid;
6958 0 : gimple *g
6959 0 : = gimple_build_call_internal_vec (IFN_GOMP_SIMT_ENTER, sctx.simt_eargs);
6960 0 : gimple_call_set_lhs (g, uid);
6961 0 : gimple_seq_add_stmt (ilist, g);
6962 0 : sctx.simt_eargs.release ();
6963 :
6964 0 : simtrec = create_tmp_var (ptr_type_node, ".omp_simt");
6965 0 : g = gimple_build_call_internal (IFN_GOMP_SIMT_ENTER_ALLOC, 1, uid);
6966 0 : gimple_call_set_lhs (g, simtrec);
6967 0 : gimple_seq_add_stmt (ilist, g);
6968 : }
6969 77134 : if (sctx.lane)
6970 : {
6971 7381 : gimple *g = gimple_build_call_internal (IFN_GOMP_SIMD_LANE,
6972 : 2 + (nonconst_simd_if != NULL),
6973 : uid, integer_zero_node,
6974 : nonconst_simd_if);
6975 4003 : gimple_call_set_lhs (g, sctx.lane);
6976 4003 : gimple_stmt_iterator gsi = gsi_start (*gimple_omp_body_ptr (ctx->stmt));
6977 4003 : gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
6978 4003 : g = gimple_build_assign (sctx.lane, INTEGER_CST,
6979 : build_int_cst (unsigned_type_node, 0));
6980 4003 : gimple_seq_add_stmt (ilist, g);
6981 4003 : if (sctx.lastlane)
6982 : {
6983 184 : g = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
6984 : 2, uid, sctx.lane);
6985 184 : gimple_call_set_lhs (g, sctx.lastlane);
6986 184 : gimple_seq_add_stmt (dlist, g);
6987 184 : gimple_seq_add_seq (dlist, llist[3]);
6988 : }
6989 : /* Emit reductions across SIMT lanes in log_2(simt_vf) steps. */
6990 4003 : if (llist[2])
6991 : {
6992 0 : tree simt_vf = create_tmp_var (unsigned_type_node);
6993 0 : g = gimple_build_call_internal (IFN_GOMP_SIMT_VF, 0);
6994 0 : gimple_call_set_lhs (g, simt_vf);
6995 0 : gimple_seq_add_stmt (dlist, g);
6996 :
6997 0 : tree t = build_int_cst (unsigned_type_node, 1);
6998 0 : g = gimple_build_assign (simt_lane, INTEGER_CST, t);
6999 0 : gimple_seq_add_stmt (dlist, g);
7000 :
7001 0 : t = build_int_cst (unsigned_type_node, 0);
7002 0 : g = gimple_build_assign (sctx.idx, INTEGER_CST, t);
7003 0 : gimple_seq_add_stmt (dlist, g);
7004 :
7005 0 : tree body = create_artificial_label (UNKNOWN_LOCATION);
7006 0 : tree header = create_artificial_label (UNKNOWN_LOCATION);
7007 0 : tree end = create_artificial_label (UNKNOWN_LOCATION);
7008 0 : gimple_seq_add_stmt (dlist, gimple_build_goto (header));
7009 0 : gimple_seq_add_stmt (dlist, gimple_build_label (body));
7010 :
7011 0 : gimple_seq_add_seq (dlist, llist[2]);
7012 :
7013 0 : g = gimple_build_assign (simt_lane, LSHIFT_EXPR, simt_lane, integer_one_node);
7014 0 : gimple_seq_add_stmt (dlist, g);
7015 :
7016 0 : gimple_seq_add_stmt (dlist, gimple_build_label (header));
7017 0 : g = gimple_build_cond (LT_EXPR, simt_lane, simt_vf, body, end);
7018 0 : gimple_seq_add_stmt (dlist, g);
7019 :
7020 0 : gimple_seq_add_stmt (dlist, gimple_build_label (end));
7021 : }
7022 12009 : for (int i = 0; i < 2; i++)
7023 8006 : if (llist[i])
7024 : {
7025 1716 : tree vf = create_tmp_var (unsigned_type_node);
7026 1716 : g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
7027 1716 : gimple_call_set_lhs (g, vf);
7028 1716 : gimple_seq *seq = i == 0 ? ilist : dlist;
7029 1716 : gimple_seq_add_stmt (seq, g);
7030 1716 : tree t = build_int_cst (unsigned_type_node, 0);
7031 1716 : g = gimple_build_assign (sctx.idx, INTEGER_CST, t);
7032 1716 : gimple_seq_add_stmt (seq, g);
7033 1716 : tree body = create_artificial_label (UNKNOWN_LOCATION);
7034 1716 : tree header = create_artificial_label (UNKNOWN_LOCATION);
7035 1716 : tree end = create_artificial_label (UNKNOWN_LOCATION);
7036 1716 : gimple_seq_add_stmt (seq, gimple_build_goto (header));
7037 1716 : gimple_seq_add_stmt (seq, gimple_build_label (body));
7038 1716 : gimple_seq_add_seq (seq, llist[i]);
7039 1716 : t = build_int_cst (unsigned_type_node, 1);
7040 1716 : g = gimple_build_assign (sctx.idx, PLUS_EXPR, sctx.idx, t);
7041 1716 : gimple_seq_add_stmt (seq, g);
7042 1716 : gimple_seq_add_stmt (seq, gimple_build_label (header));
7043 1716 : g = gimple_build_cond (LT_EXPR, sctx.idx, vf, body, end);
7044 1716 : gimple_seq_add_stmt (seq, g);
7045 1716 : gimple_seq_add_stmt (seq, gimple_build_label (end));
7046 : }
7047 : }
7048 77134 : if (sctx.is_simt)
7049 : {
7050 0 : gimple_seq_add_seq (dlist, sctx.simt_dlist);
7051 0 : gimple *g
7052 0 : = gimple_build_call_internal (IFN_GOMP_SIMT_EXIT, 1, simtrec);
7053 0 : gimple_seq_add_stmt (dlist, g);
7054 : }
7055 :
7056 : /* The copyin sequence is not to be executed by the main thread, since
7057 : that would result in self-copies. Perhaps not visible to scalars,
7058 : but it certainly is to C++ operator=. */
7059 77134 : if (copyin_seq)
7060 : {
7061 440 : x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
7062 : 0);
7063 440 : x = build2 (NE_EXPR, boolean_type_node, x,
7064 440 : build_int_cst (TREE_TYPE (x), 0));
7065 440 : x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
7066 440 : gimplify_and_add (x, ilist);
7067 : }
7068 :
7069 : /* If any copyin variable is passed by reference, we must ensure the
7070 : master thread doesn't modify it before it is copied over in all
7071 : threads. Similarly for variables in both firstprivate and
7072 : lastprivate clauses we need to ensure the lastprivate copying
7073 : happens after firstprivate copying in all threads. And similarly
7074 : for UDRs if initializer expression refers to omp_orig. */
7075 77134 : if (copyin_by_ref || lastprivate_firstprivate
7076 75218 : || (reduction_omp_orig_ref
7077 101 : && !ctx->scan_inclusive
7078 101 : && !ctx->scan_exclusive))
7079 : {
7080 : /* Don't add any barrier for #pragma omp simd or
7081 : #pragma omp distribute. */
7082 2017 : if (!is_task_ctx (ctx)
7083 2017 : && (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
7084 1462 : || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR))
7085 : {
7086 880 : int barrier_kind;
7087 880 : switch (gimple_code (ctx->stmt))
7088 : {
7089 : case GIMPLE_OMP_SECTIONS:
7090 : case GIMPLE_OMP_SCOPE:
7091 : case GIMPLE_OMP_FOR:
7092 : barrier_kind = GOMP_BARRIER_IMPLICIT_WORKSHARE;
7093 : break;
7094 540 : case GIMPLE_OMP_PARALLEL:
7095 540 : case GIMPLE_OMP_TEAMS:
7096 540 : barrier_kind = GOMP_BARRIER_IMPLICIT_PARALLEL;
7097 540 : break;
7098 0 : default:
7099 0 : gcc_unreachable ();
7100 : }
7101 880 : gimple_seq_add_stmt (ilist,
7102 : omp_build_barrier (NULL_TREE, barrier_kind));
7103 : }
7104 : }
7105 :
7106 : /* If max_vf is non-zero, then we can use only a vectorization factor
7107 : up to the max_vf we chose. So stick it into the safelen clause. */
7108 77134 : if (maybe_ne (sctx.max_vf, 0U))
7109 : {
7110 5212 : tree c = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
7111 : OMP_CLAUSE_SAFELEN);
7112 5212 : poly_uint64 safe_len;
7113 5212 : if (c == NULL_TREE
7114 5212 : || (poly_int_tree_p (OMP_CLAUSE_SAFELEN_EXPR (c), &safe_len)
7115 613 : && maybe_gt (safe_len, sctx.max_vf)))
7116 : {
7117 5122 : c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
7118 5122 : OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
7119 5122 : sctx.max_vf);
7120 5122 : OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
7121 5122 : gimple_omp_for_set_clauses (ctx->stmt, c);
7122 : }
7123 : }
7124 77134 : }
7125 :
7126 : /* Create temporary variables for lastprivate(conditional:) implementation
7127 : in context CTX with CLAUSES. */
7128 :
7129 : static void
7130 47245 : lower_lastprivate_conditional_clauses (tree *clauses, omp_context *ctx)
7131 : {
7132 47245 : tree iter_type = NULL_TREE;
7133 47245 : tree cond_ptr = NULL_TREE;
7134 47245 : tree iter_var = NULL_TREE;
7135 47245 : bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
7136 47245 : && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD);
7137 47245 : tree next = *clauses;
7138 226762 : for (tree c = *clauses; c; c = OMP_CLAUSE_CHAIN (c))
7139 179517 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7140 179517 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
7141 : {
7142 380 : if (is_simd)
7143 : {
7144 107 : tree cc = omp_find_clause (next, OMP_CLAUSE__CONDTEMP_);
7145 107 : gcc_assert (cc);
7146 107 : if (iter_type == NULL_TREE)
7147 : {
7148 77 : iter_type = TREE_TYPE (OMP_CLAUSE_DECL (cc));
7149 77 : iter_var = create_tmp_var_raw (iter_type);
7150 77 : DECL_CONTEXT (iter_var) = current_function_decl;
7151 77 : DECL_SEEN_IN_BIND_EXPR_P (iter_var) = 1;
7152 77 : DECL_CHAIN (iter_var) = ctx->block_vars;
7153 77 : ctx->block_vars = iter_var;
7154 77 : tree c3
7155 77 : = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
7156 77 : OMP_CLAUSE__CONDTEMP__ITER (c3) = 1;
7157 77 : OMP_CLAUSE_DECL (c3) = iter_var;
7158 77 : OMP_CLAUSE_CHAIN (c3) = *clauses;
7159 77 : *clauses = c3;
7160 77 : ctx->lastprivate_conditional_map = new hash_map<tree, tree>;
7161 : }
7162 107 : next = OMP_CLAUSE_CHAIN (cc);
7163 107 : tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
7164 107 : tree v = lookup_decl (OMP_CLAUSE_DECL (cc), ctx);
7165 107 : ctx->lastprivate_conditional_map->put (o, v);
7166 107 : continue;
7167 107 : }
7168 273 : if (iter_type == NULL)
7169 : {
7170 199 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR)
7171 : {
7172 187 : struct omp_for_data fd;
7173 187 : omp_extract_for_data (as_a <gomp_for *> (ctx->stmt), &fd,
7174 : NULL);
7175 187 : iter_type = unsigned_type_for (fd.iter_type);
7176 : }
7177 12 : else if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
7178 12 : iter_type = unsigned_type_node;
7179 199 : tree c2 = omp_find_clause (*clauses, OMP_CLAUSE__CONDTEMP_);
7180 199 : if (c2)
7181 : {
7182 97 : cond_ptr
7183 97 : = lookup_decl_in_outer_ctx (OMP_CLAUSE_DECL (c2), ctx);
7184 97 : OMP_CLAUSE_DECL (c2) = cond_ptr;
7185 : }
7186 : else
7187 : {
7188 102 : cond_ptr = create_tmp_var_raw (build_pointer_type (iter_type));
7189 102 : DECL_CONTEXT (cond_ptr) = current_function_decl;
7190 102 : DECL_SEEN_IN_BIND_EXPR_P (cond_ptr) = 1;
7191 102 : DECL_CHAIN (cond_ptr) = ctx->block_vars;
7192 102 : ctx->block_vars = cond_ptr;
7193 102 : c2 = build_omp_clause (UNKNOWN_LOCATION,
7194 : OMP_CLAUSE__CONDTEMP_);
7195 102 : OMP_CLAUSE_DECL (c2) = cond_ptr;
7196 102 : OMP_CLAUSE_CHAIN (c2) = *clauses;
7197 102 : *clauses = c2;
7198 : }
7199 199 : iter_var = create_tmp_var_raw (iter_type);
7200 199 : DECL_CONTEXT (iter_var) = current_function_decl;
7201 199 : DECL_SEEN_IN_BIND_EXPR_P (iter_var) = 1;
7202 199 : DECL_CHAIN (iter_var) = ctx->block_vars;
7203 199 : ctx->block_vars = iter_var;
7204 199 : tree c3
7205 199 : = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
7206 199 : OMP_CLAUSE__CONDTEMP__ITER (c3) = 1;
7207 199 : OMP_CLAUSE_DECL (c3) = iter_var;
7208 199 : OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c2);
7209 199 : OMP_CLAUSE_CHAIN (c2) = c3;
7210 199 : ctx->lastprivate_conditional_map = new hash_map<tree, tree>;
7211 : }
7212 273 : tree v = create_tmp_var_raw (iter_type);
7213 273 : DECL_CONTEXT (v) = current_function_decl;
7214 273 : DECL_SEEN_IN_BIND_EXPR_P (v) = 1;
7215 273 : DECL_CHAIN (v) = ctx->block_vars;
7216 273 : ctx->block_vars = v;
7217 273 : tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
7218 273 : ctx->lastprivate_conditional_map->put (o, v);
7219 : }
7220 47245 : }
7221 :
7222 :
7223 : /* Generate code to implement the LASTPRIVATE clauses. This is used for
7224 : both parallel and workshare constructs. PREDICATE may be NULL if it's
7225 : always true. BODY_P is the sequence to insert early initialization
7226 : if needed, STMT_LIST is where the non-conditional lastprivate handling
7227 : goes into and CSTMT_LIST is a sequence that needs to be run in a critical
7228 : section. */
7229 :
7230 : static void
7231 47245 : lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *body_p,
7232 : gimple_seq *stmt_list, gimple_seq *cstmt_list,
7233 : omp_context *ctx)
7234 : {
7235 47245 : tree x, c, label = NULL, orig_clauses = clauses;
7236 47245 : bool par_clauses = false;
7237 47245 : tree simduid = NULL, lastlane = NULL, simtcond = NULL, simtlast = NULL;
7238 47245 : unsigned HOST_WIDE_INT conditional_off = 0;
7239 47245 : gimple_seq post_stmt_list = NULL;
7240 :
7241 : /* Early exit if there are no lastprivate or linear clauses. */
7242 196287 : for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
7243 161493 : if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
7244 161493 : || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
7245 6757 : && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
7246 : break;
7247 47245 : if (clauses == NULL)
7248 : {
7249 : /* If this was a workshare clause, see if it had been combined
7250 : with its parallel. In that case, look for the clauses on the
7251 : parallel statement itself. */
7252 34794 : if (is_parallel_ctx (ctx))
7253 30794 : return;
7254 :
7255 34794 : ctx = ctx->outer;
7256 34794 : if (ctx == NULL || !is_parallel_ctx (ctx))
7257 : return;
7258 :
7259 12209 : clauses = omp_find_clause (gimple_omp_parallel_clauses (ctx->stmt),
7260 : OMP_CLAUSE_LASTPRIVATE);
7261 12209 : if (clauses == NULL)
7262 : return;
7263 : par_clauses = true;
7264 : }
7265 :
7266 16451 : bool maybe_simt = false;
7267 16451 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
7268 16451 : && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
7269 : {
7270 7424 : maybe_simt = omp_find_clause (orig_clauses, OMP_CLAUSE__SIMT_);
7271 7424 : simduid = omp_find_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
7272 7424 : if (simduid)
7273 3551 : simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7274 : }
7275 :
7276 16451 : if (predicate)
7277 : {
7278 16328 : gcond *stmt;
7279 16328 : tree label_true, arm1, arm2;
7280 16328 : enum tree_code pred_code = TREE_CODE (predicate);
7281 :
7282 16328 : label = create_artificial_label (UNKNOWN_LOCATION);
7283 16328 : label_true = create_artificial_label (UNKNOWN_LOCATION);
7284 16328 : if (TREE_CODE_CLASS (pred_code) == tcc_comparison)
7285 : {
7286 16328 : arm1 = TREE_OPERAND (predicate, 0);
7287 16328 : arm2 = TREE_OPERAND (predicate, 1);
7288 16328 : gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
7289 16328 : gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
7290 : }
7291 : else
7292 : {
7293 0 : arm1 = predicate;
7294 0 : gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
7295 0 : arm2 = boolean_false_node;
7296 0 : pred_code = NE_EXPR;
7297 : }
7298 16328 : if (maybe_simt)
7299 : {
7300 0 : c = build2 (pred_code, boolean_type_node, arm1, arm2);
7301 0 : c = fold_convert (integer_type_node, c);
7302 0 : simtcond = create_tmp_var (integer_type_node);
7303 0 : gimplify_assign (simtcond, c, stmt_list);
7304 0 : gcall *g = gimple_build_call_internal (IFN_GOMP_SIMT_VOTE_ANY,
7305 : 1, simtcond);
7306 0 : c = create_tmp_var (integer_type_node);
7307 0 : gimple_call_set_lhs (g, c);
7308 0 : gimple_seq_add_stmt (stmt_list, g);
7309 0 : stmt = gimple_build_cond (NE_EXPR, c, integer_zero_node,
7310 : label_true, label);
7311 : }
7312 : else
7313 16328 : stmt = gimple_build_cond (pred_code, arm1, arm2, label_true, label);
7314 16328 : gimple_seq_add_stmt (stmt_list, stmt);
7315 16328 : gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
7316 : }
7317 :
7318 16451 : tree cond_ptr = NULL_TREE;
7319 61204 : for (c = clauses; c ;)
7320 : {
7321 56011 : tree var, new_var;
7322 56011 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
7323 56011 : gimple_seq *this_stmt_list = stmt_list;
7324 56011 : tree lab2 = NULL_TREE;
7325 :
7326 56011 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7327 21741 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
7328 380 : && ctx->lastprivate_conditional_map
7329 56378 : && !ctx->combined_into_simd_safelen1)
7330 : {
7331 310 : gcc_assert (body_p);
7332 310 : if (simduid)
7333 37 : goto next;
7334 273 : if (cond_ptr == NULL_TREE)
7335 : {
7336 199 : cond_ptr = omp_find_clause (orig_clauses, OMP_CLAUSE__CONDTEMP_);
7337 199 : cond_ptr = OMP_CLAUSE_DECL (cond_ptr);
7338 : }
7339 273 : tree type = TREE_TYPE (TREE_TYPE (cond_ptr));
7340 273 : tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
7341 273 : tree v = *ctx->lastprivate_conditional_map->get (o);
7342 273 : gimplify_assign (v, build_zero_cst (type), body_p);
7343 273 : this_stmt_list = cstmt_list;
7344 273 : tree mem;
7345 273 : if (POINTER_TYPE_P (TREE_TYPE (cond_ptr)))
7346 : {
7347 136 : mem = build2 (MEM_REF, type, cond_ptr,
7348 136 : build_int_cst (TREE_TYPE (cond_ptr),
7349 136 : conditional_off));
7350 136 : conditional_off += tree_to_uhwi (TYPE_SIZE_UNIT (type));
7351 : }
7352 : else
7353 137 : mem = build4 (ARRAY_REF, type, cond_ptr,
7354 137 : size_int (conditional_off++), NULL_TREE, NULL_TREE);
7355 273 : tree mem2 = copy_node (mem);
7356 273 : gimple_seq seq = NULL;
7357 273 : mem = force_gimple_operand (mem, &seq, true, NULL_TREE);
7358 273 : gimple_seq_add_seq (this_stmt_list, seq);
7359 273 : tree lab1 = create_artificial_label (UNKNOWN_LOCATION);
7360 273 : lab2 = create_artificial_label (UNKNOWN_LOCATION);
7361 273 : gimple *g = gimple_build_cond (GT_EXPR, v, mem, lab1, lab2);
7362 273 : gimple_seq_add_stmt (this_stmt_list, g);
7363 273 : gimple_seq_add_stmt (this_stmt_list, gimple_build_label (lab1));
7364 273 : gimplify_assign (mem2, v, this_stmt_list);
7365 : }
7366 55701 : else if (predicate
7367 55455 : && ctx->combined_into_simd_safelen1
7368 116 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7369 57 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
7370 55758 : && ctx->lastprivate_conditional_map)
7371 : this_stmt_list = &post_stmt_list;
7372 :
7373 55974 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7374 55974 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
7375 4843 : && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
7376 : {
7377 26547 : var = OMP_CLAUSE_DECL (c);
7378 26547 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7379 21704 : && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
7380 27578 : && is_taskloop_ctx (ctx))
7381 : {
7382 312 : gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
7383 312 : new_var = lookup_decl (var, ctx->outer);
7384 : }
7385 : else
7386 : {
7387 26235 : new_var = lookup_decl (var, ctx);
7388 : /* Avoid uninitialized warnings for lastprivate and
7389 : for linear iterators. */
7390 26235 : if (predicate
7391 52277 : && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7392 4843 : || OMP_CLAUSE_LINEAR_NO_COPYIN (c)))
7393 24797 : suppress_warning (new_var, OPT_Wuninitialized);
7394 : }
7395 :
7396 26547 : if (!maybe_simt && simduid && DECL_HAS_VALUE_EXPR_P (new_var))
7397 : {
7398 5864 : tree val = DECL_VALUE_EXPR (new_var);
7399 5864 : if (TREE_CODE (val) == ARRAY_REF
7400 5816 : && VAR_P (TREE_OPERAND (val, 0))
7401 11680 : && lookup_attribute ("omp simd array",
7402 5816 : DECL_ATTRIBUTES (TREE_OPERAND (val,
7403 : 0))))
7404 : {
7405 5816 : if (lastlane == NULL)
7406 : {
7407 2759 : lastlane = create_tmp_var (unsigned_type_node);
7408 2759 : gcall *g
7409 2759 : = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
7410 : 2, simduid,
7411 2759 : TREE_OPERAND (val, 1));
7412 2759 : gimple_call_set_lhs (g, lastlane);
7413 2759 : gimple_seq_add_stmt (this_stmt_list, g);
7414 : }
7415 5816 : new_var = build4 (ARRAY_REF, TREE_TYPE (val),
7416 5816 : TREE_OPERAND (val, 0), lastlane,
7417 : NULL_TREE, NULL_TREE);
7418 5816 : TREE_THIS_NOTRAP (new_var) = 1;
7419 : }
7420 : }
7421 20683 : else if (maybe_simt)
7422 : {
7423 0 : tree val = (DECL_HAS_VALUE_EXPR_P (new_var)
7424 0 : ? DECL_VALUE_EXPR (new_var)
7425 : : new_var);
7426 0 : if (simtlast == NULL)
7427 : {
7428 0 : simtlast = create_tmp_var (unsigned_type_node);
7429 0 : gcall *g = gimple_build_call_internal
7430 0 : (IFN_GOMP_SIMT_LAST_LANE, 1, simtcond);
7431 0 : gimple_call_set_lhs (g, simtlast);
7432 0 : gimple_seq_add_stmt (this_stmt_list, g);
7433 : }
7434 0 : x = build_call_expr_internal_loc
7435 0 : (UNKNOWN_LOCATION, IFN_GOMP_SIMT_XCHG_IDX,
7436 0 : TREE_TYPE (val), 2, val, simtlast);
7437 0 : new_var = unshare_expr (new_var);
7438 0 : gimplify_assign (new_var, x, this_stmt_list);
7439 0 : new_var = unshare_expr (new_var);
7440 : }
7441 :
7442 26547 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7443 26547 : && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
7444 : {
7445 7117 : lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
7446 7117 : gimple_seq_add_seq (this_stmt_list,
7447 7117 : OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
7448 7117 : OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
7449 : }
7450 19430 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
7451 19430 : && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
7452 : {
7453 426 : lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
7454 426 : gimple_seq_add_seq (this_stmt_list,
7455 426 : OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
7456 426 : OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
7457 : }
7458 :
7459 26547 : x = NULL_TREE;
7460 26547 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7461 21704 : && OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c)
7462 26607 : && is_taskloop_ctx (ctx))
7463 : {
7464 76 : tree ovar = maybe_lookup_decl_in_outer_ctx (var,
7465 38 : ctx->outer->outer);
7466 38 : if (is_global_var (ovar))
7467 7 : x = ovar;
7468 : }
7469 7 : if (!x)
7470 26540 : x = build_outer_var_ref (var, ctx, OMP_CLAUSE_LASTPRIVATE);
7471 26547 : if (omp_privatize_by_reference (var))
7472 657 : new_var = build_simple_mem_ref_loc (clause_loc, new_var);
7473 26547 : x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
7474 26547 : gimplify_and_add (x, this_stmt_list);
7475 :
7476 26547 : if (lab2)
7477 273 : gimple_seq_add_stmt (this_stmt_list, gimple_build_label (lab2));
7478 : }
7479 :
7480 56011 : next:
7481 56011 : c = OMP_CLAUSE_CHAIN (c);
7482 56011 : if (c == NULL && !par_clauses)
7483 : {
7484 : /* If this was a workshare clause, see if it had been combined
7485 : with its parallel. In that case, continue looking for the
7486 : clauses also on the parallel statement itself. */
7487 12451 : if (is_parallel_ctx (ctx))
7488 : break;
7489 :
7490 12451 : ctx = ctx->outer;
7491 12451 : if (ctx == NULL || !is_parallel_ctx (ctx))
7492 : break;
7493 :
7494 1193 : c = omp_find_clause (gimple_omp_parallel_clauses (ctx->stmt),
7495 : OMP_CLAUSE_LASTPRIVATE);
7496 1193 : par_clauses = true;
7497 : }
7498 : }
7499 :
7500 16451 : if (label)
7501 16328 : gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
7502 16451 : gimple_seq_add_seq (stmt_list, post_stmt_list);
7503 : }
7504 :
7505 : /* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
7506 : (which might be a placeholder). INNER is true if this is an inner
7507 : axis of a multi-axis loop. FORK and JOIN are (optional) fork and
7508 : join markers. Generate the before-loop forking sequence in
7509 : FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
7510 : general form of these sequences is
7511 :
7512 : GOACC_REDUCTION_SETUP
7513 : GOACC_FORK
7514 : GOACC_REDUCTION_INIT
7515 : ...
7516 : GOACC_REDUCTION_FINI
7517 : GOACC_JOIN
7518 : GOACC_REDUCTION_TEARDOWN. */
7519 :
7520 : static void
7521 25946 : lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
7522 : gcall *fork, gcall *private_marker, gcall *join,
7523 : gimple_seq *fork_seq, gimple_seq *join_seq,
7524 : omp_context *ctx)
7525 : {
7526 25946 : gimple_seq before_fork = NULL;
7527 25946 : gimple_seq after_fork = NULL;
7528 25946 : gimple_seq before_join = NULL;
7529 25946 : gimple_seq after_join = NULL;
7530 25946 : tree init_code = NULL_TREE, fini_code = NULL_TREE,
7531 25946 : setup_code = NULL_TREE, teardown_code = NULL_TREE;
7532 25946 : unsigned offset = 0;
7533 :
7534 96516 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
7535 70570 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
7536 : {
7537 : /* No 'reduction' clauses on OpenACC 'kernels'. */
7538 7751 : gcc_checking_assert (!is_oacc_kernels (ctx));
7539 : /* Likewise, on OpenACC 'kernels' decomposed parts. */
7540 7751 : gcc_checking_assert (!is_oacc_kernels_decomposed_part (ctx));
7541 :
7542 7751 : tree orig = OMP_CLAUSE_DECL (c);
7543 7751 : tree orig_clause;
7544 7751 : tree var = maybe_lookup_decl (orig, ctx);
7545 7751 : tree ref_to_res = NULL_TREE;
7546 7751 : tree incoming, outgoing, v1, v2, v3;
7547 7751 : bool is_private = false;
7548 :
7549 7751 : enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
7550 7751 : if (rcode == MINUS_EXPR)
7551 : rcode = PLUS_EXPR;
7552 6609 : else if (rcode == TRUTH_ANDIF_EXPR)
7553 : rcode = BIT_AND_EXPR;
7554 6431 : else if (rcode == TRUTH_ORIF_EXPR)
7555 433 : rcode = BIT_IOR_EXPR;
7556 7751 : tree op = build_int_cst (unsigned_type_node, rcode);
7557 :
7558 7751 : if (!var)
7559 4 : var = orig;
7560 :
7561 7751 : incoming = outgoing = var;
7562 :
7563 7751 : if (!inner)
7564 : {
7565 : /* See if an outer construct also reduces this variable. */
7566 : omp_context *outer = ctx;
7567 :
7568 7385 : while (omp_context *probe = outer->outer)
7569 : {
7570 4708 : enum gimple_code type = gimple_code (probe->stmt);
7571 4708 : tree cls;
7572 :
7573 4708 : switch (type)
7574 : {
7575 2220 : case GIMPLE_OMP_FOR:
7576 2220 : cls = gimple_omp_for_clauses (probe->stmt);
7577 2220 : break;
7578 :
7579 2488 : case GIMPLE_OMP_TARGET:
7580 : /* No 'reduction' clauses inside OpenACC 'kernels'
7581 : regions. */
7582 2488 : gcc_checking_assert (!is_oacc_kernels (probe));
7583 :
7584 2488 : if (!is_gimple_omp_offloaded (probe->stmt))
7585 26 : goto do_lookup;
7586 :
7587 2462 : cls = gimple_omp_target_clauses (probe->stmt);
7588 2462 : break;
7589 :
7590 0 : default:
7591 0 : goto do_lookup;
7592 : }
7593 :
7594 14249 : outer = probe;
7595 14249 : for (; cls; cls = OMP_CLAUSE_CHAIN (cls))
7596 11632 : if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
7597 11632 : && orig == OMP_CLAUSE_DECL (cls))
7598 : {
7599 1772 : incoming = outgoing = lookup_decl (orig, probe);
7600 1772 : goto has_outer_reduction;
7601 : }
7602 9860 : else if ((OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_FIRSTPRIVATE
7603 8971 : || OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_PRIVATE)
7604 11164 : && orig == OMP_CLAUSE_DECL (cls))
7605 : {
7606 293 : is_private = true;
7607 293 : goto do_lookup;
7608 : }
7609 : }
7610 :
7611 2677 : do_lookup:
7612 : /* This is the outermost construct with this reduction,
7613 : see if there's a mapping for it. */
7614 2996 : orig_clause = NULL_TREE;
7615 2996 : if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET)
7616 7557 : for (tree cls = gimple_omp_target_clauses (outer->stmt);
7617 7557 : cls; cls = OMP_CLAUSE_CHAIN (cls))
7618 7250 : if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_MAP
7619 4823 : && orig == OMP_CLAUSE_DECL (cls)
7620 9805 : && maybe_lookup_field (cls, outer))
7621 : {
7622 : orig_clause = cls;
7623 : break;
7624 : }
7625 2996 : if (orig_clause != NULL_TREE && !is_private)
7626 : {
7627 2553 : ref_to_res = build_receiver_ref (orig_clause, false, outer);
7628 2553 : if (omp_privatize_by_reference (orig))
7629 79 : ref_to_res = build_simple_mem_ref (ref_to_res);
7630 :
7631 2553 : tree type = TREE_TYPE (var);
7632 2553 : if (POINTER_TYPE_P (type))
7633 79 : type = TREE_TYPE (type);
7634 :
7635 2553 : outgoing = var;
7636 2553 : incoming = omp_reduction_init_op (loc, rcode, type);
7637 : }
7638 : else
7639 : {
7640 : /* Try to look at enclosing contexts for reduction var,
7641 : use original if no mapping found. */
7642 443 : tree t = NULL_TREE;
7643 443 : omp_context *c = ctx->outer;
7644 895 : while (c && !t)
7645 : {
7646 452 : t = maybe_lookup_decl (orig, c);
7647 452 : c = c->outer;
7648 : }
7649 443 : incoming = outgoing = (t ? t : orig);
7650 : }
7651 :
7652 2553 : has_outer_reduction:;
7653 : }
7654 :
7655 4325 : if (!ref_to_res)
7656 5198 : ref_to_res = integer_zero_node;
7657 :
7658 7751 : if (omp_privatize_by_reference (orig))
7659 : {
7660 159 : tree type = TREE_TYPE (var);
7661 159 : const char *id = IDENTIFIER_POINTER (DECL_NAME (var));
7662 :
7663 159 : if (!inner)
7664 : {
7665 110 : tree x = create_tmp_var (TREE_TYPE (type), id);
7666 110 : gimplify_assign (var, build_fold_addr_expr (x), fork_seq);
7667 : }
7668 :
7669 159 : v1 = create_tmp_var (type, id);
7670 159 : v2 = create_tmp_var (type, id);
7671 159 : v3 = create_tmp_var (type, id);
7672 :
7673 159 : gimplify_assign (v1, var, fork_seq);
7674 159 : gimplify_assign (v2, var, fork_seq);
7675 159 : gimplify_assign (v3, var, fork_seq);
7676 :
7677 159 : var = build_simple_mem_ref (var);
7678 159 : v1 = build_simple_mem_ref (v1);
7679 159 : v2 = build_simple_mem_ref (v2);
7680 159 : v3 = build_simple_mem_ref (v3);
7681 159 : outgoing = build_simple_mem_ref (outgoing);
7682 :
7683 159 : if (!TREE_CONSTANT (incoming))
7684 80 : incoming = build_simple_mem_ref (incoming);
7685 : }
7686 : else
7687 : /* Note that 'var' might be a mem ref. */
7688 : v1 = v2 = v3 = var;
7689 :
7690 : /* Determine position in reduction buffer, which may be used
7691 : by target. The parser has ensured that this is not a
7692 : variable-sized type. */
7693 7751 : fixed_size_mode mode
7694 7751 : = as_a <fixed_size_mode> (TYPE_MODE (TREE_TYPE (var)));
7695 7751 : unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
7696 7751 : offset = (offset + align - 1) & ~(align - 1);
7697 7751 : tree off = build_int_cst (sizetype, offset);
7698 7751 : offset += GET_MODE_SIZE (mode);
7699 :
7700 7751 : if (!init_code)
7701 : {
7702 6969 : init_code = build_int_cst (integer_type_node,
7703 : IFN_GOACC_REDUCTION_INIT);
7704 6969 : fini_code = build_int_cst (integer_type_node,
7705 : IFN_GOACC_REDUCTION_FINI);
7706 6969 : setup_code = build_int_cst (integer_type_node,
7707 : IFN_GOACC_REDUCTION_SETUP);
7708 6969 : teardown_code = build_int_cst (integer_type_node,
7709 : IFN_GOACC_REDUCTION_TEARDOWN);
7710 : }
7711 :
7712 7751 : tree setup_call
7713 15502 : = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
7714 7751 : TREE_TYPE (var), 6, setup_code,
7715 : unshare_expr (ref_to_res),
7716 : unshare_expr (incoming),
7717 : level, op, off);
7718 7751 : tree init_call
7719 15502 : = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
7720 7751 : TREE_TYPE (var), 6, init_code,
7721 : unshare_expr (ref_to_res),
7722 : unshare_expr (v1), level, op, off);
7723 7751 : tree fini_call
7724 15502 : = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
7725 7751 : TREE_TYPE (var), 6, fini_code,
7726 : unshare_expr (ref_to_res),
7727 : unshare_expr (v2), level, op, off);
7728 7751 : tree teardown_call
7729 15502 : = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
7730 7751 : TREE_TYPE (var), 6, teardown_code,
7731 : ref_to_res, unshare_expr (v3),
7732 : level, op, off);
7733 :
7734 7751 : gimplify_assign (unshare_expr (v1), setup_call, &before_fork);
7735 7751 : gimplify_assign (unshare_expr (v2), init_call, &after_fork);
7736 7751 : gimplify_assign (unshare_expr (v3), fini_call, &before_join);
7737 7751 : gimplify_assign (unshare_expr (outgoing), teardown_call, &after_join);
7738 : }
7739 :
7740 : /* Now stitch things together. */
7741 25946 : gimple_seq_add_seq (fork_seq, before_fork);
7742 25946 : if (private_marker)
7743 259 : gimple_seq_add_stmt (fork_seq, private_marker);
7744 25946 : if (fork)
7745 16551 : gimple_seq_add_stmt (fork_seq, fork);
7746 25946 : gimple_seq_add_seq (fork_seq, after_fork);
7747 :
7748 25946 : gimple_seq_add_seq (join_seq, before_join);
7749 25946 : if (join)
7750 16551 : gimple_seq_add_stmt (join_seq, join);
7751 25946 : gimple_seq_add_seq (join_seq, after_join);
7752 25946 : }
7753 :
7754 : /* Generate code to implement the REDUCTION clauses, append it
7755 : to STMT_SEQP. CLIST if non-NULL is a pointer to a sequence
7756 : that should be emitted also inside of the critical section,
7757 : in that case clear *CLIST afterwards, otherwise leave it as is
7758 : and let the caller emit it itself. */
7759 :
7760 : static void
7761 71945 : lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp,
7762 : gimple_seq *clist, omp_context *ctx)
7763 : {
7764 71945 : gimple_seq sub_seq = NULL;
7765 71945 : gimple *stmt;
7766 71945 : tree x, c;
7767 71945 : int count = 0;
7768 :
7769 : /* OpenACC loop reductions are handled elsewhere. */
7770 71945 : if (is_gimple_omp_oacc (ctx->stmt))
7771 70892 : return;
7772 :
7773 : /* SIMD reductions are handled in lower_rec_input_clauses. */
7774 60620 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
7775 60620 : && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
7776 : return;
7777 :
7778 : /* inscan reductions are handled elsewhere. */
7779 51265 : if (ctx->scan_inclusive || ctx->scan_exclusive)
7780 : return;
7781 :
7782 : /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
7783 : update in that case, otherwise use a lock. */
7784 241714 : for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
7785 191482 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
7786 191482 : && !OMP_CLAUSE_REDUCTION_TASK (c))
7787 : {
7788 4618 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
7789 4618 : || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
7790 : {
7791 : /* Never use OMP_ATOMIC for array reductions or UDRs. */
7792 : count = -1;
7793 : break;
7794 : }
7795 3762 : count++;
7796 : }
7797 :
7798 51088 : if (count == 0)
7799 : return;
7800 :
7801 14929 : for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
7802 : {
7803 13876 : tree var, ref, new_var, orig_var;
7804 13876 : enum tree_code code;
7805 13876 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
7806 :
7807 22334 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
7808 13876 : || OMP_CLAUSE_REDUCTION_TASK (c))
7809 8458 : continue;
7810 :
7811 5418 : enum omp_clause_code ccode = OMP_CLAUSE_REDUCTION;
7812 5418 : orig_var = var = OMP_CLAUSE_DECL (c);
7813 5418 : if (TREE_CODE (var) == MEM_REF)
7814 : {
7815 689 : var = TREE_OPERAND (var, 0);
7816 689 : if (TREE_CODE (var) == POINTER_PLUS_EXPR)
7817 50 : var = TREE_OPERAND (var, 0);
7818 689 : if (TREE_CODE (var) == ADDR_EXPR)
7819 304 : var = TREE_OPERAND (var, 0);
7820 : else
7821 : {
7822 : /* If this is a pointer or referenced based array
7823 : section, the var could be private in the outer
7824 : context e.g. on orphaned loop construct. Pretend this
7825 : is private variable's outer reference. */
7826 385 : ccode = OMP_CLAUSE_PRIVATE;
7827 385 : if (INDIRECT_REF_P (var))
7828 54 : var = TREE_OPERAND (var, 0);
7829 : }
7830 689 : orig_var = var;
7831 689 : if (is_variable_sized (var))
7832 : {
7833 25 : gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
7834 25 : var = DECL_VALUE_EXPR (var);
7835 25 : gcc_assert (INDIRECT_REF_P (var));
7836 25 : var = TREE_OPERAND (var, 0);
7837 25 : gcc_assert (DECL_P (var));
7838 : }
7839 : }
7840 5418 : new_var = lookup_decl (var, ctx);
7841 5418 : if (var == OMP_CLAUSE_DECL (c)
7842 5418 : && omp_privatize_by_reference (var))
7843 140 : new_var = build_simple_mem_ref_loc (clause_loc, new_var);
7844 5418 : ref = build_outer_var_ref (var, ctx, ccode);
7845 5418 : code = OMP_CLAUSE_REDUCTION_CODE (c);
7846 :
7847 : /* reduction(-:var) sums up the partial results, so it acts
7848 : identically to reduction(+:var). */
7849 5418 : if (code == MINUS_EXPR)
7850 57 : code = PLUS_EXPR;
7851 :
7852 5418 : bool is_truth_op = (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR);
7853 5418 : if (count == 1)
7854 : {
7855 3313 : tree addr = build_fold_addr_expr_loc (clause_loc, ref);
7856 :
7857 3313 : addr = save_expr (addr);
7858 3313 : ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
7859 3313 : tree new_var2 = new_var;
7860 3313 : tree ref2 = ref;
7861 3313 : if (is_truth_op)
7862 : {
7863 784 : tree zero = build_zero_cst (TREE_TYPE (new_var));
7864 784 : new_var2 = fold_build2_loc (clause_loc, NE_EXPR,
7865 : boolean_type_node, new_var, zero);
7866 784 : ref2 = fold_build2_loc (clause_loc, NE_EXPR, boolean_type_node,
7867 : ref, zero);
7868 : }
7869 3313 : x = fold_build2_loc (clause_loc, code, TREE_TYPE (new_var2), ref2,
7870 : new_var2);
7871 3313 : if (is_truth_op)
7872 784 : x = fold_convert (TREE_TYPE (new_var), x);
7873 3313 : x = build2 (OMP_ATOMIC, void_type_node, addr, x);
7874 3313 : OMP_ATOMIC_MEMORY_ORDER (x) = OMP_MEMORY_ORDER_RELAXED;
7875 3313 : gimplify_and_add (x, stmt_seqp);
7876 3313 : return;
7877 : }
7878 2105 : else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
7879 : {
7880 689 : tree d = OMP_CLAUSE_DECL (c);
7881 689 : tree type = TREE_TYPE (d);
7882 689 : tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
7883 689 : tree i = create_tmp_var (TREE_TYPE (v));
7884 689 : tree ptype = build_pointer_type (TREE_TYPE (type));
7885 689 : tree bias = TREE_OPERAND (d, 1);
7886 689 : d = TREE_OPERAND (d, 0);
7887 689 : if (TREE_CODE (d) == POINTER_PLUS_EXPR)
7888 : {
7889 50 : tree b = TREE_OPERAND (d, 1);
7890 50 : b = maybe_lookup_decl (b, ctx);
7891 50 : if (b == NULL)
7892 : {
7893 2 : b = TREE_OPERAND (d, 1);
7894 2 : b = maybe_lookup_decl_in_outer_ctx (b, ctx);
7895 : }
7896 50 : if (integer_zerop (bias))
7897 : bias = b;
7898 : else
7899 : {
7900 0 : bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
7901 0 : bias = fold_build2_loc (clause_loc, PLUS_EXPR,
7902 0 : TREE_TYPE (b), b, bias);
7903 : }
7904 50 : d = TREE_OPERAND (d, 0);
7905 : }
7906 : /* For ref build_outer_var_ref already performs this, so
7907 : only new_var needs a dereference. */
7908 689 : if (INDIRECT_REF_P (d))
7909 : {
7910 54 : new_var = build_simple_mem_ref_loc (clause_loc, new_var);
7911 54 : gcc_assert (omp_privatize_by_reference (var)
7912 : && var == orig_var);
7913 : }
7914 635 : else if (TREE_CODE (d) == ADDR_EXPR)
7915 : {
7916 304 : if (orig_var == var)
7917 : {
7918 279 : new_var = build_fold_addr_expr (new_var);
7919 279 : ref = build_fold_addr_expr (ref);
7920 : }
7921 : }
7922 : else
7923 : {
7924 331 : gcc_assert (orig_var == var);
7925 331 : if (omp_privatize_by_reference (var))
7926 79 : ref = build_fold_addr_expr (ref);
7927 : }
7928 689 : if (DECL_P (v))
7929 : {
7930 93 : tree t = maybe_lookup_decl (v, ctx);
7931 93 : if (t)
7932 88 : v = t;
7933 : else
7934 5 : v = maybe_lookup_decl_in_outer_ctx (v, ctx);
7935 93 : gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
7936 : }
7937 689 : if (!integer_zerop (bias))
7938 : {
7939 402 : bias = fold_convert_loc (clause_loc, sizetype, bias);
7940 804 : new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
7941 402 : TREE_TYPE (new_var), new_var,
7942 : unshare_expr (bias));
7943 402 : ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
7944 402 : TREE_TYPE (ref), ref, bias);
7945 : }
7946 689 : new_var = fold_convert_loc (clause_loc, ptype, new_var);
7947 689 : ref = fold_convert_loc (clause_loc, ptype, ref);
7948 689 : tree m = create_tmp_var (ptype);
7949 689 : gimplify_assign (m, new_var, stmt_seqp);
7950 689 : new_var = m;
7951 689 : m = create_tmp_var (ptype);
7952 689 : gimplify_assign (m, ref, stmt_seqp);
7953 689 : ref = m;
7954 689 : gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
7955 689 : tree body = create_artificial_label (UNKNOWN_LOCATION);
7956 689 : tree end = create_artificial_label (UNKNOWN_LOCATION);
7957 689 : gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
7958 689 : tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
7959 689 : tree out = build_simple_mem_ref_loc (clause_loc, ref);
7960 689 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
7961 : {
7962 72 : tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
7963 72 : tree decl_placeholder
7964 72 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
7965 72 : SET_DECL_VALUE_EXPR (placeholder, out);
7966 72 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
7967 72 : SET_DECL_VALUE_EXPR (decl_placeholder, priv);
7968 72 : DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
7969 72 : lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
7970 72 : gimple_seq_add_seq (&sub_seq,
7971 72 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
7972 72 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
7973 72 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
7974 72 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
7975 : }
7976 : else
7977 : {
7978 617 : tree out2 = out;
7979 617 : tree priv2 = priv;
7980 617 : if (is_truth_op)
7981 : {
7982 0 : tree zero = build_zero_cst (TREE_TYPE (out));
7983 0 : out2 = fold_build2_loc (clause_loc, NE_EXPR,
7984 : boolean_type_node, out, zero);
7985 0 : priv2 = fold_build2_loc (clause_loc, NE_EXPR,
7986 : boolean_type_node, priv, zero);
7987 : }
7988 617 : x = build2 (code, TREE_TYPE (out2), out2, priv2);
7989 617 : if (is_truth_op)
7990 0 : x = fold_convert (TREE_TYPE (out), x);
7991 617 : out = unshare_expr (out);
7992 617 : gimplify_assign (out, x, &sub_seq);
7993 : }
7994 689 : gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
7995 689 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
7996 689 : gimple_seq_add_stmt (&sub_seq, g);
7997 689 : g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
7998 689 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
7999 689 : gimple_seq_add_stmt (&sub_seq, g);
8000 689 : g = gimple_build_assign (i, PLUS_EXPR, i,
8001 689 : build_int_cst (TREE_TYPE (i), 1));
8002 689 : gimple_seq_add_stmt (&sub_seq, g);
8003 689 : g = gimple_build_cond (LE_EXPR, i, v, body, end);
8004 689 : gimple_seq_add_stmt (&sub_seq, g);
8005 689 : gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
8006 : }
8007 1416 : else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
8008 : {
8009 770 : tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
8010 :
8011 770 : if (omp_privatize_by_reference (var)
8012 815 : && !useless_type_conversion_p (TREE_TYPE (placeholder),
8013 45 : TREE_TYPE (ref)))
8014 37 : ref = build_fold_addr_expr_loc (clause_loc, ref);
8015 770 : SET_DECL_VALUE_EXPR (placeholder, ref);
8016 770 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
8017 770 : lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
8018 770 : gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
8019 770 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
8020 770 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
8021 : }
8022 : else
8023 : {
8024 646 : tree new_var2 = new_var;
8025 646 : tree ref2 = ref;
8026 646 : if (is_truth_op)
8027 : {
8028 78 : tree zero = build_zero_cst (TREE_TYPE (new_var));
8029 78 : new_var2 = fold_build2_loc (clause_loc, NE_EXPR,
8030 : boolean_type_node, new_var, zero);
8031 78 : ref2 = fold_build2_loc (clause_loc, NE_EXPR, boolean_type_node,
8032 : ref, zero);
8033 : }
8034 646 : x = build2 (code, TREE_TYPE (ref), ref2, new_var2);
8035 646 : if (is_truth_op)
8036 78 : x = fold_convert (TREE_TYPE (new_var), x);
8037 646 : ref = build_outer_var_ref (var, ctx);
8038 646 : gimplify_assign (ref, x, &sub_seq);
8039 : }
8040 : }
8041 :
8042 1053 : stmt
8043 1053 : = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_START),
8044 : 0);
8045 1053 : gimple_seq_add_stmt (stmt_seqp, stmt);
8046 :
8047 1053 : gimple_seq_add_seq (stmt_seqp, sub_seq);
8048 :
8049 1053 : if (clist)
8050 : {
8051 167 : gimple_seq_add_seq (stmt_seqp, *clist);
8052 167 : *clist = NULL;
8053 : }
8054 :
8055 1053 : stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_END),
8056 : 0);
8057 1053 : gimple_seq_add_stmt (stmt_seqp, stmt);
8058 : }
8059 :
8060 :
8061 : /* Generate code to implement the COPYPRIVATE clauses. */
8062 :
8063 : static void
8064 115 : lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
8065 : omp_context *ctx)
8066 : {
8067 115 : tree c;
8068 :
8069 463 : for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
8070 : {
8071 348 : tree var, new_var, ref, x;
8072 348 : bool by_ref;
8073 348 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
8074 :
8075 348 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
8076 6 : continue;
8077 :
8078 342 : var = OMP_CLAUSE_DECL (c);
8079 342 : by_ref = use_pointer_for_field (var, NULL);
8080 :
8081 342 : ref = build_sender_ref (var, ctx);
8082 342 : x = new_var = lookup_decl_in_outer_ctx (var, ctx);
8083 342 : if (by_ref)
8084 : {
8085 74 : x = build_fold_addr_expr_loc (clause_loc, new_var);
8086 74 : x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
8087 : }
8088 342 : gimplify_assign (ref, x, slist);
8089 :
8090 342 : ref = build_receiver_ref (var, false, ctx);
8091 342 : if (by_ref)
8092 : {
8093 74 : ref = fold_convert_loc (clause_loc,
8094 74 : build_pointer_type (TREE_TYPE (new_var)),
8095 : ref);
8096 74 : ref = build_fold_indirect_ref_loc (clause_loc, ref);
8097 : }
8098 342 : if (omp_privatize_by_reference (var))
8099 : {
8100 171 : ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
8101 171 : ref = build_simple_mem_ref_loc (clause_loc, ref);
8102 171 : new_var = build_simple_mem_ref_loc (clause_loc, new_var);
8103 : }
8104 342 : x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
8105 342 : gimplify_and_add (x, rlist);
8106 : }
8107 115 : }
8108 :
8109 :
8110 : /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
8111 : and REDUCTION from the sender (aka parent) side. */
8112 :
8113 : static void
8114 22383 : lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
8115 : omp_context *ctx)
8116 : {
8117 22383 : tree c, t;
8118 22383 : int ignored_looptemp = 0;
8119 22383 : bool is_taskloop = false;
8120 :
8121 : /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
8122 : by GOMP_taskloop. */
8123 22383 : if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
8124 : {
8125 : ignored_looptemp = 2;
8126 : is_taskloop = true;
8127 : }
8128 :
8129 116545 : for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
8130 : {
8131 94162 : tree val, ref, x, var;
8132 94162 : bool by_ref, do_in = false, do_out = false;
8133 94162 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
8134 :
8135 94162 : switch (OMP_CLAUSE_CODE (c))
8136 : {
8137 4606 : case OMP_CLAUSE_PRIVATE:
8138 4606 : if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
8139 : break;
8140 4451 : continue;
8141 : case OMP_CLAUSE_FIRSTPRIVATE:
8142 : case OMP_CLAUSE_COPYIN:
8143 : case OMP_CLAUSE_LASTPRIVATE:
8144 : case OMP_CLAUSE_IN_REDUCTION:
8145 : case OMP_CLAUSE__REDUCTEMP_:
8146 : break;
8147 4800 : case OMP_CLAUSE_REDUCTION:
8148 4800 : if (is_task_ctx (ctx) || OMP_CLAUSE_REDUCTION_TASK (c))
8149 745 : continue;
8150 : break;
8151 17340 : case OMP_CLAUSE_SHARED:
8152 17340 : if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
8153 : break;
8154 17028 : continue;
8155 18795 : case OMP_CLAUSE__LOOPTEMP_:
8156 18795 : if (ignored_looptemp)
8157 : {
8158 2660 : ignored_looptemp--;
8159 2660 : continue;
8160 : }
8161 : break;
8162 11827 : default:
8163 11827 : continue;
8164 : }
8165 :
8166 57451 : val = OMP_CLAUSE_DECL (c);
8167 57451 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
8168 53396 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)
8169 59091 : && TREE_CODE (val) == MEM_REF)
8170 : {
8171 1578 : val = TREE_OPERAND (val, 0);
8172 1578 : if (TREE_CODE (val) == POINTER_PLUS_EXPR)
8173 351 : val = TREE_OPERAND (val, 0);
8174 1578 : if (INDIRECT_REF_P (val)
8175 1494 : || TREE_CODE (val) == ADDR_EXPR)
8176 906 : val = TREE_OPERAND (val, 0);
8177 1578 : if (is_variable_sized (val))
8178 56 : continue;
8179 : }
8180 :
8181 : /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
8182 : outer taskloop region. */
8183 57395 : omp_context *ctx_for_o = ctx;
8184 57395 : if (is_taskloop
8185 3911 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
8186 57707 : && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
8187 312 : ctx_for_o = ctx->outer;
8188 :
8189 57395 : var = lookup_decl_in_outer_ctx (val, ctx_for_o);
8190 :
8191 57395 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
8192 56881 : && is_global_var (var)
8193 59700 : && (val == OMP_CLAUSE_DECL (c)
8194 273 : || !is_task_ctx (ctx)
8195 241 : || (TREE_CODE (TREE_TYPE (val)) != POINTER_TYPE
8196 187 : && (TREE_CODE (TREE_TYPE (val)) != REFERENCE_TYPE
8197 0 : || (TREE_CODE (TREE_TYPE (TREE_TYPE (val)))
8198 : != POINTER_TYPE)))))
8199 2251 : continue;
8200 :
8201 55144 : t = omp_member_access_dummy_var (var);
8202 55144 : if (t)
8203 : {
8204 249 : var = DECL_VALUE_EXPR (var);
8205 249 : tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
8206 249 : if (o != t)
8207 69 : var = unshare_and_remap (var, t, o);
8208 : else
8209 180 : var = unshare_expr (var);
8210 : }
8211 :
8212 55144 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
8213 : {
8214 : /* Handle taskloop firstprivate/lastprivate, where the
8215 : lastprivate on GIMPLE_OMP_TASK is represented as
8216 : OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
8217 79 : tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
8218 79 : x = omp_build_component_ref (ctx->sender_decl, f);
8219 79 : if (use_pointer_for_field (val, ctx))
8220 59 : var = build_fold_addr_expr (var);
8221 79 : gimplify_assign (x, var, ilist);
8222 79 : DECL_ABSTRACT_ORIGIN (f) = NULL;
8223 79 : continue;
8224 79 : }
8225 :
8226 55119 : if (((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
8227 51755 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IN_REDUCTION)
8228 4446 : || val == OMP_CLAUSE_DECL (c))
8229 108827 : && is_variable_sized (val))
8230 54 : continue;
8231 55011 : by_ref = use_pointer_for_field (val, NULL);
8232 :
8233 55011 : switch (OMP_CLAUSE_CODE (c))
8234 : {
8235 26747 : case OMP_CLAUSE_FIRSTPRIVATE:
8236 26747 : if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)
8237 7238 : && !by_ref
8238 33933 : && is_task_ctx (ctx))
8239 2325 : suppress_warning (var);
8240 : do_in = true;
8241 : break;
8242 :
8243 : case OMP_CLAUSE_PRIVATE:
8244 : case OMP_CLAUSE_COPYIN:
8245 : case OMP_CLAUSE__LOOPTEMP_:
8246 : case OMP_CLAUSE__REDUCTEMP_:
8247 : do_in = true;
8248 : break;
8249 :
8250 6458 : case OMP_CLAUSE_LASTPRIVATE:
8251 6458 : if (by_ref || omp_privatize_by_reference (val))
8252 : {
8253 384 : if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
8254 239 : continue;
8255 : do_in = true;
8256 : }
8257 : else
8258 : {
8259 6074 : do_out = true;
8260 6074 : if (lang_hooks.decls.omp_private_outer_ref (val))
8261 : do_in = true;
8262 : }
8263 : break;
8264 :
8265 4446 : case OMP_CLAUSE_REDUCTION:
8266 4446 : case OMP_CLAUSE_IN_REDUCTION:
8267 4446 : do_in = true;
8268 4446 : if (val == OMP_CLAUSE_DECL (c))
8269 : {
8270 3143 : if (is_task_ctx (ctx))
8271 301 : by_ref = use_pointer_for_field (val, ctx);
8272 : else
8273 2842 : do_out = !(by_ref || omp_privatize_by_reference (val));
8274 : }
8275 : else
8276 1303 : by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
8277 : break;
8278 :
8279 0 : default:
8280 0 : gcc_unreachable ();
8281 : }
8282 :
8283 1604 : if (do_in)
8284 : {
8285 48722 : ref = build_sender_ref (val, ctx);
8286 48722 : x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
8287 48722 : gimplify_assign (ref, x, ilist);
8288 48722 : if (is_task_ctx (ctx))
8289 6190 : DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
8290 : }
8291 :
8292 54772 : if (do_out)
8293 : {
8294 8373 : ref = build_sender_ref (val, ctx);
8295 8373 : gimplify_assign (var, ref, olist);
8296 : }
8297 : }
8298 22383 : }
8299 :
8300 : /* Generate code to implement SHARED from the sender (aka parent)
8301 : side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
8302 : list things that got automatically shared. */
8303 :
8304 : static void
8305 22383 : lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
8306 : {
8307 22383 : tree var, ovar, nvar, t, f, x, record_type;
8308 :
8309 22383 : if (ctx->record_type == NULL)
8310 4456 : return;
8311 :
8312 17927 : record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
8313 86490 : for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
8314 : {
8315 68563 : ovar = DECL_ABSTRACT_ORIGIN (f);
8316 68563 : if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
8317 6269 : continue;
8318 :
8319 62294 : nvar = maybe_lookup_decl (ovar, ctx);
8320 113180 : if (!nvar
8321 61881 : || !DECL_HAS_VALUE_EXPR_P (nvar)
8322 73888 : || (ctx->allocate_map
8323 231 : && ctx->allocate_map->get (ovar)))
8324 50886 : continue;
8325 :
8326 : /* If CTX is a nested parallel directive. Find the immediately
8327 : enclosing parallel or workshare construct that contains a
8328 : mapping for OVAR. */
8329 11408 : var = lookup_decl_in_outer_ctx (ovar, ctx);
8330 :
8331 11408 : t = omp_member_access_dummy_var (var);
8332 11408 : if (t)
8333 : {
8334 49 : var = DECL_VALUE_EXPR (var);
8335 49 : tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
8336 49 : if (o != t)
8337 18 : var = unshare_and_remap (var, t, o);
8338 : else
8339 31 : var = unshare_expr (var);
8340 : }
8341 :
8342 11408 : if (use_pointer_for_field (ovar, ctx))
8343 : {
8344 6294 : x = build_sender_ref (ovar, ctx);
8345 6294 : if (TREE_CODE (TREE_TYPE (f)) == ARRAY_TYPE
8346 6294 : && TREE_TYPE (f) == TREE_TYPE (ovar))
8347 : {
8348 97 : gcc_assert (is_parallel_ctx (ctx)
8349 : && DECL_ARTIFICIAL (ovar));
8350 : /* _condtemp_ clause. */
8351 97 : var = build_constructor (TREE_TYPE (x), NULL);
8352 : }
8353 : else
8354 6197 : var = build_fold_addr_expr (var);
8355 6294 : gimplify_assign (x, var, ilist);
8356 : }
8357 : else
8358 : {
8359 5114 : x = build_sender_ref (ovar, ctx);
8360 5114 : gimplify_assign (x, var, ilist);
8361 :
8362 5114 : if (!TREE_READONLY (var)
8363 : /* We don't need to receive a new reference to a result
8364 : or parm decl. In fact we may not store to it as we will
8365 : invalidate any pending RSO and generate wrong gimple
8366 : during inlining. */
8367 5114 : && !((TREE_CODE (var) == RESULT_DECL
8368 3296 : || TREE_CODE (var) == PARM_DECL)
8369 182 : && DECL_BY_REFERENCE (var)))
8370 : {
8371 3225 : x = build_sender_ref (ovar, ctx);
8372 3225 : gimplify_assign (var, x, olist);
8373 : }
8374 : }
8375 : }
8376 : }
8377 :
8378 : /* Emit an OpenACC head marker call, encapulating the partitioning and
8379 : other information that must be processed by the target compiler.
8380 : Return the maximum number of dimensions the associated loop might
8381 : be partitioned over. */
8382 :
8383 : static unsigned
8384 9665 : lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
8385 : gimple_seq *seq, omp_context *ctx)
8386 : {
8387 9665 : unsigned levels = 0;
8388 9665 : unsigned tag = 0;
8389 9665 : tree gang_static = NULL_TREE;
8390 9665 : auto_vec<tree, 5> args;
8391 :
8392 19330 : args.quick_push (build_int_cst
8393 9665 : (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
8394 9665 : args.quick_push (ddvar);
8395 30854 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
8396 : {
8397 21189 : switch (OMP_CLAUSE_CODE (c))
8398 : {
8399 1856 : case OMP_CLAUSE_GANG:
8400 1856 : tag |= OLF_DIM_GANG;
8401 1856 : gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
8402 : /* static:* is represented by -1, and we can ignore it, as
8403 : scheduling is always static. */
8404 1856 : if (gang_static && integer_minus_onep (gang_static))
8405 70 : gang_static = NULL_TREE;
8406 1856 : levels++;
8407 1856 : break;
8408 :
8409 1330 : case OMP_CLAUSE_WORKER:
8410 1330 : tag |= OLF_DIM_WORKER;
8411 1330 : levels++;
8412 1330 : break;
8413 :
8414 1523 : case OMP_CLAUSE_VECTOR:
8415 1523 : tag |= OLF_DIM_VECTOR;
8416 1523 : levels++;
8417 1523 : break;
8418 :
8419 314 : case OMP_CLAUSE_SEQ:
8420 314 : tag |= OLF_SEQ;
8421 314 : break;
8422 :
8423 409 : case OMP_CLAUSE_AUTO:
8424 409 : tag |= OLF_AUTO;
8425 409 : break;
8426 :
8427 260 : case OMP_CLAUSE_INDEPENDENT:
8428 260 : tag |= OLF_INDEPENDENT;
8429 260 : break;
8430 :
8431 136 : case OMP_CLAUSE_TILE:
8432 136 : tag |= OLF_TILE;
8433 136 : break;
8434 :
8435 3986 : case OMP_CLAUSE_REDUCTION:
8436 3986 : tag |= OLF_REDUCTION;
8437 3986 : break;
8438 :
8439 11375 : default:
8440 11375 : continue;
8441 : }
8442 : }
8443 :
8444 9665 : if (gang_static)
8445 : {
8446 146 : if (DECL_P (gang_static))
8447 16 : gang_static = build_outer_var_ref (gang_static, ctx);
8448 146 : tag |= OLF_GANG_STATIC;
8449 : }
8450 :
8451 9665 : omp_context *tgt = enclosing_target_ctx (ctx);
8452 9665 : if (!tgt || is_oacc_parallel_or_serial (tgt))
8453 : ;
8454 62 : else if (is_oacc_kernels (tgt))
8455 : /* Not using this loops handling inside OpenACC 'kernels' regions. */
8456 0 : gcc_unreachable ();
8457 62 : else if (is_oacc_kernels_decomposed_part (tgt))
8458 : ;
8459 : else
8460 0 : gcc_unreachable ();
8461 :
8462 : /* In a parallel region, loops are implicitly INDEPENDENT. */
8463 9665 : if (!tgt || is_oacc_parallel_or_serial (tgt))
8464 9603 : tag |= OLF_INDEPENDENT;
8465 :
8466 : /* Loops inside OpenACC 'kernels' decomposed parts' regions are expected to
8467 : have an explicit 'seq' or 'independent' clause, and no 'auto' clause. */
8468 9665 : if (tgt && is_oacc_kernels_decomposed_part (tgt))
8469 : {
8470 62 : gcc_assert (tag & (OLF_SEQ | OLF_INDEPENDENT));
8471 62 : gcc_assert (!(tag & OLF_AUTO));
8472 : }
8473 :
8474 9665 : if (tag & OLF_TILE)
8475 : /* Tiling could use all 3 levels. */
8476 : levels = 3;
8477 : else
8478 : {
8479 : /* A loop lacking SEQ, GANG, WORKER and/or VECTOR could be AUTO.
8480 : Ensure at least one level, or 2 for possible auto
8481 : partitioning */
8482 9529 : bool maybe_auto = !(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
8483 : << OLF_DIM_BASE) | OLF_SEQ));
8484 :
8485 9529 : if (levels < 1u + maybe_auto)
8486 : levels = 1u + maybe_auto;
8487 : }
8488 :
8489 9665 : args.quick_push (build_int_cst (integer_type_node, levels));
8490 9665 : args.quick_push (build_int_cst (integer_type_node, tag));
8491 9665 : if (gang_static)
8492 146 : args.quick_push (gang_static);
8493 :
8494 9665 : gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
8495 9665 : gimple_set_location (call, loc);
8496 9665 : gimple_set_lhs (call, ddvar);
8497 9665 : gimple_seq_add_stmt (seq, call);
8498 :
8499 9665 : return levels;
8500 9665 : }
8501 :
8502 : /* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
8503 : partitioning level of the enclosed region. */
8504 :
8505 : static void
8506 42767 : lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
8507 : tree tofollow, gimple_seq *seq)
8508 : {
8509 42767 : int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
8510 : : IFN_UNIQUE_OACC_TAIL_MARK);
8511 42767 : tree marker = build_int_cst (integer_type_node, marker_kind);
8512 42767 : int nargs = 2 + (tofollow != NULL_TREE);
8513 42767 : gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
8514 : marker, ddvar, tofollow);
8515 42767 : gimple_set_location (call, loc);
8516 42767 : gimple_set_lhs (call, ddvar);
8517 42767 : gimple_seq_add_stmt (seq, call);
8518 42767 : }
8519 :
8520 : /* Generate the before and after OpenACC loop sequences. CLAUSES are
8521 : the loop clauses, from which we extract reductions. Initialize
8522 : HEAD and TAIL. */
8523 :
8524 : static void
8525 9665 : lower_oacc_head_tail (location_t loc, tree clauses, gcall *private_marker,
8526 : gimple_seq *head, gimple_seq *tail, omp_context *ctx)
8527 : {
8528 9665 : bool inner = false;
8529 9665 : tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
8530 9665 : gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
8531 :
8532 9665 : unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
8533 :
8534 9665 : if (private_marker)
8535 : {
8536 229 : gimple_set_location (private_marker, loc);
8537 229 : gimple_call_set_lhs (private_marker, ddvar);
8538 229 : gimple_call_set_arg (private_marker, 1, ddvar);
8539 : }
8540 :
8541 9665 : tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
8542 9665 : tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
8543 :
8544 9665 : gcc_assert (count);
8545 26216 : for (unsigned done = 1; count; count--, done++)
8546 : {
8547 16551 : gimple_seq fork_seq = NULL;
8548 16551 : gimple_seq join_seq = NULL;
8549 :
8550 16551 : tree place = build_int_cst (integer_type_node, -1);
8551 16551 : gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
8552 : fork_kind, ddvar, place);
8553 16551 : gimple_set_location (fork, loc);
8554 16551 : gimple_set_lhs (fork, ddvar);
8555 :
8556 16551 : gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
8557 : join_kind, ddvar, place);
8558 16551 : gimple_set_location (join, loc);
8559 16551 : gimple_set_lhs (join, ddvar);
8560 :
8561 : /* Mark the beginning of this level sequence. */
8562 16551 : if (inner)
8563 6886 : lower_oacc_loop_marker (loc, ddvar, true,
8564 6886 : build_int_cst (integer_type_node, count),
8565 : &fork_seq);
8566 16551 : lower_oacc_loop_marker (loc, ddvar, false,
8567 16551 : build_int_cst (integer_type_node, done),
8568 : &join_seq);
8569 :
8570 23437 : lower_oacc_reductions (loc, clauses, place, inner,
8571 : fork, (count == 1) ? private_marker : NULL,
8572 : join, &fork_seq, &join_seq, ctx);
8573 :
8574 : /* Append this level to head. */
8575 16551 : gimple_seq_add_seq (head, fork_seq);
8576 : /* Prepend it to tail. */
8577 16551 : gimple_seq_add_seq (&join_seq, *tail);
8578 16551 : *tail = join_seq;
8579 :
8580 16551 : inner = true;
8581 : }
8582 :
8583 : /* Mark the end of the sequence. */
8584 9665 : lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
8585 9665 : lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
8586 9665 : }
8587 :
8588 : /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
8589 : catch handler and return it. This prevents programs from violating the
8590 : structured block semantics with throws. */
8591 :
8592 : static gimple_seq
8593 95066 : maybe_catch_exception (gimple_seq body)
8594 : {
8595 95066 : gimple *g;
8596 95066 : tree decl;
8597 :
8598 95066 : if (!flag_exceptions)
8599 : return body;
8600 :
8601 42682 : if (lang_hooks.eh_protect_cleanup_actions != NULL)
8602 42654 : decl = lang_hooks.eh_protect_cleanup_actions ();
8603 : else
8604 28 : decl = builtin_decl_explicit (BUILT_IN_TRAP);
8605 :
8606 42682 : g = gimple_build_eh_must_not_throw (decl);
8607 42682 : g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
8608 : GIMPLE_TRY_CATCH);
8609 :
8610 42682 : return gimple_seq_alloc_with_stmt (g);
8611 : }
8612 :
8613 :
8614 : /* Routines to lower OMP directives into OMP-GIMPLE. */
8615 :
8616 : /* If ctx is a worksharing context inside of a cancellable parallel
8617 : region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8618 : and conditional branch to parallel's cancel_label to handle
8619 : cancellation in the implicit barrier. */
8620 :
8621 : static void
8622 48517 : maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple *omp_return,
8623 : gimple_seq *body)
8624 : {
8625 48517 : gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8626 48517 : if (gimple_omp_return_nowait_p (omp_return))
8627 : return;
8628 19520 : for (omp_context *outer = ctx->outer; outer; outer = outer->outer)
8629 15943 : if (gimple_code (outer->stmt) == GIMPLE_OMP_PARALLEL
8630 15943 : && outer->cancellable)
8631 : {
8632 40 : tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
8633 40 : tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
8634 40 : tree lhs = create_tmp_var (c_bool_type);
8635 40 : gimple_omp_return_set_lhs (omp_return, lhs);
8636 40 : tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8637 40 : gimple *g = gimple_build_cond (NE_EXPR, lhs,
8638 : fold_convert (c_bool_type,
8639 : boolean_false_node),
8640 : outer->cancel_label, fallthru_label);
8641 40 : gimple_seq_add_stmt (body, g);
8642 40 : gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8643 : }
8644 15903 : else if (gimple_code (outer->stmt) != GIMPLE_OMP_TASKGROUP
8645 15903 : && gimple_code (outer->stmt) != GIMPLE_OMP_SCOPE)
8646 : return;
8647 : }
8648 :
8649 : /* Find the first task_reduction or reduction clause or return NULL
8650 : if there are none. */
8651 :
8652 : static inline tree
8653 48764 : omp_task_reductions_find_first (tree clauses, enum tree_code code,
8654 : enum omp_clause_code ccode)
8655 : {
8656 64110 : while (1)
8657 : {
8658 56437 : clauses = omp_find_clause (clauses, ccode);
8659 56437 : if (clauses == NULL_TREE)
8660 : return NULL_TREE;
8661 9119 : if (ccode != OMP_CLAUSE_REDUCTION
8662 9119 : || code == OMP_TASKLOOP
8663 9119 : || OMP_CLAUSE_REDUCTION_TASK (clauses))
8664 : return clauses;
8665 7673 : clauses = OMP_CLAUSE_CHAIN (clauses);
8666 : }
8667 : }
8668 :
8669 : static void lower_omp_task_reductions (omp_context *, enum tree_code, tree,
8670 : gimple_seq *, gimple_seq *);
8671 :
8672 : /* Lower the OpenMP sections directive in the current statement in GSI_P.
8673 : CTX is the enclosing OMP context for the current statement. */
8674 :
8675 : static void
8676 386 : lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8677 : {
8678 386 : tree block, control;
8679 386 : gimple_stmt_iterator tgsi;
8680 386 : gomp_sections *stmt;
8681 386 : gimple *t;
8682 386 : gbind *new_stmt, *bind;
8683 386 : gimple_seq ilist, dlist, olist, tred_dlist = NULL, clist = NULL, new_body;
8684 :
8685 386 : stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
8686 :
8687 386 : push_gimplify_context ();
8688 :
8689 386 : dlist = NULL;
8690 386 : ilist = NULL;
8691 :
8692 386 : tree rclauses
8693 386 : = omp_task_reductions_find_first (gimple_omp_sections_clauses (stmt),
8694 : OMP_SECTIONS, OMP_CLAUSE_REDUCTION);
8695 386 : tree rtmp = NULL_TREE;
8696 386 : if (rclauses)
8697 : {
8698 8 : tree type = build_pointer_type (pointer_sized_int_node);
8699 8 : tree temp = create_tmp_var (type);
8700 8 : tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__REDUCTEMP_);
8701 8 : OMP_CLAUSE_DECL (c) = temp;
8702 8 : OMP_CLAUSE_CHAIN (c) = gimple_omp_sections_clauses (stmt);
8703 8 : gimple_omp_sections_set_clauses (stmt, c);
8704 8 : lower_omp_task_reductions (ctx, OMP_SECTIONS,
8705 : gimple_omp_sections_clauses (stmt),
8706 : &ilist, &tred_dlist);
8707 8 : rclauses = c;
8708 8 : rtmp = make_ssa_name (type);
8709 8 : gimple_seq_add_stmt (&ilist, gimple_build_assign (rtmp, temp));
8710 : }
8711 :
8712 386 : tree *clauses_ptr = gimple_omp_sections_clauses_ptr (stmt);
8713 386 : lower_lastprivate_conditional_clauses (clauses_ptr, ctx);
8714 :
8715 386 : lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8716 : &ilist, &dlist, ctx, NULL);
8717 :
8718 386 : control = create_tmp_var (unsigned_type_node, ".section");
8719 386 : gimple_omp_sections_set_control (stmt, control);
8720 :
8721 386 : new_body = gimple_omp_body (stmt);
8722 386 : gimple_omp_set_body (stmt, NULL);
8723 386 : tgsi = gsi_start (new_body);
8724 1249 : for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8725 : {
8726 863 : omp_context *sctx;
8727 863 : gimple *sec_start;
8728 :
8729 863 : sec_start = gsi_stmt (tgsi);
8730 863 : sctx = maybe_lookup_ctx (sec_start);
8731 863 : gcc_assert (sctx);
8732 :
8733 863 : lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8734 863 : gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8735 : GSI_CONTINUE_LINKING);
8736 863 : gimple_omp_set_body (sec_start, NULL);
8737 :
8738 863 : if (gsi_one_before_end_p (tgsi))
8739 : {
8740 386 : gimple_seq l = NULL;
8741 386 : lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8742 : &ilist, &l, &clist, ctx);
8743 386 : gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8744 386 : gimple_omp_section_set_last (sec_start);
8745 : }
8746 :
8747 863 : gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8748 : GSI_CONTINUE_LINKING);
8749 : }
8750 :
8751 386 : block = make_node (BLOCK);
8752 386 : bind = gimple_build_bind (NULL, new_body, block);
8753 :
8754 386 : olist = NULL;
8755 386 : lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist,
8756 : &clist, ctx);
8757 386 : if (clist)
8758 : {
8759 10 : tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_START);
8760 10 : gcall *g = gimple_build_call (fndecl, 0);
8761 10 : gimple_seq_add_stmt (&olist, g);
8762 10 : gimple_seq_add_seq (&olist, clist);
8763 10 : fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_END);
8764 10 : g = gimple_build_call (fndecl, 0);
8765 10 : gimple_seq_add_stmt (&olist, g);
8766 : }
8767 :
8768 386 : block = make_node (BLOCK);
8769 386 : new_stmt = gimple_build_bind (NULL, NULL, block);
8770 386 : gsi_replace (gsi_p, new_stmt, true);
8771 :
8772 386 : pop_gimplify_context (new_stmt);
8773 386 : gimple_bind_append_vars (new_stmt, ctx->block_vars);
8774 386 : BLOCK_VARS (block) = gimple_bind_vars (bind);
8775 386 : if (BLOCK_VARS (block))
8776 0 : TREE_USED (block) = 1;
8777 :
8778 386 : new_body = NULL;
8779 386 : gimple_seq_add_seq (&new_body, ilist);
8780 386 : gimple_seq_add_stmt (&new_body, stmt);
8781 386 : gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
8782 386 : gimple_seq_add_stmt (&new_body, bind);
8783 :
8784 386 : t = gimple_build_omp_continue (control, control);
8785 386 : gimple_seq_add_stmt (&new_body, t);
8786 :
8787 386 : gimple_seq_add_seq (&new_body, olist);
8788 386 : if (ctx->cancellable)
8789 19 : gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
8790 386 : gimple_seq_add_seq (&new_body, dlist);
8791 :
8792 386 : new_body = maybe_catch_exception (new_body);
8793 :
8794 386 : bool nowait = omp_find_clause (gimple_omp_sections_clauses (stmt),
8795 386 : OMP_CLAUSE_NOWAIT) != NULL_TREE;
8796 386 : t = gimple_build_omp_return (nowait);
8797 386 : gimple_seq_add_stmt (&new_body, t);
8798 386 : gimple_seq_add_seq (&new_body, tred_dlist);
8799 386 : maybe_add_implicit_barrier_cancel (ctx, t, &new_body);
8800 :
8801 386 : if (rclauses)
8802 8 : OMP_CLAUSE_DECL (rclauses) = rtmp;
8803 :
8804 386 : gimple_bind_set_body (new_stmt, new_body);
8805 386 : }
8806 :
8807 :
8808 : /* A subroutine of lower_omp_single. Expand the simple form of
8809 : a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8810 :
8811 : if (GOMP_single_start ())
8812 : BODY;
8813 : [ GOMP_barrier (); ] -> unless 'nowait' is present.
8814 :
8815 : FIXME. It may be better to delay expanding the logic of this until
8816 : pass_expand_omp. The expanded logic may make the job more difficult
8817 : to a synchronization analysis pass. */
8818 :
8819 : static void
8820 1012 : lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
8821 : {
8822 1012 : location_t loc = gimple_location (single_stmt);
8823 1012 : tree tlabel = create_artificial_label (loc);
8824 1012 : tree flabel = create_artificial_label (loc);
8825 1012 : gimple *call, *cond;
8826 1012 : tree lhs, decl;
8827 :
8828 2020 : decl = builtin_decl_explicit (flag_openmp_ompt
8829 : ? BUILT_IN_GOMP_SINGLE_START_WITH_END
8830 : : BUILT_IN_GOMP_SINGLE_START);
8831 1012 : lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
8832 1012 : call = gimple_build_call (decl, 0);
8833 1012 : gimple_call_set_lhs (call, lhs);
8834 1012 : gimple_seq_add_stmt (pre_p, call);
8835 :
8836 1012 : cond = gimple_build_cond (EQ_EXPR, lhs,
8837 1012 : fold_convert_loc (loc, TREE_TYPE (lhs),
8838 : boolean_true_node),
8839 : tlabel, flabel);
8840 1012 : gimple_seq_add_stmt (pre_p, cond);
8841 1012 : gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
8842 1012 : gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8843 1012 : gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
8844 1012 : }
8845 :
8846 :
8847 : /* A subroutine of lower_omp_single. Expand the simple form of
8848 : a GIMPLE_OMP_SINGLE, with a copyprivate clause:
8849 :
8850 : #pragma omp single copyprivate (a, b, c)
8851 :
8852 : Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
8853 :
8854 : {
8855 : if ((copyout_p = GOMP_single_copy_start ()) == NULL)
8856 : {
8857 : BODY;
8858 : copyout.a = a;
8859 : copyout.b = b;
8860 : copyout.c = c;
8861 : GOMP_single_copy_end (©out);
8862 : }
8863 : else
8864 : {
8865 : a = copyout_p->a;
8866 : b = copyout_p->b;
8867 : c = copyout_p->c;
8868 : }
8869 : GOMP_barrier ();
8870 : }
8871 :
8872 : FIXME. It may be better to delay expanding the logic of this until
8873 : pass_expand_omp. The expanded logic may make the job more difficult
8874 : to a synchronization analysis pass. */
8875 :
8876 : static void
8877 115 : lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
8878 : omp_context *ctx)
8879 : {
8880 115 : tree ptr_type, t, l0, l1, l2, bfn_decl;
8881 115 : gimple_seq copyin_seq;
8882 115 : location_t loc = gimple_location (single_stmt);
8883 :
8884 115 : ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
8885 :
8886 115 : ptr_type = build_pointer_type (ctx->record_type);
8887 115 : ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
8888 :
8889 115 : l0 = create_artificial_label (loc);
8890 115 : l1 = create_artificial_label (loc);
8891 115 : l2 = create_artificial_label (loc);
8892 :
8893 115 : bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
8894 115 : t = build_call_expr_loc (loc, bfn_decl, 0);
8895 115 : t = fold_convert_loc (loc, ptr_type, t);
8896 115 : gimplify_assign (ctx->receiver_decl, t, pre_p);
8897 :
8898 115 : t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
8899 : build_int_cst (ptr_type, 0));
8900 115 : t = build3 (COND_EXPR, void_type_node, t,
8901 : build_and_jump (&l0), build_and_jump (&l1));
8902 115 : gimplify_and_add (t, pre_p);
8903 :
8904 115 : gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
8905 :
8906 115 : gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8907 :
8908 115 : copyin_seq = NULL;
8909 115 : lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
8910 : ©in_seq, ctx);
8911 :
8912 115 : t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
8913 115 : bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
8914 115 : t = build_call_expr_loc (loc, bfn_decl, 1, t);
8915 115 : gimplify_and_add (t, pre_p);
8916 :
8917 115 : t = build_and_jump (&l2);
8918 115 : gimplify_and_add (t, pre_p);
8919 :
8920 115 : gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
8921 :
8922 115 : gimple_seq_add_seq (pre_p, copyin_seq);
8923 :
8924 115 : gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
8925 115 : }
8926 :
8927 :
8928 : /* Expand code for an OpenMP single directive. */
8929 :
8930 : static void
8931 1127 : lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8932 : {
8933 1127 : tree block;
8934 1127 : gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
8935 1127 : gbind *bind;
8936 1127 : gimple_seq bind_body, bind_body_tail = NULL, dlist;
8937 :
8938 1127 : push_gimplify_context ();
8939 :
8940 1127 : block = make_node (BLOCK);
8941 1127 : bind = gimple_build_bind (NULL, NULL, block);
8942 1127 : gsi_replace (gsi_p, bind, true);
8943 1127 : bind_body = NULL;
8944 1127 : dlist = NULL;
8945 1127 : lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
8946 : &bind_body, &dlist, ctx, NULL);
8947 1127 : lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
8948 :
8949 1127 : gimple_seq_add_stmt (&bind_body, single_stmt);
8950 :
8951 1127 : if (ctx->record_type)
8952 115 : lower_omp_single_copy (single_stmt, &bind_body, ctx);
8953 : else
8954 1012 : lower_omp_single_simple (single_stmt, &bind_body);
8955 :
8956 1127 : gimple_omp_set_body (single_stmt, NULL);
8957 :
8958 1127 : gimple_seq_add_seq (&bind_body, dlist);
8959 :
8960 1127 : bind_body = maybe_catch_exception (bind_body);
8961 :
8962 1127 : bool nowait = omp_find_clause (gimple_omp_single_clauses (single_stmt),
8963 1127 : OMP_CLAUSE_NOWAIT) != NULL_TREE;
8964 1127 : gimple *g = gimple_build_omp_return (nowait);
8965 1127 : gimple_seq_add_stmt (&bind_body_tail, g);
8966 1127 : maybe_add_implicit_barrier_cancel (ctx, g, &bind_body_tail);
8967 :
8968 1127 : if (flag_openmp_ompt && !ctx->record_type)
8969 : {
8970 : /* Insert call to GOMP_single_end. */
8971 4 : tree decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_END);
8972 4 : gimple *stmt = gimple_build_call (decl, 0);
8973 4 : gimple_seq_add_stmt (&bind_body_tail, stmt);
8974 : }
8975 :
8976 1127 : if (ctx->record_type)
8977 : {
8978 115 : gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
8979 115 : tree clobber = build_clobber (ctx->record_type);
8980 115 : gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
8981 : clobber), GSI_SAME_STMT);
8982 : }
8983 1127 : gimple_seq_add_seq (&bind_body, bind_body_tail);
8984 1127 : gimple_bind_set_body (bind, bind_body);
8985 :
8986 1127 : pop_gimplify_context (bind);
8987 :
8988 1127 : gimple_bind_append_vars (bind, ctx->block_vars);
8989 1127 : BLOCK_VARS (block) = ctx->block_vars;
8990 1127 : if (BLOCK_VARS (block))
8991 26 : TREE_USED (block) = 1;
8992 1127 : }
8993 :
8994 :
8995 : /* Lower code for an OMP scope directive. */
8996 :
8997 : static void
8998 145 : lower_omp_scope (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8999 : {
9000 145 : tree block;
9001 145 : gimple *scope_stmt = gsi_stmt (*gsi_p);
9002 145 : gbind *bind;
9003 145 : gimple_seq bind_body, bind_body_tail = NULL, dlist;
9004 145 : gimple_seq tred_dlist = NULL;
9005 :
9006 145 : push_gimplify_context ();
9007 :
9008 145 : block = make_node (BLOCK);
9009 145 : bind = gimple_build_bind (NULL, NULL, block);
9010 145 : gsi_replace (gsi_p, bind, true);
9011 145 : bind_body = NULL;
9012 145 : dlist = NULL;
9013 :
9014 145 : tree rclauses
9015 145 : = omp_task_reductions_find_first (gimple_omp_scope_clauses (scope_stmt),
9016 : OMP_SCOPE, OMP_CLAUSE_REDUCTION);
9017 145 : if (rclauses)
9018 : {
9019 46 : tree type = build_pointer_type (pointer_sized_int_node);
9020 46 : tree temp = create_tmp_var (type);
9021 46 : tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__REDUCTEMP_);
9022 46 : OMP_CLAUSE_DECL (c) = temp;
9023 46 : OMP_CLAUSE_CHAIN (c) = gimple_omp_scope_clauses (scope_stmt);
9024 46 : gimple_omp_scope_set_clauses (scope_stmt, c);
9025 46 : lower_omp_task_reductions (ctx, OMP_SCOPE,
9026 : gimple_omp_scope_clauses (scope_stmt),
9027 : &bind_body, &tred_dlist);
9028 46 : rclauses = c;
9029 46 : tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_SCOPE_START);
9030 46 : gimple *stmt = gimple_build_call (fndecl, 1, temp);
9031 46 : gimple_seq_add_stmt (&bind_body, stmt);
9032 : }
9033 :
9034 145 : lower_rec_input_clauses (gimple_omp_scope_clauses (scope_stmt),
9035 : &bind_body, &dlist, ctx, NULL);
9036 145 : lower_omp (gimple_omp_body_ptr (scope_stmt), ctx);
9037 :
9038 145 : gimple_seq_add_stmt (&bind_body, scope_stmt);
9039 :
9040 145 : gimple_seq_add_seq (&bind_body, gimple_omp_body (scope_stmt));
9041 :
9042 145 : gimple_omp_set_body (scope_stmt, NULL);
9043 :
9044 145 : gimple_seq clist = NULL;
9045 145 : lower_reduction_clauses (gimple_omp_scope_clauses (scope_stmt),
9046 : &bind_body, &clist, ctx);
9047 145 : if (clist)
9048 : {
9049 0 : tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_START);
9050 0 : gcall *g = gimple_build_call (fndecl, 0);
9051 0 : gimple_seq_add_stmt (&bind_body, g);
9052 0 : gimple_seq_add_seq (&bind_body, clist);
9053 0 : fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_END);
9054 0 : g = gimple_build_call (fndecl, 0);
9055 0 : gimple_seq_add_stmt (&bind_body, g);
9056 : }
9057 :
9058 145 : gimple_seq_add_seq (&bind_body, dlist);
9059 :
9060 145 : bind_body = maybe_catch_exception (bind_body);
9061 :
9062 145 : bool nowait = omp_find_clause (gimple_omp_scope_clauses (scope_stmt),
9063 145 : OMP_CLAUSE_NOWAIT) != NULL_TREE;
9064 145 : gimple *g = gimple_build_omp_return (nowait);
9065 145 : gimple_seq_add_stmt (&bind_body_tail, g);
9066 145 : gimple_seq_add_seq (&bind_body_tail, tred_dlist);
9067 145 : maybe_add_implicit_barrier_cancel (ctx, g, &bind_body_tail);
9068 145 : if (ctx->record_type)
9069 : {
9070 0 : gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
9071 0 : tree clobber = build_clobber (ctx->record_type);
9072 0 : gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
9073 : clobber), GSI_SAME_STMT);
9074 : }
9075 145 : gimple_seq_add_seq (&bind_body, bind_body_tail);
9076 :
9077 145 : gimple_bind_set_body (bind, bind_body);
9078 :
9079 145 : pop_gimplify_context (bind);
9080 :
9081 145 : gimple_bind_append_vars (bind, ctx->block_vars);
9082 145 : BLOCK_VARS (block) = ctx->block_vars;
9083 145 : if (BLOCK_VARS (block))
9084 113 : TREE_USED (block) = 1;
9085 145 : }
9086 :
9087 : /* Lower code for an OMP dispatch directive. */
9088 :
9089 : static void
9090 659 : lower_omp_dispatch (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9091 : {
9092 659 : tree block;
9093 659 : gimple *stmt = gsi_stmt (*gsi_p);
9094 659 : gbind *bind;
9095 :
9096 659 : push_gimplify_context ();
9097 :
9098 659 : block = make_node (BLOCK);
9099 659 : bind = gimple_build_bind (NULL, NULL, block);
9100 659 : gsi_replace (gsi_p, bind, true);
9101 :
9102 659 : lower_omp (gimple_omp_body_ptr (stmt), ctx);
9103 659 : gimple_bind_set_body (bind, maybe_catch_exception (gimple_omp_body (stmt)));
9104 :
9105 659 : pop_gimplify_context (bind);
9106 :
9107 659 : gimple_bind_append_vars (bind, ctx->block_vars);
9108 659 : BLOCK_VARS (block) = ctx->block_vars;
9109 659 : }
9110 :
9111 : /* Expand code for an OpenMP master or masked directive. */
9112 :
9113 : static void
9114 1118 : lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9115 : {
9116 1118 : tree block, lab = NULL, x, bfn_decl;
9117 1118 : gimple *stmt = gsi_stmt (*gsi_p);
9118 1118 : gbind *bind;
9119 1118 : location_t loc = gimple_location (stmt);
9120 1118 : gimple_seq tseq;
9121 1118 : tree filter = integer_zero_node;
9122 :
9123 1118 : push_gimplify_context ();
9124 :
9125 1118 : if (gimple_code (stmt) == GIMPLE_OMP_MASKED)
9126 : {
9127 387 : filter = omp_find_clause (gimple_omp_masked_clauses (stmt),
9128 : OMP_CLAUSE_FILTER);
9129 387 : if (filter)
9130 252 : filter = fold_convert (integer_type_node,
9131 : OMP_CLAUSE_FILTER_EXPR (filter));
9132 : else
9133 135 : filter = integer_zero_node;
9134 : }
9135 1118 : block = make_node (BLOCK);
9136 1118 : bind = gimple_build_bind (NULL, NULL, block);
9137 1118 : gsi_replace (gsi_p, bind, true);
9138 1118 : gimple_bind_add_stmt (bind, stmt);
9139 :
9140 1118 : bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_HAS_MASKED_THREAD_NUM);
9141 1118 : x = build_call_expr_loc (loc, bfn_decl, 1, filter);
9142 1118 : x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
9143 1118 : tseq = NULL;
9144 1118 : gimplify_and_add (x, &tseq);
9145 1118 : gimple_bind_add_seq (bind, tseq);
9146 :
9147 1118 : lower_omp (gimple_omp_body_ptr (stmt), ctx);
9148 1118 : gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9149 1118 : gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9150 1118 : gimple_omp_set_body (stmt, NULL);
9151 :
9152 1118 : if (flag_openmp_ompt)
9153 : {
9154 : /* Insert call to GOMP_masked_end at the end of the body. */
9155 4 : tree decl = builtin_decl_explicit (BUILT_IN_GOMP_MASKED_END);
9156 4 : gcall *g = gimple_build_call (decl, 0);
9157 4 : gimple_bind_add_stmt (bind, g);
9158 : }
9159 :
9160 1118 : gimple_bind_add_stmt (bind, gimple_build_label (lab));
9161 :
9162 1118 : gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9163 :
9164 1118 : pop_gimplify_context (bind);
9165 :
9166 1118 : gimple_bind_append_vars (bind, ctx->block_vars);
9167 1118 : BLOCK_VARS (block) = ctx->block_vars;
9168 1118 : }
9169 :
9170 : /* Helper function for lower_omp_task_reductions. For a specific PASS
9171 : find out the current clause it should be processed, or return false
9172 : if all have been processed already. */
9173 :
9174 : static inline bool
9175 7952 : omp_task_reduction_iterate (int pass, enum tree_code code,
9176 : enum omp_clause_code ccode, tree *c, tree *decl,
9177 : tree *type, tree *next)
9178 : {
9179 11300 : for (; *c; *c = omp_find_clause (OMP_CLAUSE_CHAIN (*c), ccode))
9180 : {
9181 6696 : if (ccode == OMP_CLAUSE_REDUCTION
9182 6640 : && code != OMP_TASKLOOP
9183 6640 : && !OMP_CLAUSE_REDUCTION_TASK (*c))
9184 56 : continue;
9185 6584 : *decl = OMP_CLAUSE_DECL (*c);
9186 6584 : *type = TREE_TYPE (*decl);
9187 6584 : if (TREE_CODE (*decl) == MEM_REF)
9188 : {
9189 1940 : if (pass != 1)
9190 970 : continue;
9191 : }
9192 : else
9193 : {
9194 4644 : if (omp_privatize_by_reference (*decl))
9195 152 : *type = TREE_TYPE (*type);
9196 4644 : if (pass != (!TREE_CONSTANT (TYPE_SIZE_UNIT (*type))))
9197 2322 : continue;
9198 : }
9199 3292 : *next = omp_find_clause (OMP_CLAUSE_CHAIN (*c), ccode);
9200 3292 : return true;
9201 : }
9202 4660 : *decl = NULL_TREE;
9203 4660 : *type = NULL_TREE;
9204 4660 : *next = NULL_TREE;
9205 4660 : return false;
9206 : }
9207 :
9208 : /* Lower task_reduction and reduction clauses (the latter unless CODE is
9209 : OMP_TASKGROUP only with task modifier). Register mapping of those in
9210 : START sequence and reducing them and unregister them in the END sequence. */
9211 :
9212 : static void
9213 1374 : lower_omp_task_reductions (omp_context *ctx, enum tree_code code, tree clauses,
9214 : gimple_seq *start, gimple_seq *end)
9215 : {
9216 838 : enum omp_clause_code ccode
9217 : = (code == OMP_TASKGROUP
9218 1374 : ? OMP_CLAUSE_TASK_REDUCTION : OMP_CLAUSE_REDUCTION);
9219 1374 : tree cancellable = NULL_TREE;
9220 1374 : clauses = omp_task_reductions_find_first (clauses, code, ccode);
9221 1374 : if (clauses == NULL_TREE)
9222 209 : return;
9223 1165 : if (code == OMP_FOR || code == OMP_SECTIONS || code == OMP_SCOPE)
9224 : {
9225 316 : for (omp_context *outer = ctx->outer; outer; outer = outer->outer)
9226 238 : if (gimple_code (outer->stmt) == GIMPLE_OMP_PARALLEL
9227 238 : && outer->cancellable)
9228 : {
9229 14 : cancellable = error_mark_node;
9230 14 : break;
9231 : }
9232 224 : else if (gimple_code (outer->stmt) != GIMPLE_OMP_TASKGROUP
9233 224 : && gimple_code (outer->stmt) != GIMPLE_OMP_SCOPE)
9234 : break;
9235 : }
9236 1165 : tree record_type = lang_hooks.types.make_type (RECORD_TYPE);
9237 1165 : tree *last = &TYPE_FIELDS (record_type);
9238 1165 : unsigned cnt = 0;
9239 1165 : if (cancellable)
9240 : {
9241 14 : tree field = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
9242 : ptr_type_node);
9243 14 : tree ifield = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
9244 : integer_type_node);
9245 14 : *last = field;
9246 14 : DECL_CHAIN (field) = ifield;
9247 14 : last = &DECL_CHAIN (ifield);
9248 14 : DECL_CONTEXT (field) = record_type;
9249 14 : if (TYPE_ALIGN (record_type) < DECL_ALIGN (field))
9250 0 : SET_TYPE_ALIGN (record_type, DECL_ALIGN (field));
9251 14 : DECL_CONTEXT (ifield) = record_type;
9252 14 : if (TYPE_ALIGN (record_type) < DECL_ALIGN (ifield))
9253 0 : SET_TYPE_ALIGN (record_type, DECL_ALIGN (ifield));
9254 : }
9255 3495 : for (int pass = 0; pass < 2; pass++)
9256 : {
9257 2330 : tree decl, type, next;
9258 2330 : for (tree c = clauses;
9259 3976 : omp_task_reduction_iterate (pass, code, ccode,
9260 1646 : &c, &decl, &type, &next); c = next)
9261 : {
9262 1646 : ++cnt;
9263 1646 : tree new_type = type;
9264 1646 : if (ctx->outer)
9265 1165 : new_type = remap_type (type, &ctx->outer->cb);
9266 1646 : tree field
9267 1646 : = build_decl (OMP_CLAUSE_LOCATION (c), FIELD_DECL,
9268 1646 : DECL_P (decl) ? DECL_NAME (decl) : NULL_TREE,
9269 : new_type);
9270 1646 : if (DECL_P (decl) && type == TREE_TYPE (decl))
9271 : {
9272 1123 : SET_DECL_ALIGN (field, DECL_ALIGN (decl));
9273 1123 : DECL_USER_ALIGN (field) = DECL_USER_ALIGN (decl);
9274 1123 : TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (decl);
9275 : }
9276 : else
9277 523 : SET_DECL_ALIGN (field, TYPE_ALIGN (type));
9278 1646 : DECL_CONTEXT (field) = record_type;
9279 1646 : if (TYPE_ALIGN (record_type) < DECL_ALIGN (field))
9280 1187 : SET_TYPE_ALIGN (record_type, DECL_ALIGN (field));
9281 1646 : *last = field;
9282 1646 : last = &DECL_CHAIN (field);
9283 1646 : tree bfield
9284 1646 : = build_decl (OMP_CLAUSE_LOCATION (c), FIELD_DECL, NULL_TREE,
9285 : boolean_type_node);
9286 1646 : DECL_CONTEXT (bfield) = record_type;
9287 1646 : if (TYPE_ALIGN (record_type) < DECL_ALIGN (bfield))
9288 0 : SET_TYPE_ALIGN (record_type, DECL_ALIGN (bfield));
9289 1646 : *last = bfield;
9290 1646 : last = &DECL_CHAIN (bfield);
9291 : }
9292 : }
9293 1165 : *last = NULL_TREE;
9294 1165 : layout_type (record_type);
9295 :
9296 : /* Build up an array which registers with the runtime all the reductions
9297 : and deregisters them at the end. Format documented in libgomp/task.c. */
9298 1165 : tree atype = build_array_type_nelts (pointer_sized_int_node, 7 + cnt * 3);
9299 1165 : tree avar = create_tmp_var_raw (atype);
9300 1165 : gimple_add_tmp_var (avar);
9301 1165 : TREE_ADDRESSABLE (avar) = 1;
9302 1165 : tree r = build4 (ARRAY_REF, pointer_sized_int_node, avar, size_zero_node,
9303 : NULL_TREE, NULL_TREE);
9304 1165 : tree t = build_int_cst (pointer_sized_int_node, cnt);
9305 1165 : gimple_seq_add_stmt (start, gimple_build_assign (r, t));
9306 1165 : gimple_seq seq = NULL;
9307 1165 : tree sz = fold_convert (pointer_sized_int_node,
9308 : TYPE_SIZE_UNIT (record_type));
9309 1165 : int cachesz = 64;
9310 1165 : sz = fold_build2 (PLUS_EXPR, pointer_sized_int_node, sz,
9311 : build_int_cst (pointer_sized_int_node, cachesz - 1));
9312 1165 : sz = fold_build2 (BIT_AND_EXPR, pointer_sized_int_node, sz,
9313 : build_int_cst (pointer_sized_int_node, ~(cachesz - 1)));
9314 1165 : ctx->task_reductions.create (1 + cnt);
9315 1165 : ctx->task_reduction_map = new hash_map<tree, unsigned>;
9316 2330 : ctx->task_reductions.quick_push (TREE_CODE (sz) == INTEGER_CST
9317 1205 : ? sz : NULL_TREE);
9318 1165 : sz = force_gimple_operand (sz, &seq, true, NULL_TREE);
9319 1165 : gimple_seq_add_seq (start, seq);
9320 1165 : r = build4 (ARRAY_REF, pointer_sized_int_node, avar, size_one_node,
9321 : NULL_TREE, NULL_TREE);
9322 1165 : gimple_seq_add_stmt (start, gimple_build_assign (r, sz));
9323 1165 : r = build4 (ARRAY_REF, pointer_sized_int_node, avar, size_int (2),
9324 : NULL_TREE, NULL_TREE);
9325 1165 : t = build_int_cst (pointer_sized_int_node,
9326 1165 : MAX (TYPE_ALIGN_UNIT (record_type), (unsigned) cachesz));
9327 1165 : gimple_seq_add_stmt (start, gimple_build_assign (r, t));
9328 1165 : r = build4 (ARRAY_REF, pointer_sized_int_node, avar, size_int (3),
9329 : NULL_TREE, NULL_TREE);
9330 1165 : t = build_int_cst (pointer_sized_int_node, -1);
9331 1165 : gimple_seq_add_stmt (start, gimple_build_assign (r, t));
9332 1165 : r = build4 (ARRAY_REF, pointer_sized_int_node, avar, size_int (4),
9333 : NULL_TREE, NULL_TREE);
9334 1165 : t = build_int_cst (pointer_sized_int_node, 0);
9335 1165 : gimple_seq_add_stmt (start, gimple_build_assign (r, t));
9336 :
9337 : /* In end, build a loop that iterates from 0 to < omp_get_num_threads ()
9338 : and for each task reduction checks a bool right after the private variable
9339 : within that thread's chunk; if the bool is clear, it hasn't been
9340 : initialized and thus isn't going to be reduced nor destructed, otherwise
9341 : reduce and destruct it. */
9342 1165 : tree idx = create_tmp_var (size_type_node);
9343 1165 : gimple_seq_add_stmt (end, gimple_build_assign (idx, size_zero_node));
9344 1165 : tree num_thr_sz = create_tmp_var (size_type_node);
9345 1165 : tree lab1 = create_artificial_label (UNKNOWN_LOCATION);
9346 1165 : tree lab2 = create_artificial_label (UNKNOWN_LOCATION);
9347 1165 : tree lab3 = NULL_TREE, lab7 = NULL_TREE;
9348 1165 : gimple *g;
9349 1165 : if (code == OMP_FOR || code == OMP_SECTIONS || code == OMP_SCOPE)
9350 : {
9351 : /* For worksharing constructs or scope, only perform it in the master
9352 : thread, with the exception of cancelled implicit barriers - then only
9353 : handle the current thread. */
9354 281 : tree lab4 = create_artificial_label (UNKNOWN_LOCATION);
9355 281 : t = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9356 281 : tree thr_num = create_tmp_var (integer_type_node);
9357 281 : g = gimple_build_call (t, 0);
9358 281 : gimple_call_set_lhs (g, thr_num);
9359 281 : gimple_seq_add_stmt (end, g);
9360 281 : if (cancellable)
9361 : {
9362 14 : tree c;
9363 14 : tree lab5 = create_artificial_label (UNKNOWN_LOCATION);
9364 14 : tree lab6 = create_artificial_label (UNKNOWN_LOCATION);
9365 14 : lab3 = create_artificial_label (UNKNOWN_LOCATION);
9366 14 : if (code == OMP_FOR)
9367 4 : c = gimple_omp_for_clauses (ctx->stmt);
9368 10 : else if (code == OMP_SECTIONS)
9369 0 : c = gimple_omp_sections_clauses (ctx->stmt);
9370 : else /* if (code == OMP_SCOPE) */
9371 10 : c = gimple_omp_scope_clauses (ctx->stmt);
9372 14 : c = OMP_CLAUSE_DECL (omp_find_clause (c, OMP_CLAUSE__REDUCTEMP_));
9373 14 : cancellable = c;
9374 14 : g = gimple_build_cond (NE_EXPR, c, build_zero_cst (TREE_TYPE (c)),
9375 : lab5, lab6);
9376 14 : gimple_seq_add_stmt (end, g);
9377 14 : gimple_seq_add_stmt (end, gimple_build_label (lab5));
9378 14 : g = gimple_build_assign (idx, NOP_EXPR, thr_num);
9379 14 : gimple_seq_add_stmt (end, g);
9380 14 : g = gimple_build_assign (num_thr_sz, PLUS_EXPR, idx,
9381 14 : build_one_cst (TREE_TYPE (idx)));
9382 14 : gimple_seq_add_stmt (end, g);
9383 14 : gimple_seq_add_stmt (end, gimple_build_goto (lab3));
9384 14 : gimple_seq_add_stmt (end, gimple_build_label (lab6));
9385 : }
9386 281 : g = gimple_build_cond (NE_EXPR, thr_num, integer_zero_node, lab2, lab4);
9387 281 : gimple_seq_add_stmt (end, g);
9388 281 : gimple_seq_add_stmt (end, gimple_build_label (lab4));
9389 : }
9390 1165 : if (code != OMP_PARALLEL)
9391 : {
9392 1105 : t = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9393 1105 : tree num_thr = create_tmp_var (integer_type_node);
9394 1105 : g = gimple_build_call (t, 0);
9395 1105 : gimple_call_set_lhs (g, num_thr);
9396 1105 : gimple_seq_add_stmt (end, g);
9397 1105 : g = gimple_build_assign (num_thr_sz, NOP_EXPR, num_thr);
9398 1105 : gimple_seq_add_stmt (end, g);
9399 1105 : if (cancellable)
9400 14 : gimple_seq_add_stmt (end, gimple_build_label (lab3));
9401 : }
9402 : else
9403 : {
9404 60 : tree c = omp_find_clause (gimple_omp_parallel_clauses (ctx->stmt),
9405 : OMP_CLAUSE__REDUCTEMP_);
9406 60 : t = fold_convert (pointer_sized_int_node, OMP_CLAUSE_DECL (c));
9407 60 : t = fold_convert (size_type_node, t);
9408 60 : gimplify_assign (num_thr_sz, t, end);
9409 : }
9410 1165 : t = build4 (ARRAY_REF, pointer_sized_int_node, avar, size_int (2),
9411 : NULL_TREE, NULL_TREE);
9412 1165 : tree data = create_tmp_var (pointer_sized_int_node);
9413 1165 : gimple_seq_add_stmt (end, gimple_build_assign (data, t));
9414 1165 : if (code == OMP_TASKLOOP)
9415 : {
9416 497 : lab7 = create_artificial_label (UNKNOWN_LOCATION);
9417 497 : g = gimple_build_cond (NE_EXPR, data,
9418 : build_zero_cst (pointer_sized_int_node),
9419 : lab1, lab7);
9420 497 : gimple_seq_add_stmt (end, g);
9421 : }
9422 1165 : gimple_seq_add_stmt (end, gimple_build_label (lab1));
9423 1165 : tree ptr;
9424 1165 : if (TREE_CODE (TYPE_SIZE_UNIT (record_type)) == INTEGER_CST)
9425 1125 : ptr = create_tmp_var (build_pointer_type (record_type));
9426 : else
9427 40 : ptr = create_tmp_var (ptr_type_node);
9428 1165 : gimple_seq_add_stmt (end, gimple_build_assign (ptr, NOP_EXPR, data));
9429 :
9430 1165 : tree field = TYPE_FIELDS (record_type);
9431 1165 : cnt = 0;
9432 1165 : if (cancellable)
9433 14 : field = DECL_CHAIN (DECL_CHAIN (field));
9434 3495 : for (int pass = 0; pass < 2; pass++)
9435 : {
9436 2330 : tree decl, type, next;
9437 2330 : for (tree c = clauses;
9438 3976 : omp_task_reduction_iterate (pass, code, ccode,
9439 1646 : &c, &decl, &type, &next); c = next)
9440 : {
9441 1646 : tree var = decl, ref;
9442 1646 : if (TREE_CODE (decl) == MEM_REF)
9443 : {
9444 485 : var = TREE_OPERAND (var, 0);
9445 485 : if (TREE_CODE (var) == POINTER_PLUS_EXPR)
9446 108 : var = TREE_OPERAND (var, 0);
9447 485 : tree v = var;
9448 485 : if (TREE_CODE (var) == ADDR_EXPR)
9449 310 : var = TREE_OPERAND (var, 0);
9450 175 : else if (INDIRECT_REF_P (var))
9451 4 : var = TREE_OPERAND (var, 0);
9452 485 : tree orig_var = var;
9453 485 : if (is_variable_sized (var))
9454 : {
9455 31 : gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
9456 31 : var = DECL_VALUE_EXPR (var);
9457 31 : gcc_assert (INDIRECT_REF_P (var));
9458 31 : var = TREE_OPERAND (var, 0);
9459 31 : gcc_assert (DECL_P (var));
9460 : }
9461 485 : t = ref = maybe_lookup_decl_in_outer_ctx (var, ctx);
9462 485 : if (orig_var != var)
9463 31 : gcc_assert (TREE_CODE (v) == ADDR_EXPR);
9464 454 : else if (TREE_CODE (v) == ADDR_EXPR)
9465 279 : t = build_fold_addr_expr (t);
9466 175 : else if (INDIRECT_REF_P (v))
9467 4 : t = build_fold_indirect_ref (t);
9468 485 : if (TREE_CODE (TREE_OPERAND (decl, 0)) == POINTER_PLUS_EXPR)
9469 : {
9470 108 : tree b = TREE_OPERAND (TREE_OPERAND (decl, 0), 1);
9471 108 : b = maybe_lookup_decl_in_outer_ctx (b, ctx);
9472 108 : t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t, b);
9473 : }
9474 485 : if (!integer_zerop (TREE_OPERAND (decl, 1)))
9475 219 : t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t,
9476 : fold_convert (size_type_node,
9477 : TREE_OPERAND (decl, 1)));
9478 : }
9479 : else
9480 : {
9481 1161 : t = ref = maybe_lookup_decl_in_outer_ctx (var, ctx);
9482 1161 : if (!omp_privatize_by_reference (decl))
9483 1123 : t = build_fold_addr_expr (t);
9484 : }
9485 1646 : t = fold_convert (pointer_sized_int_node, t);
9486 1646 : seq = NULL;
9487 1646 : t = force_gimple_operand (t, &seq, true, NULL_TREE);
9488 1646 : gimple_seq_add_seq (start, seq);
9489 1646 : r = build4 (ARRAY_REF, pointer_sized_int_node, avar,
9490 1646 : size_int (7 + cnt * 3), NULL_TREE, NULL_TREE);
9491 1646 : gimple_seq_add_stmt (start, gimple_build_assign (r, t));
9492 1646 : t = unshare_expr (byte_position (field));
9493 1646 : t = fold_convert (pointer_sized_int_node, t);
9494 1646 : ctx->task_reduction_map->put (c, cnt);
9495 3292 : ctx->task_reductions.quick_push (TREE_CODE (t) == INTEGER_CST
9496 2018 : ? t : NULL_TREE);
9497 1646 : seq = NULL;
9498 1646 : t = force_gimple_operand (t, &seq, true, NULL_TREE);
9499 1646 : gimple_seq_add_seq (start, seq);
9500 1646 : r = build4 (ARRAY_REF, pointer_sized_int_node, avar,
9501 1646 : size_int (7 + cnt * 3 + 1), NULL_TREE, NULL_TREE);
9502 1646 : gimple_seq_add_stmt (start, gimple_build_assign (r, t));
9503 :
9504 1646 : tree bfield = DECL_CHAIN (field);
9505 1646 : tree cond;
9506 1646 : if (code == OMP_PARALLEL
9507 1646 : || code == OMP_FOR
9508 : || code == OMP_SECTIONS
9509 : || code == OMP_SCOPE)
9510 : /* In parallel, worksharing or scope all threads unconditionally
9511 : initialize all their task reduction private variables. */
9512 548 : cond = boolean_true_node;
9513 1098 : else if (TREE_TYPE (ptr) == ptr_type_node)
9514 : {
9515 261 : cond = build2 (POINTER_PLUS_EXPR, ptr_type_node, ptr,
9516 : unshare_expr (byte_position (bfield)));
9517 261 : seq = NULL;
9518 261 : cond = force_gimple_operand (cond, &seq, true, NULL_TREE);
9519 261 : gimple_seq_add_seq (end, seq);
9520 261 : tree pbool = build_pointer_type (TREE_TYPE (bfield));
9521 261 : cond = build2 (MEM_REF, TREE_TYPE (bfield), cond,
9522 : build_int_cst (pbool, 0));
9523 : }
9524 : else
9525 837 : cond = build3 (COMPONENT_REF, TREE_TYPE (bfield),
9526 : build_simple_mem_ref (ptr), bfield, NULL_TREE);
9527 1646 : tree lab3 = create_artificial_label (UNKNOWN_LOCATION);
9528 1646 : tree lab4 = create_artificial_label (UNKNOWN_LOCATION);
9529 1646 : tree condv = create_tmp_var (boolean_type_node);
9530 1646 : gimple_seq_add_stmt (end, gimple_build_assign (condv, cond));
9531 1646 : g = gimple_build_cond (NE_EXPR, condv, boolean_false_node,
9532 : lab3, lab4);
9533 1646 : gimple_seq_add_stmt (end, g);
9534 1646 : gimple_seq_add_stmt (end, gimple_build_label (lab3));
9535 1646 : if (cancellable && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) == NULL_TREE)
9536 : {
9537 : /* If this reduction doesn't need destruction and parallel
9538 : has been cancelled, there is nothing to do for this
9539 : reduction, so jump around the merge operation. */
9540 18 : tree lab5 = create_artificial_label (UNKNOWN_LOCATION);
9541 18 : g = gimple_build_cond (NE_EXPR, cancellable,
9542 18 : build_zero_cst (TREE_TYPE (cancellable)),
9543 : lab4, lab5);
9544 18 : gimple_seq_add_stmt (end, g);
9545 18 : gimple_seq_add_stmt (end, gimple_build_label (lab5));
9546 : }
9547 :
9548 1646 : tree new_var;
9549 1646 : if (TREE_TYPE (ptr) == ptr_type_node)
9550 : {
9551 428 : new_var = build2 (POINTER_PLUS_EXPR, ptr_type_node, ptr,
9552 : unshare_expr (byte_position (field)));
9553 428 : seq = NULL;
9554 428 : new_var = force_gimple_operand (new_var, &seq, true, NULL_TREE);
9555 428 : gimple_seq_add_seq (end, seq);
9556 428 : tree pbool = build_pointer_type (TREE_TYPE (field));
9557 428 : new_var = build2 (MEM_REF, TREE_TYPE (field), new_var,
9558 : build_int_cst (pbool, 0));
9559 : }
9560 : else
9561 1218 : new_var = build3 (COMPONENT_REF, TREE_TYPE (field),
9562 : build_simple_mem_ref (ptr), field, NULL_TREE);
9563 :
9564 1646 : enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
9565 1646 : if (TREE_CODE (decl) != MEM_REF
9566 1646 : && omp_privatize_by_reference (decl))
9567 38 : ref = build_simple_mem_ref (ref);
9568 : /* reduction(-:var) sums up the partial results, so it acts
9569 : identically to reduction(+:var). */
9570 1646 : if (rcode == MINUS_EXPR)
9571 0 : rcode = PLUS_EXPR;
9572 1646 : if (TREE_CODE (decl) == MEM_REF)
9573 : {
9574 485 : tree type = TREE_TYPE (new_var);
9575 485 : tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
9576 485 : tree i = create_tmp_var (TREE_TYPE (v));
9577 485 : tree ptype = build_pointer_type (TREE_TYPE (type));
9578 485 : if (DECL_P (v))
9579 : {
9580 142 : v = maybe_lookup_decl_in_outer_ctx (v, ctx);
9581 142 : tree vv = create_tmp_var (TREE_TYPE (v));
9582 142 : gimplify_assign (vv, v, start);
9583 142 : v = vv;
9584 : }
9585 485 : ref = build4 (ARRAY_REF, pointer_sized_int_node, avar,
9586 485 : size_int (7 + cnt * 3), NULL_TREE, NULL_TREE);
9587 485 : new_var = build_fold_addr_expr (new_var);
9588 485 : new_var = fold_convert (ptype, new_var);
9589 485 : ref = fold_convert (ptype, ref);
9590 485 : tree m = create_tmp_var (ptype);
9591 485 : gimplify_assign (m, new_var, end);
9592 485 : new_var = m;
9593 485 : m = create_tmp_var (ptype);
9594 485 : gimplify_assign (m, ref, end);
9595 485 : ref = m;
9596 485 : gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), end);
9597 485 : tree body = create_artificial_label (UNKNOWN_LOCATION);
9598 485 : tree endl = create_artificial_label (UNKNOWN_LOCATION);
9599 485 : gimple_seq_add_stmt (end, gimple_build_label (body));
9600 485 : tree priv = build_simple_mem_ref (new_var);
9601 485 : tree out = build_simple_mem_ref (ref);
9602 485 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
9603 : {
9604 161 : tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
9605 161 : tree decl_placeholder
9606 161 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
9607 161 : tree lab6 = NULL_TREE;
9608 161 : if (cancellable)
9609 : {
9610 : /* If this reduction needs destruction and parallel
9611 : has been cancelled, jump around the merge operation
9612 : to the destruction. */
9613 4 : tree lab5 = create_artificial_label (UNKNOWN_LOCATION);
9614 4 : lab6 = create_artificial_label (UNKNOWN_LOCATION);
9615 4 : tree zero = build_zero_cst (TREE_TYPE (cancellable));
9616 4 : g = gimple_build_cond (NE_EXPR, cancellable, zero,
9617 : lab6, lab5);
9618 4 : gimple_seq_add_stmt (end, g);
9619 4 : gimple_seq_add_stmt (end, gimple_build_label (lab5));
9620 : }
9621 161 : SET_DECL_VALUE_EXPR (placeholder, out);
9622 161 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
9623 161 : SET_DECL_VALUE_EXPR (decl_placeholder, priv);
9624 161 : DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
9625 161 : lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
9626 322 : gimple_seq_add_seq (end,
9627 161 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
9628 161 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
9629 161 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
9630 : {
9631 56 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
9632 56 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
9633 : }
9634 161 : if (cancellable)
9635 4 : gimple_seq_add_stmt (end, gimple_build_label (lab6));
9636 161 : tree x = lang_hooks.decls.omp_clause_dtor (c, priv);
9637 161 : if (x)
9638 : {
9639 137 : gimple_seq tseq = NULL;
9640 137 : gimplify_stmt (&x, &tseq);
9641 137 : gimple_seq_add_seq (end, tseq);
9642 : }
9643 : }
9644 : else
9645 : {
9646 324 : tree x = build2 (rcode, TREE_TYPE (out), out, priv);
9647 324 : out = unshare_expr (out);
9648 324 : gimplify_assign (out, x, end);
9649 : }
9650 485 : gimple *g
9651 485 : = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
9652 485 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
9653 485 : gimple_seq_add_stmt (end, g);
9654 485 : g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
9655 485 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
9656 485 : gimple_seq_add_stmt (end, g);
9657 485 : g = gimple_build_assign (i, PLUS_EXPR, i,
9658 485 : build_int_cst (TREE_TYPE (i), 1));
9659 485 : gimple_seq_add_stmt (end, g);
9660 485 : g = gimple_build_cond (LE_EXPR, i, v, body, endl);
9661 485 : gimple_seq_add_stmt (end, g);
9662 485 : gimple_seq_add_stmt (end, gimple_build_label (endl));
9663 : }
9664 1161 : else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
9665 : {
9666 127 : tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
9667 127 : tree oldv = NULL_TREE;
9668 127 : tree lab6 = NULL_TREE;
9669 127 : if (cancellable)
9670 : {
9671 : /* If this reduction needs destruction and parallel
9672 : has been cancelled, jump around the merge operation
9673 : to the destruction. */
9674 4 : tree lab5 = create_artificial_label (UNKNOWN_LOCATION);
9675 4 : lab6 = create_artificial_label (UNKNOWN_LOCATION);
9676 4 : tree zero = build_zero_cst (TREE_TYPE (cancellable));
9677 4 : g = gimple_build_cond (NE_EXPR, cancellable, zero,
9678 : lab6, lab5);
9679 4 : gimple_seq_add_stmt (end, g);
9680 4 : gimple_seq_add_stmt (end, gimple_build_label (lab5));
9681 : }
9682 127 : if (omp_privatize_by_reference (decl)
9683 137 : && !useless_type_conversion_p (TREE_TYPE (placeholder),
9684 10 : TREE_TYPE (ref)))
9685 0 : ref = build_fold_addr_expr_loc (OMP_CLAUSE_LOCATION (c), ref);
9686 127 : ref = build_fold_addr_expr_loc (OMP_CLAUSE_LOCATION (c), ref);
9687 127 : tree refv = create_tmp_var (TREE_TYPE (ref));
9688 127 : gimplify_assign (refv, ref, end);
9689 127 : ref = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), refv);
9690 127 : SET_DECL_VALUE_EXPR (placeholder, ref);
9691 127 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
9692 127 : tree d = maybe_lookup_decl (decl, ctx);
9693 127 : gcc_assert (d);
9694 127 : if (DECL_HAS_VALUE_EXPR_P (d))
9695 7 : oldv = DECL_VALUE_EXPR (d);
9696 127 : if (omp_privatize_by_reference (var))
9697 : {
9698 10 : tree v = fold_convert (TREE_TYPE (d),
9699 : build_fold_addr_expr (new_var));
9700 10 : SET_DECL_VALUE_EXPR (d, v);
9701 : }
9702 : else
9703 117 : SET_DECL_VALUE_EXPR (d, new_var);
9704 127 : DECL_HAS_VALUE_EXPR_P (d) = 1;
9705 127 : lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
9706 127 : if (oldv)
9707 7 : SET_DECL_VALUE_EXPR (d, oldv);
9708 : else
9709 : {
9710 120 : SET_DECL_VALUE_EXPR (d, NULL_TREE);
9711 120 : DECL_HAS_VALUE_EXPR_P (d) = 0;
9712 : }
9713 127 : gimple_seq_add_seq (end, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
9714 127 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
9715 127 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
9716 24 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
9717 127 : if (cancellable)
9718 4 : gimple_seq_add_stmt (end, gimple_build_label (lab6));
9719 127 : tree x = lang_hooks.decls.omp_clause_dtor (c, new_var);
9720 127 : if (x)
9721 : {
9722 29 : gimple_seq tseq = NULL;
9723 29 : gimplify_stmt (&x, &tseq);
9724 29 : gimple_seq_add_seq (end, tseq);
9725 : }
9726 : }
9727 : else
9728 : {
9729 1034 : tree x = build2 (rcode, TREE_TYPE (ref), ref, new_var);
9730 1034 : ref = unshare_expr (ref);
9731 1034 : gimplify_assign (ref, x, end);
9732 : }
9733 1646 : gimple_seq_add_stmt (end, gimple_build_label (lab4));
9734 1646 : ++cnt;
9735 1646 : field = DECL_CHAIN (bfield);
9736 : }
9737 : }
9738 :
9739 1165 : if (code == OMP_TASKGROUP)
9740 : {
9741 327 : t = builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_REDUCTION_REGISTER);
9742 327 : g = gimple_build_call (t, 1, build_fold_addr_expr (avar));
9743 327 : gimple_seq_add_stmt (start, g);
9744 : }
9745 : else
9746 : {
9747 838 : tree c;
9748 838 : if (code == OMP_FOR)
9749 227 : c = gimple_omp_for_clauses (ctx->stmt);
9750 611 : else if (code == OMP_SECTIONS)
9751 8 : c = gimple_omp_sections_clauses (ctx->stmt);
9752 603 : else if (code == OMP_SCOPE)
9753 46 : c = gimple_omp_scope_clauses (ctx->stmt);
9754 : else
9755 557 : c = gimple_omp_taskreg_clauses (ctx->stmt);
9756 838 : c = omp_find_clause (c, OMP_CLAUSE__REDUCTEMP_);
9757 838 : t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (c)),
9758 : build_fold_addr_expr (avar));
9759 838 : gimplify_assign (OMP_CLAUSE_DECL (c), t, start);
9760 : }
9761 :
9762 1165 : gimple_seq_add_stmt (end, gimple_build_assign (data, PLUS_EXPR, data, sz));
9763 1165 : gimple_seq_add_stmt (end, gimple_build_assign (idx, PLUS_EXPR, idx,
9764 : size_one_node));
9765 1165 : g = gimple_build_cond (NE_EXPR, idx, num_thr_sz, lab1, lab2);
9766 1165 : gimple_seq_add_stmt (end, g);
9767 1165 : gimple_seq_add_stmt (end, gimple_build_label (lab2));
9768 1165 : if (code == OMP_FOR || code == OMP_SECTIONS || code == OMP_SCOPE)
9769 : {
9770 281 : enum built_in_function bfn
9771 : = BUILT_IN_GOMP_WORKSHARE_TASK_REDUCTION_UNREGISTER;
9772 281 : t = builtin_decl_explicit (bfn);
9773 281 : tree c_bool_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (t)));
9774 281 : tree arg;
9775 281 : if (cancellable)
9776 : {
9777 14 : arg = create_tmp_var (c_bool_type);
9778 14 : gimple_seq_add_stmt (end, gimple_build_assign (arg, NOP_EXPR,
9779 : cancellable));
9780 : }
9781 : else
9782 267 : arg = build_int_cst (c_bool_type, 0);
9783 281 : g = gimple_build_call (t, 1, arg);
9784 281 : }
9785 : else
9786 : {
9787 884 : t = builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_REDUCTION_UNREGISTER);
9788 884 : g = gimple_build_call (t, 1, build_fold_addr_expr (avar));
9789 : }
9790 1165 : gimple_seq_add_stmt (end, g);
9791 1165 : if (lab7)
9792 497 : gimple_seq_add_stmt (end, gimple_build_label (lab7));
9793 1165 : t = build_constructor (atype, NULL);
9794 1165 : TREE_THIS_VOLATILE (t) = 1;
9795 1165 : gimple_seq_add_stmt (end, gimple_build_assign (avar, t));
9796 : }
9797 :
9798 : /* Expand code for an OpenMP taskgroup directive. */
9799 :
9800 : static void
9801 536 : lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9802 : {
9803 536 : gimple *stmt = gsi_stmt (*gsi_p);
9804 536 : gcall *x;
9805 536 : gbind *bind;
9806 536 : gimple_seq dseq = NULL;
9807 536 : tree block = make_node (BLOCK);
9808 :
9809 536 : bind = gimple_build_bind (NULL, NULL, block);
9810 536 : gsi_replace (gsi_p, bind, true);
9811 536 : gimple_bind_add_stmt (bind, stmt);
9812 :
9813 536 : push_gimplify_context ();
9814 :
9815 536 : x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
9816 : 0);
9817 536 : gimple_bind_add_stmt (bind, x);
9818 :
9819 536 : lower_omp_task_reductions (ctx, OMP_TASKGROUP,
9820 : gimple_omp_taskgroup_clauses (stmt),
9821 : gimple_bind_body_ptr (bind), &dseq);
9822 :
9823 536 : lower_omp (gimple_omp_body_ptr (stmt), ctx);
9824 536 : gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9825 536 : gimple_omp_set_body (stmt, NULL);
9826 :
9827 536 : gimple_bind_add_seq (bind, dseq);
9828 :
9829 536 : pop_gimplify_context (bind);
9830 :
9831 536 : gimple_bind_append_vars (bind, ctx->block_vars);
9832 536 : BLOCK_VARS (block) = ctx->block_vars;
9833 536 : }
9834 :
9835 :
9836 : /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
9837 :
9838 : static void
9839 0 : lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
9840 : omp_context *ctx)
9841 : {
9842 0 : struct omp_for_data fd;
9843 0 : if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
9844 0 : return;
9845 :
9846 0 : unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
9847 0 : struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
9848 0 : omp_extract_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
9849 0 : if (!fd.ordered)
9850 : return;
9851 :
9852 0 : tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
9853 0 : tree c = gimple_omp_ordered_clauses (ord_stmt);
9854 0 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
9855 0 : && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
9856 : {
9857 : /* Merge depend clauses from multiple adjacent
9858 : #pragma omp ordered depend(sink:...) constructs
9859 : into one #pragma omp ordered depend(sink:...), so that
9860 : we can optimize them together. */
9861 0 : gimple_stmt_iterator gsi = *gsi_p;
9862 0 : gsi_next (&gsi);
9863 0 : while (!gsi_end_p (gsi))
9864 : {
9865 0 : gimple *stmt = gsi_stmt (gsi);
9866 0 : if (is_gimple_debug (stmt)
9867 0 : || gimple_code (stmt) == GIMPLE_NOP)
9868 : {
9869 0 : gsi_next (&gsi);
9870 0 : continue;
9871 : }
9872 0 : if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
9873 : break;
9874 0 : gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
9875 0 : c = gimple_omp_ordered_clauses (ord_stmt2);
9876 0 : if (c == NULL_TREE
9877 0 : || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DOACROSS
9878 0 : || OMP_CLAUSE_DOACROSS_KIND (c) != OMP_CLAUSE_DOACROSS_SINK)
9879 : break;
9880 0 : while (*list_p)
9881 0 : list_p = &OMP_CLAUSE_CHAIN (*list_p);
9882 0 : *list_p = c;
9883 0 : gsi_remove (&gsi, true);
9884 : }
9885 : }
9886 :
9887 : /* Canonicalize sink dependence clauses into one folded clause if
9888 : possible.
9889 :
9890 : The basic algorithm is to create a sink vector whose first
9891 : element is the GCD of all the first elements, and whose remaining
9892 : elements are the minimum of the subsequent columns.
9893 :
9894 : We ignore dependence vectors whose first element is zero because
9895 : such dependencies are known to be executed by the same thread.
9896 :
9897 : We take into account the direction of the loop, so a minimum
9898 : becomes a maximum if the loop is iterating forwards. We also
9899 : ignore sink clauses where the loop direction is unknown, or where
9900 : the offsets are clearly invalid because they are not a multiple
9901 : of the loop increment.
9902 :
9903 : For example:
9904 :
9905 : #pragma omp for ordered(2)
9906 : for (i=0; i < N; ++i)
9907 : for (j=0; j < M; ++j)
9908 : {
9909 : #pragma omp ordered \
9910 : depend(sink:i-8,j-2) \
9911 : depend(sink:i,j-1) \ // Completely ignored because i+0.
9912 : depend(sink:i-4,j-3) \
9913 : depend(sink:i-6,j-4)
9914 : #pragma omp ordered depend(source)
9915 : }
9916 :
9917 : Folded clause is:
9918 :
9919 : depend(sink:-gcd(8,4,6),-min(2,3,4))
9920 : -or-
9921 : depend(sink:-2,-2)
9922 : */
9923 :
9924 : /* FIXME: Computing GCD's where the first element is zero is
9925 : non-trivial in the presence of collapsed loops. Do this later. */
9926 0 : if (fd.collapse > 1)
9927 : return;
9928 :
9929 0 : wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
9930 :
9931 : /* wide_int is not a POD so it must be default-constructed. */
9932 0 : for (unsigned i = 0; i != 2 * len - 1; ++i)
9933 0 : new (static_cast<void*>(folded_deps + i)) wide_int ();
9934 :
9935 : tree folded_dep = NULL_TREE;
9936 : /* TRUE if the first dimension's offset is negative. */
9937 : bool neg_offset_p = false;
9938 :
9939 : list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
9940 : unsigned int i;
9941 0 : while ((c = *list_p) != NULL)
9942 : {
9943 0 : bool remove = false;
9944 :
9945 0 : gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS);
9946 0 : if (OMP_CLAUSE_DOACROSS_KIND (c) != OMP_CLAUSE_DOACROSS_SINK)
9947 0 : goto next_ordered_clause;
9948 :
9949 0 : tree vec;
9950 0 : for (vec = OMP_CLAUSE_DECL (c), i = 0;
9951 0 : vec && TREE_CODE (vec) == TREE_LIST;
9952 0 : vec = TREE_CHAIN (vec), ++i)
9953 : {
9954 0 : gcc_assert (i < len);
9955 :
9956 : /* omp_extract_for_data has canonicalized the condition. */
9957 0 : gcc_assert (fd.loops[i].cond_code == LT_EXPR
9958 : || fd.loops[i].cond_code == GT_EXPR);
9959 0 : bool forward = fd.loops[i].cond_code == LT_EXPR;
9960 0 : bool maybe_lexically_later = true;
9961 :
9962 : /* While the committee makes up its mind, bail if we have any
9963 : non-constant steps. */
9964 0 : if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
9965 0 : goto lower_omp_ordered_ret;
9966 :
9967 0 : tree itype = TREE_TYPE (TREE_VALUE (vec));
9968 0 : if (POINTER_TYPE_P (itype))
9969 0 : itype = sizetype;
9970 0 : wide_int offset = wide_int::from (wi::to_wide (TREE_PURPOSE (vec)),
9971 0 : TYPE_PRECISION (itype),
9972 0 : TYPE_SIGN (itype));
9973 :
9974 : /* Ignore invalid offsets that are not multiples of the step. */
9975 0 : if (!wi::multiple_of_p (wi::abs (offset),
9976 0 : wi::abs (wi::to_wide (fd.loops[i].step)),
9977 : UNSIGNED))
9978 : {
9979 0 : warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp,
9980 : "ignoring %<sink%> clause with offset that is not "
9981 : "a multiple of the loop step");
9982 0 : remove = true;
9983 0 : goto next_ordered_clause;
9984 : }
9985 :
9986 : /* Calculate the first dimension. The first dimension of
9987 : the folded dependency vector is the GCD of the first
9988 : elements, while ignoring any first elements whose offset
9989 : is 0. */
9990 0 : if (i == 0)
9991 : {
9992 : /* Ignore dependence vectors whose first dimension is 0. */
9993 0 : if (offset == 0)
9994 : {
9995 0 : remove = true;
9996 0 : goto next_ordered_clause;
9997 : }
9998 : else
9999 : {
10000 0 : if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
10001 : {
10002 0 : error_at (OMP_CLAUSE_LOCATION (c),
10003 : "first offset must be in opposite direction "
10004 : "of loop iterations");
10005 0 : goto lower_omp_ordered_ret;
10006 : }
10007 0 : if (forward)
10008 0 : offset = -offset;
10009 0 : neg_offset_p = forward;
10010 : /* Initialize the first time around. */
10011 0 : if (folded_dep == NULL_TREE)
10012 : {
10013 0 : folded_dep = c;
10014 0 : folded_deps[0] = offset;
10015 : }
10016 : else
10017 0 : folded_deps[0] = wi::gcd (folded_deps[0],
10018 0 : offset, UNSIGNED);
10019 : }
10020 : }
10021 : /* Calculate minimum for the remaining dimensions. */
10022 : else
10023 : {
10024 0 : folded_deps[len + i - 1] = offset;
10025 0 : if (folded_dep == c)
10026 0 : folded_deps[i] = offset;
10027 0 : else if (maybe_lexically_later
10028 0 : && !wi::eq_p (folded_deps[i], offset))
10029 : {
10030 0 : if (forward ^ wi::gts_p (folded_deps[i], offset))
10031 : {
10032 : unsigned int j;
10033 0 : folded_dep = c;
10034 0 : for (j = 1; j <= i; j++)
10035 0 : folded_deps[j] = folded_deps[len + j - 1];
10036 : }
10037 : else
10038 0 : maybe_lexically_later = false;
10039 : }
10040 : }
10041 0 : }
10042 0 : gcc_assert (i == len);
10043 :
10044 : remove = true;
10045 :
10046 0 : next_ordered_clause:
10047 0 : if (remove)
10048 0 : *list_p = OMP_CLAUSE_CHAIN (c);
10049 : else
10050 0 : list_p = &OMP_CLAUSE_CHAIN (c);
10051 : }
10052 :
10053 0 : if (folded_dep)
10054 : {
10055 0 : if (neg_offset_p)
10056 0 : folded_deps[0] = -folded_deps[0];
10057 :
10058 0 : tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
10059 0 : if (POINTER_TYPE_P (itype))
10060 0 : itype = sizetype;
10061 :
10062 0 : TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
10063 0 : = wide_int_to_tree (itype, folded_deps[0]);
10064 0 : OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
10065 0 : *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
10066 : }
10067 :
10068 0 : lower_omp_ordered_ret:
10069 :
10070 : /* Ordered without clauses is #pragma omp threads, while we want
10071 : a nop instead if we remove all clauses. */
10072 0 : if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
10073 0 : gsi_replace (gsi_p, gimple_build_nop (), true);
10074 : }
10075 :
10076 :
10077 : /* Expand code for an OpenMP ordered directive. */
10078 :
10079 : static void
10080 1124 : lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10081 : {
10082 1124 : tree block;
10083 1124 : gimple *stmt = gsi_stmt (*gsi_p), *g;
10084 1124 : gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
10085 1124 : gcall *x;
10086 1124 : gbind *bind;
10087 1124 : bool simd = omp_find_clause (gimple_omp_ordered_clauses (ord_stmt),
10088 1124 : OMP_CLAUSE_SIMD);
10089 : /* FIXME: this should check presence of OMP_CLAUSE__SIMT_ on the enclosing
10090 : loop. */
10091 1124 : bool maybe_simt
10092 1124 : = simd && omp_maybe_offloaded_ctx (ctx) && omp_max_simt_vf () > 1;
10093 1124 : bool threads = omp_find_clause (gimple_omp_ordered_clauses (ord_stmt),
10094 1124 : OMP_CLAUSE_THREADS);
10095 :
10096 1124 : if (gimple_omp_ordered_standalone_p (ord_stmt))
10097 : {
10098 : /* FIXME: This is needs to be moved to the expansion to verify various
10099 : conditions only testable on cfg with dominators computed, and also
10100 : all the depend clauses to be merged still might need to be available
10101 : for the runtime checks. */
10102 : if (0)
10103 : lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
10104 1124 : return;
10105 : }
10106 :
10107 411 : push_gimplify_context ();
10108 :
10109 411 : block = make_node (BLOCK);
10110 411 : bind = gimple_build_bind (NULL, NULL, block);
10111 411 : gsi_replace (gsi_p, bind, true);
10112 411 : gimple_bind_add_stmt (bind, stmt);
10113 :
10114 411 : if (simd)
10115 : {
10116 79 : x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 1,
10117 79 : build_int_cst (NULL_TREE, threads));
10118 79 : cfun->has_simduid_loops = true;
10119 : }
10120 : else
10121 332 : x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10122 : 0);
10123 411 : gimple_bind_add_stmt (bind, x);
10124 :
10125 411 : tree counter = NULL_TREE, test = NULL_TREE, body = NULL_TREE;
10126 411 : if (maybe_simt)
10127 : {
10128 0 : counter = create_tmp_var (integer_type_node);
10129 0 : g = gimple_build_call_internal (IFN_GOMP_SIMT_LANE, 0);
10130 0 : gimple_call_set_lhs (g, counter);
10131 0 : gimple_bind_add_stmt (bind, g);
10132 :
10133 0 : body = create_artificial_label (UNKNOWN_LOCATION);
10134 0 : test = create_artificial_label (UNKNOWN_LOCATION);
10135 0 : gimple_bind_add_stmt (bind, gimple_build_label (body));
10136 :
10137 0 : tree simt_pred = create_tmp_var (integer_type_node);
10138 0 : g = gimple_build_call_internal (IFN_GOMP_SIMT_ORDERED_PRED, 1, counter);
10139 0 : gimple_call_set_lhs (g, simt_pred);
10140 0 : gimple_bind_add_stmt (bind, g);
10141 :
10142 0 : tree t = create_artificial_label (UNKNOWN_LOCATION);
10143 0 : g = gimple_build_cond (EQ_EXPR, simt_pred, integer_zero_node, t, test);
10144 0 : gimple_bind_add_stmt (bind, g);
10145 :
10146 0 : gimple_bind_add_stmt (bind, gimple_build_label (t));
10147 : }
10148 411 : lower_omp (gimple_omp_body_ptr (stmt), ctx);
10149 411 : gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10150 411 : gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10151 411 : gimple_omp_set_body (stmt, NULL);
10152 :
10153 411 : if (maybe_simt)
10154 : {
10155 0 : gimple_bind_add_stmt (bind, gimple_build_label (test));
10156 0 : g = gimple_build_assign (counter, MINUS_EXPR, counter, integer_one_node);
10157 0 : gimple_bind_add_stmt (bind, g);
10158 :
10159 0 : tree c = build2 (GE_EXPR, boolean_type_node, counter, integer_zero_node);
10160 0 : tree nonneg = create_tmp_var (integer_type_node);
10161 0 : gimple_seq tseq = NULL;
10162 0 : gimplify_assign (nonneg, fold_convert (integer_type_node, c), &tseq);
10163 0 : gimple_bind_add_seq (bind, tseq);
10164 :
10165 0 : g = gimple_build_call_internal (IFN_GOMP_SIMT_VOTE_ANY, 1, nonneg);
10166 0 : gimple_call_set_lhs (g, nonneg);
10167 0 : gimple_bind_add_stmt (bind, g);
10168 :
10169 0 : tree end = create_artificial_label (UNKNOWN_LOCATION);
10170 0 : g = gimple_build_cond (NE_EXPR, nonneg, integer_zero_node, body, end);
10171 0 : gimple_bind_add_stmt (bind, g);
10172 :
10173 0 : gimple_bind_add_stmt (bind, gimple_build_label (end));
10174 : }
10175 411 : if (simd)
10176 79 : x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 1,
10177 79 : build_int_cst (NULL_TREE, threads));
10178 : else
10179 332 : x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
10180 : 0);
10181 411 : gimple_bind_add_stmt (bind, x);
10182 :
10183 411 : gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10184 :
10185 411 : pop_gimplify_context (bind);
10186 :
10187 411 : gimple_bind_append_vars (bind, ctx->block_vars);
10188 411 : BLOCK_VARS (block) = gimple_bind_vars (bind);
10189 : }
10190 :
10191 :
10192 : /* Expand code for an OpenMP scan directive and the structured block
10193 : before the scan directive. */
10194 :
10195 : static void
10196 1544 : lower_omp_scan (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10197 : {
10198 1544 : gimple *stmt = gsi_stmt (*gsi_p);
10199 1544 : bool has_clauses
10200 1544 : = gimple_omp_scan_clauses (as_a <gomp_scan *> (stmt)) != NULL;
10201 1544 : tree lane = NULL_TREE;
10202 1544 : gimple_seq before = NULL;
10203 1544 : omp_context *octx = ctx->outer;
10204 1544 : gcc_assert (octx);
10205 1544 : if (octx->scan_exclusive && !has_clauses)
10206 : {
10207 536 : gimple_stmt_iterator gsi2 = *gsi_p;
10208 536 : gsi_next (&gsi2);
10209 536 : gimple *stmt2 = gsi_stmt (gsi2);
10210 : /* For exclusive scan, swap GIMPLE_OMP_SCAN without clauses
10211 : with following GIMPLE_OMP_SCAN with clauses, so that input_phase,
10212 : the one with exclusive clause(s), comes first. */
10213 536 : if (stmt2
10214 274 : && gimple_code (stmt2) == GIMPLE_OMP_SCAN
10215 804 : && gimple_omp_scan_clauses (as_a <gomp_scan *> (stmt2)) != NULL)
10216 : {
10217 268 : gsi_remove (gsi_p, false);
10218 268 : gsi_insert_after (gsi_p, stmt, GSI_SAME_STMT);
10219 268 : ctx = maybe_lookup_ctx (stmt2);
10220 268 : gcc_assert (ctx);
10221 268 : lower_omp_scan (gsi_p, ctx);
10222 268 : return;
10223 : }
10224 : }
10225 :
10226 1276 : bool input_phase = has_clauses ^ octx->scan_inclusive;
10227 1276 : bool is_simd = (gimple_code (octx->stmt) == GIMPLE_OMP_FOR
10228 1276 : && gimple_omp_for_kind (octx->stmt) == GF_OMP_FOR_KIND_SIMD);
10229 1276 : bool is_for = (gimple_code (octx->stmt) == GIMPLE_OMP_FOR
10230 1276 : && gimple_omp_for_kind (octx->stmt) == GF_OMP_FOR_KIND_FOR
10231 1630 : && !gimple_omp_for_combined_p (octx->stmt));
10232 1276 : bool is_for_simd = is_simd && gimple_omp_for_combined_into_p (octx->stmt);
10233 332 : if (is_for_simd && octx->for_simd_scan_phase)
10234 : is_simd = false;
10235 1110 : if (is_simd)
10236 756 : if (tree c = omp_find_clause (gimple_omp_for_clauses (octx->stmt),
10237 : OMP_CLAUSE__SIMDUID_))
10238 : {
10239 368 : tree uid = OMP_CLAUSE__SIMDUID__DECL (c);
10240 368 : lane = create_tmp_var (unsigned_type_node);
10241 368 : tree t = build_int_cst (integer_type_node,
10242 552 : input_phase ? 1
10243 184 : : octx->scan_inclusive ? 2 : 3);
10244 368 : gimple *g
10245 368 : = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 2, uid, t);
10246 368 : gimple_call_set_lhs (g, lane);
10247 368 : gimple_seq_add_stmt (&before, g);
10248 : }
10249 :
10250 1276 : if (is_simd || is_for)
10251 : {
10252 5004 : for (tree c = gimple_omp_for_clauses (octx->stmt);
10253 5004 : c; c = OMP_CLAUSE_CHAIN (c))
10254 4060 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
10255 4060 : && OMP_CLAUSE_REDUCTION_INSCAN (c))
10256 : {
10257 1168 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
10258 1168 : tree var = OMP_CLAUSE_DECL (c);
10259 1168 : tree new_var = lookup_decl (var, octx);
10260 1168 : tree val = new_var;
10261 1168 : tree var2 = NULL_TREE;
10262 1168 : tree var3 = NULL_TREE;
10263 1168 : tree var4 = NULL_TREE;
10264 1168 : tree lane0 = NULL_TREE;
10265 1168 : tree new_vard = new_var;
10266 1168 : if (omp_privatize_by_reference (var))
10267 : {
10268 184 : new_var = build_simple_mem_ref_loc (clause_loc, new_var);
10269 184 : val = new_var;
10270 : }
10271 1168 : if (DECL_HAS_VALUE_EXPR_P (new_vard))
10272 : {
10273 464 : val = DECL_VALUE_EXPR (new_vard);
10274 464 : if (new_vard != new_var)
10275 : {
10276 76 : gcc_assert (TREE_CODE (val) == ADDR_EXPR);
10277 76 : val = TREE_OPERAND (val, 0);
10278 : }
10279 464 : if (TREE_CODE (val) == ARRAY_REF
10280 464 : && VAR_P (TREE_OPERAND (val, 0)))
10281 : {
10282 464 : tree v = TREE_OPERAND (val, 0);
10283 464 : if (lookup_attribute ("omp simd array",
10284 464 : DECL_ATTRIBUTES (v)))
10285 : {
10286 464 : val = unshare_expr (val);
10287 464 : lane0 = TREE_OPERAND (val, 1);
10288 464 : TREE_OPERAND (val, 1) = lane;
10289 464 : var2 = lookup_decl (v, octx);
10290 464 : if (octx->scan_exclusive)
10291 228 : var4 = lookup_decl (var2, octx);
10292 464 : if (input_phase
10293 464 : && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
10294 120 : var3 = maybe_lookup_decl (var4 ? var4 : var2, octx);
10295 464 : if (!input_phase)
10296 : {
10297 232 : var2 = build4 (ARRAY_REF, TREE_TYPE (val),
10298 : var2, lane, NULL_TREE, NULL_TREE);
10299 232 : TREE_THIS_NOTRAP (var2) = 1;
10300 232 : if (octx->scan_exclusive)
10301 : {
10302 114 : var4 = build4 (ARRAY_REF, TREE_TYPE (val),
10303 : var4, lane, NULL_TREE,
10304 : NULL_TREE);
10305 114 : TREE_THIS_NOTRAP (var4) = 1;
10306 : }
10307 : }
10308 : else
10309 : var2 = val;
10310 : }
10311 : }
10312 464 : gcc_assert (var2);
10313 : }
10314 : else
10315 : {
10316 704 : var2 = build_outer_var_ref (var, octx);
10317 704 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
10318 : {
10319 220 : var3 = maybe_lookup_decl (new_vard, octx);
10320 220 : if (var3 == new_vard || var3 == NULL_TREE)
10321 : var3 = NULL_TREE;
10322 108 : else if (is_simd && octx->scan_exclusive && !input_phase)
10323 : {
10324 16 : var4 = maybe_lookup_decl (var3, octx);
10325 16 : if (var4 == var3 || var4 == NULL_TREE)
10326 : {
10327 0 : if (TREE_ADDRESSABLE (TREE_TYPE (new_var)))
10328 : {
10329 : var4 = var3;
10330 : var3 = NULL_TREE;
10331 : }
10332 : else
10333 16 : var4 = NULL_TREE;
10334 : }
10335 : }
10336 : }
10337 672 : if (is_simd
10338 484 : && octx->scan_exclusive
10339 244 : && !input_phase
10340 244 : && var4 == NULL_TREE)
10341 106 : var4 = create_tmp_var (TREE_TYPE (val));
10342 : }
10343 1168 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
10344 : {
10345 376 : tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
10346 376 : if (input_phase)
10347 : {
10348 188 : if (var3)
10349 : {
10350 : /* If we've added a separate identity element
10351 : variable, copy it over into val. */
10352 92 : tree x = lang_hooks.decls.omp_clause_assign_op (c, val,
10353 : var3);
10354 92 : gimplify_and_add (x, &before);
10355 : }
10356 96 : else if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
10357 : {
10358 : /* Otherwise, assign to it the identity element. */
10359 96 : gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
10360 96 : if (is_for)
10361 16 : tseq = copy_gimple_seq_and_replace_locals (tseq);
10362 96 : tree ref = build_outer_var_ref (var, octx);
10363 96 : tree x = (DECL_HAS_VALUE_EXPR_P (new_vard)
10364 96 : ? DECL_VALUE_EXPR (new_vard) : NULL_TREE);
10365 40 : if (x)
10366 : {
10367 40 : if (new_vard != new_var)
10368 8 : val = build_fold_addr_expr_loc (clause_loc, val);
10369 40 : SET_DECL_VALUE_EXPR (new_vard, val);
10370 : }
10371 96 : SET_DECL_VALUE_EXPR (placeholder, ref);
10372 96 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
10373 96 : lower_omp (&tseq, octx);
10374 96 : if (x)
10375 40 : SET_DECL_VALUE_EXPR (new_vard, x);
10376 96 : SET_DECL_VALUE_EXPR (placeholder, NULL_TREE);
10377 96 : DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
10378 96 : gimple_seq_add_seq (&before, tseq);
10379 96 : if (is_simd)
10380 80 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
10381 : }
10382 : }
10383 188 : else if (is_simd)
10384 : {
10385 156 : tree x;
10386 156 : if (octx->scan_exclusive)
10387 : {
10388 72 : tree v4 = unshare_expr (var4);
10389 72 : tree v2 = unshare_expr (var2);
10390 72 : x = lang_hooks.decls.omp_clause_assign_op (c, v4, v2);
10391 72 : gimplify_and_add (x, &before);
10392 : }
10393 156 : gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
10394 156 : x = (DECL_HAS_VALUE_EXPR_P (new_vard)
10395 156 : ? DECL_VALUE_EXPR (new_vard) : NULL_TREE);
10396 156 : tree vexpr = val;
10397 156 : if (x && new_vard != new_var)
10398 30 : vexpr = build_fold_addr_expr_loc (clause_loc, val);
10399 156 : if (x)
10400 78 : SET_DECL_VALUE_EXPR (new_vard, vexpr);
10401 156 : SET_DECL_VALUE_EXPR (placeholder, var2);
10402 156 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
10403 156 : lower_omp (&tseq, octx);
10404 156 : gimple_seq_add_seq (&before, tseq);
10405 156 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
10406 156 : if (x)
10407 78 : SET_DECL_VALUE_EXPR (new_vard, x);
10408 156 : SET_DECL_VALUE_EXPR (placeholder, NULL_TREE);
10409 156 : DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
10410 156 : if (octx->scan_inclusive)
10411 : {
10412 84 : x = lang_hooks.decls.omp_clause_assign_op (c, val,
10413 : var2);
10414 84 : gimplify_and_add (x, &before);
10415 : }
10416 72 : else if (lane0 == NULL_TREE)
10417 : {
10418 36 : x = lang_hooks.decls.omp_clause_assign_op (c, val,
10419 : var4);
10420 36 : gimplify_and_add (x, &before);
10421 : }
10422 : }
10423 : }
10424 : else
10425 : {
10426 792 : if (input_phase)
10427 : {
10428 : /* input phase. Set val to initializer before
10429 : the body. */
10430 396 : tree x = omp_reduction_init (c, TREE_TYPE (new_var));
10431 396 : gimplify_assign (val, x, &before);
10432 : }
10433 396 : else if (is_simd)
10434 : {
10435 : /* scan phase. */
10436 318 : enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
10437 318 : if (code == MINUS_EXPR)
10438 0 : code = PLUS_EXPR;
10439 :
10440 318 : tree x = build2 (code, TREE_TYPE (var2),
10441 : unshare_expr (var2), unshare_expr (val));
10442 318 : if (octx->scan_inclusive)
10443 : {
10444 154 : gimplify_assign (unshare_expr (var2), x, &before);
10445 154 : gimplify_assign (val, var2, &before);
10446 : }
10447 : else
10448 : {
10449 164 : gimplify_assign (unshare_expr (var4),
10450 : unshare_expr (var2), &before);
10451 164 : gimplify_assign (var2, x, &before);
10452 164 : if (lane0 == NULL_TREE)
10453 86 : gimplify_assign (val, var4, &before);
10454 : }
10455 : }
10456 : }
10457 1168 : if (octx->scan_exclusive && !input_phase && lane0)
10458 : {
10459 114 : tree vexpr = unshare_expr (var4);
10460 114 : TREE_OPERAND (vexpr, 1) = lane0;
10461 114 : if (new_vard != new_var)
10462 16 : vexpr = build_fold_addr_expr_loc (clause_loc, vexpr);
10463 114 : SET_DECL_VALUE_EXPR (new_vard, vexpr);
10464 : }
10465 : }
10466 : }
10467 1276 : if (is_simd && !is_for_simd)
10468 : {
10469 590 : gsi_insert_seq_after (gsi_p, gimple_omp_body (stmt), GSI_SAME_STMT);
10470 590 : gsi_insert_seq_after (gsi_p, before, GSI_SAME_STMT);
10471 590 : gsi_replace (gsi_p, gimple_build_nop (), true);
10472 590 : return;
10473 : }
10474 686 : lower_omp (gimple_omp_body_ptr (stmt), octx);
10475 686 : if (before)
10476 : {
10477 260 : gimple_stmt_iterator gsi = gsi_start (*gimple_omp_body_ptr (stmt));
10478 260 : gsi_insert_seq_before (&gsi, before, GSI_SAME_STMT);
10479 : }
10480 : }
10481 :
10482 :
10483 : /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
10484 : substitution of a couple of function calls. But in the NAMED case,
10485 : requires that languages coordinate a symbol name. It is therefore
10486 : best put here in common code. */
10487 :
10488 : static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
10489 :
10490 : static void
10491 311 : lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10492 : {
10493 311 : tree block;
10494 311 : tree name, lock, unlock;
10495 311 : gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10496 311 : gbind *bind;
10497 311 : location_t loc = gimple_location (stmt);
10498 311 : gimple_seq tbody;
10499 :
10500 311 : name = gimple_omp_critical_name (stmt);
10501 311 : if (name)
10502 : {
10503 88 : tree decl;
10504 :
10505 88 : if (!critical_name_mutexes)
10506 48 : critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
10507 :
10508 88 : tree *n = critical_name_mutexes->get (name);
10509 88 : if (n == NULL)
10510 : {
10511 70 : char *new_str;
10512 :
10513 70 : decl = create_tmp_var_raw (ptr_type_node);
10514 :
10515 70 : new_str = ACONCAT ((".gomp_critical_user_",
10516 : IDENTIFIER_POINTER (name), NULL));
10517 70 : DECL_NAME (decl) = get_identifier (new_str);
10518 70 : TREE_PUBLIC (decl) = 1;
10519 70 : TREE_STATIC (decl) = 1;
10520 70 : DECL_COMMON (decl) = 1;
10521 70 : DECL_ARTIFICIAL (decl) = 1;
10522 70 : DECL_IGNORED_P (decl) = 1;
10523 :
10524 70 : varpool_node::finalize_decl (decl);
10525 :
10526 70 : critical_name_mutexes->put (name, decl);
10527 : }
10528 : else
10529 18 : decl = *n;
10530 :
10531 : /* If '#pragma omp critical' is inside offloaded region or
10532 : inside function marked as offloadable, the symbol must be
10533 : marked as offloadable too. */
10534 88 : omp_context *octx;
10535 88 : if (cgraph_node::get (current_function_decl)->offloadable)
10536 1 : varpool_node::get_create (decl)->offloadable = 1;
10537 : else
10538 173 : for (octx = ctx->outer; octx; octx = octx->outer)
10539 87 : if (is_gimple_omp_offloaded (octx->stmt))
10540 : {
10541 1 : varpool_node::get_create (decl)->offloadable = 1;
10542 1 : break;
10543 : }
10544 :
10545 88 : lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
10546 88 : lock = build_call_expr_loc (loc, lock, 1,
10547 : build_fold_addr_expr_loc (loc, decl));
10548 :
10549 88 : unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
10550 88 : unlock = build_call_expr_loc (loc, unlock, 1,
10551 : build_fold_addr_expr_loc (loc, decl));
10552 : }
10553 : else
10554 : {
10555 223 : lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
10556 223 : lock = build_call_expr_loc (loc, lock, 0);
10557 :
10558 223 : unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
10559 223 : unlock = build_call_expr_loc (loc, unlock, 0);
10560 : }
10561 :
10562 311 : push_gimplify_context ();
10563 :
10564 311 : block = make_node (BLOCK);
10565 311 : bind = gimple_build_bind (NULL, NULL, block);
10566 311 : gsi_replace (gsi_p, bind, true);
10567 311 : gimple_bind_add_stmt (bind, stmt);
10568 :
10569 311 : tbody = gimple_bind_body (bind);
10570 311 : gimplify_and_add (lock, &tbody);
10571 311 : gimple_bind_set_body (bind, tbody);
10572 :
10573 311 : lower_omp (gimple_omp_body_ptr (stmt), ctx);
10574 311 : gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10575 311 : gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10576 311 : gimple_omp_set_body (stmt, NULL);
10577 :
10578 311 : tbody = gimple_bind_body (bind);
10579 311 : gimplify_and_add (unlock, &tbody);
10580 311 : gimple_bind_set_body (bind, tbody);
10581 :
10582 311 : gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10583 :
10584 311 : pop_gimplify_context (bind);
10585 311 : gimple_bind_append_vars (bind, ctx->block_vars);
10586 311 : BLOCK_VARS (block) = gimple_bind_vars (bind);
10587 311 : }
10588 :
10589 : /* A subroutine of lower_omp_for. Generate code to emit the predicate
10590 : for a lastprivate clause. Given a loop control predicate of (V
10591 : cond N2), we gate the clause on (!(V cond N2)). The lowered form
10592 : is appended to *DLIST, iterator initialization is appended to
10593 : *BODY_P. *CLIST is for lastprivate(conditional:) code that needs
10594 : to be emitted in a critical section. */
10595 :
10596 : static void
10597 46859 : lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10598 : gimple_seq *dlist, gimple_seq *clist,
10599 : struct omp_context *ctx)
10600 : {
10601 46859 : tree clauses, cond, vinit;
10602 46859 : enum tree_code cond_code;
10603 46859 : gimple_seq stmts;
10604 :
10605 46859 : cond_code = fd->loop.cond_code;
10606 46859 : cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10607 :
10608 : /* When possible, use a strict equality expression. This can let VRP
10609 : type optimizations deduce the value and remove a copy. */
10610 46859 : if (tree_fits_shwi_p (fd->loop.step))
10611 : {
10612 44620 : HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
10613 44620 : if (step == 1 || step == -1)
10614 46859 : cond_code = EQ_EXPR;
10615 : }
10616 :
10617 46859 : tree n2 = fd->loop.n2;
10618 46859 : if (fd->collapse > 1
10619 11233 : && TREE_CODE (n2) != INTEGER_CST
10620 53073 : && gimple_omp_for_combined_into_p (fd->for_stmt))
10621 : {
10622 2692 : struct omp_context *taskreg_ctx = NULL;
10623 2692 : if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
10624 : {
10625 1226 : gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
10626 1226 : if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
10627 1226 : || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
10628 : {
10629 1194 : if (gimple_omp_for_combined_into_p (gfor))
10630 : {
10631 672 : gcc_assert (ctx->outer->outer
10632 : && is_parallel_ctx (ctx->outer->outer));
10633 : taskreg_ctx = ctx->outer->outer;
10634 : }
10635 : else
10636 : {
10637 522 : struct omp_for_data outer_fd;
10638 522 : omp_extract_for_data (gfor, &outer_fd, NULL);
10639 522 : n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
10640 : }
10641 : }
10642 32 : else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
10643 32 : taskreg_ctx = ctx->outer->outer;
10644 : }
10645 1466 : else if (is_taskreg_ctx (ctx->outer))
10646 : taskreg_ctx = ctx->outer;
10647 2692 : if (taskreg_ctx)
10648 : {
10649 2170 : int i;
10650 2170 : tree taskreg_clauses
10651 2170 : = gimple_omp_taskreg_clauses (taskreg_ctx->stmt);
10652 2170 : tree innerc = omp_find_clause (taskreg_clauses,
10653 : OMP_CLAUSE__LOOPTEMP_);
10654 2170 : gcc_assert (innerc);
10655 2170 : int count = fd->collapse;
10656 2170 : if (fd->non_rect
10657 24 : && fd->last_nonrect == fd->first_nonrect + 1)
10658 12 : if (tree v = gimple_omp_for_index (fd->for_stmt, fd->last_nonrect))
10659 12 : if (!TYPE_UNSIGNED (TREE_TYPE (v)))
10660 12 : count += 4;
10661 8582 : for (i = 0; i < count; i++)
10662 : {
10663 6412 : innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
10664 : OMP_CLAUSE__LOOPTEMP_);
10665 6412 : gcc_assert (innerc);
10666 : }
10667 2170 : innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
10668 : OMP_CLAUSE__LOOPTEMP_);
10669 2170 : if (innerc)
10670 1419 : n2 = fold_convert (TREE_TYPE (n2),
10671 : lookup_decl (OMP_CLAUSE_DECL (innerc),
10672 : taskreg_ctx));
10673 : }
10674 : }
10675 46859 : cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
10676 :
10677 46859 : clauses = gimple_omp_for_clauses (fd->for_stmt);
10678 46859 : stmts = NULL;
10679 46859 : lower_lastprivate_clauses (clauses, cond, body_p, &stmts, clist, ctx);
10680 46859 : if (!gimple_seq_empty_p (stmts))
10681 : {
10682 16328 : gimple_seq_add_seq (&stmts, *dlist);
10683 16328 : *dlist = stmts;
10684 :
10685 : /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
10686 16328 : vinit = fd->loop.n1;
10687 16328 : if (cond_code == EQ_EXPR
10688 14347 : && tree_fits_shwi_p (fd->loop.n2)
10689 25861 : && ! integer_zerop (fd->loop.n2))
10690 8317 : vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
10691 : else
10692 8011 : vinit = unshare_expr (vinit);
10693 :
10694 : /* Initialize the iterator variable, so that threads that don't execute
10695 : any iterations don't execute the lastprivate clauses by accident. */
10696 16328 : gimplify_assign (fd->loop.v, vinit, body_p);
10697 : }
10698 46859 : }
10699 :
10700 : /* OpenACC privatization.
10701 :
10702 : Or, in other words, *sharing* at the respective OpenACC level of
10703 : parallelism.
10704 :
10705 : From a correctness perspective, a non-addressable variable can't be accessed
10706 : outside the current thread, so it can go in a (faster than shared memory)
10707 : register -- though that register may need to be broadcast in some
10708 : circumstances. A variable can only meaningfully be "shared" across workers
10709 : or vector lanes if its address is taken, e.g. by a call to an atomic
10710 : builtin.
10711 :
10712 : From an optimisation perspective, the answer might be fuzzier: maybe
10713 : sometimes, using shared memory directly would be faster than
10714 : broadcasting. */
10715 :
10716 : static void
10717 18997 : oacc_privatization_begin_diagnose_var (const dump_flags_t l_dump_flags,
10718 : const location_t loc, const tree c,
10719 : const tree decl)
10720 : {
10721 18997 : const dump_user_location_t d_u_loc
10722 18997 : = dump_user_location_t::from_location_t (loc);
10723 : /* PR100695 "Format decoder, quoting in 'dump_printf' etc." */
10724 : #if __GNUC__ >= 10
10725 18997 : # pragma GCC diagnostic push
10726 18997 : # pragma GCC diagnostic ignored "-Wformat"
10727 : #endif
10728 18997 : dump_printf_loc (l_dump_flags, d_u_loc,
10729 : "variable %<%T%> ", decl);
10730 : #if __GNUC__ >= 10
10731 18997 : # pragma GCC diagnostic pop
10732 : #endif
10733 18997 : if (c)
10734 2797 : dump_printf (l_dump_flags,
10735 : "in %qs clause ",
10736 2797 : omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
10737 : else
10738 16200 : dump_printf (l_dump_flags,
10739 : "declared in block ");
10740 18997 : }
10741 :
10742 : static bool
10743 41114 : oacc_privatization_candidate_p (const location_t loc, const tree c,
10744 : const tree decl)
10745 : {
10746 41114 : dump_flags_t l_dump_flags = get_openacc_privatization_dump_flags ();
10747 :
10748 : /* There is some differentiation depending on block vs. clause. */
10749 41114 : bool block = !c;
10750 :
10751 41114 : bool res = true;
10752 :
10753 41114 : if (res && !VAR_P (decl))
10754 : {
10755 : /* A PARM_DECL (appearing in a 'private' clause) is expected to have been
10756 : privatized into a new VAR_DECL. */
10757 712 : gcc_checking_assert (TREE_CODE (decl) != PARM_DECL);
10758 :
10759 712 : res = false;
10760 :
10761 712 : if (dump_enabled_p ())
10762 : {
10763 683 : oacc_privatization_begin_diagnose_var (l_dump_flags, loc, c, decl);
10764 683 : dump_printf (l_dump_flags,
10765 : "potentially has improper OpenACC privatization level: %qs\n",
10766 683 : get_tree_code_name (TREE_CODE (decl)));
10767 : }
10768 : }
10769 :
10770 41085 : if (res && block && TREE_STATIC (decl))
10771 : {
10772 53 : res = false;
10773 :
10774 53 : if (dump_enabled_p ())
10775 : {
10776 28 : oacc_privatization_begin_diagnose_var (l_dump_flags, loc, c, decl);
10777 28 : dump_printf (l_dump_flags,
10778 : "isn%'t candidate for adjusting OpenACC privatization level: %s\n",
10779 : "static");
10780 : }
10781 : }
10782 :
10783 41089 : if (res && block && DECL_EXTERNAL (decl))
10784 : {
10785 12 : res = false;
10786 :
10787 12 : if (dump_enabled_p ())
10788 : {
10789 12 : oacc_privatization_begin_diagnose_var (l_dump_flags, loc, c, decl);
10790 12 : dump_printf (l_dump_flags,
10791 : "isn%'t candidate for adjusting OpenACC privatization level: %s\n",
10792 : "external");
10793 : }
10794 : }
10795 :
10796 41114 : if (res && !TREE_ADDRESSABLE (decl))
10797 : {
10798 39245 : res = false;
10799 :
10800 39245 : if (dump_enabled_p ())
10801 : {
10802 17456 : oacc_privatization_begin_diagnose_var (l_dump_flags, loc, c, decl);
10803 17456 : dump_printf (l_dump_flags,
10804 : "isn%'t candidate for adjusting OpenACC privatization level: %s\n",
10805 : "not addressable");
10806 : }
10807 : }
10808 :
10809 : /* If an artificial variable has been added to a bind, e.g.
10810 : a compiler-generated temporary structure used by the Fortran front-end, do
10811 : not consider it as a privatization candidate. Note that variables on
10812 : the stack are private per-thread by default: making them "gang-private"
10813 : for OpenACC actually means to share a single instance of a variable
10814 : amongst all workers and threads spawned within each gang.
10815 : At present, no compiler-generated artificial variables require such
10816 : sharing semantics, so this is safe. */
10817 :
10818 18548 : if (res && block && DECL_ARTIFICIAL (decl))
10819 : {
10820 548 : res = false;
10821 :
10822 548 : if (dump_enabled_p ())
10823 : {
10824 360 : oacc_privatization_begin_diagnose_var (l_dump_flags, loc, c, decl);
10825 360 : dump_printf (l_dump_flags,
10826 : "isn%'t candidate for adjusting OpenACC privatization "
10827 : "level: %s\n", "artificial");
10828 : }
10829 : }
10830 :
10831 40926 : if (res)
10832 : {
10833 544 : if (dump_enabled_p ())
10834 : {
10835 458 : oacc_privatization_begin_diagnose_var (l_dump_flags, loc, c, decl);
10836 458 : dump_printf (l_dump_flags,
10837 : "is candidate for adjusting OpenACC privatization level\n");
10838 : }
10839 : }
10840 :
10841 41114 : if (dump_file && (dump_flags & TDF_DETAILS))
10842 : {
10843 0 : print_generic_decl (dump_file, decl, dump_flags);
10844 0 : fprintf (dump_file, "\n");
10845 : }
10846 :
10847 41114 : return res;
10848 : }
10849 :
10850 : /* Scan CLAUSES for candidates for adjusting OpenACC privatization level in
10851 : CTX. */
10852 :
10853 : static void
10854 11325 : oacc_privatization_scan_clause_chain (omp_context *ctx, tree clauses)
10855 : {
10856 35223 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
10857 23898 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE)
10858 : {
10859 12986 : tree decl = OMP_CLAUSE_DECL (c);
10860 :
10861 12986 : tree new_decl = lookup_decl (decl, ctx);
10862 :
10863 12986 : if (!oacc_privatization_candidate_p (OMP_CLAUSE_LOCATION (c), c,
10864 : new_decl))
10865 12654 : continue;
10866 :
10867 332 : gcc_checking_assert
10868 : (!ctx->oacc_privatization_candidates.contains (new_decl));
10869 332 : ctx->oacc_privatization_candidates.safe_push (new_decl);
10870 : }
10871 11325 : }
10872 :
10873 : /* Scan DECLS for candidates for adjusting OpenACC privatization level in
10874 : CTX. */
10875 :
10876 : static void
10877 23090 : oacc_privatization_scan_decl_chain (omp_context *ctx, tree decls)
10878 : {
10879 51218 : for (tree decl = decls; decl; decl = DECL_CHAIN (decl))
10880 : {
10881 28128 : tree new_decl = lookup_decl (decl, ctx);
10882 28128 : gcc_checking_assert (new_decl == decl);
10883 :
10884 28128 : if (!oacc_privatization_candidate_p (gimple_location (ctx->stmt), NULL,
10885 : new_decl))
10886 27916 : continue;
10887 :
10888 212 : gcc_checking_assert
10889 : (!ctx->oacc_privatization_candidates.contains (new_decl));
10890 212 : ctx->oacc_privatization_candidates.safe_push (new_decl);
10891 : }
10892 23090 : }
10893 :
10894 : /* Callback for walk_gimple_seq. Find #pragma omp scan statement. */
10895 :
10896 : static tree
10897 2233 : omp_find_scan (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10898 : struct walk_stmt_info *wi)
10899 : {
10900 2233 : gimple *stmt = gsi_stmt (*gsi_p);
10901 :
10902 2233 : *handled_ops_p = true;
10903 2233 : switch (gimple_code (stmt))
10904 : {
10905 418 : WALK_SUBSTMTS;
10906 :
10907 166 : case GIMPLE_OMP_FOR:
10908 166 : if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_SIMD
10909 166 : && gimple_omp_for_combined_into_p (stmt))
10910 166 : *handled_ops_p = false;
10911 : break;
10912 :
10913 686 : case GIMPLE_OMP_SCAN:
10914 686 : *(gimple_stmt_iterator *) (wi->info) = *gsi_p;
10915 686 : return integer_zero_node;
10916 : default:
10917 : break;
10918 : }
10919 : return NULL;
10920 : }
10921 :
10922 : /* Helper function for lower_omp_for, add transformations for a worksharing
10923 : loop with scan directives inside of it.
10924 : For worksharing loop not combined with simd, transform:
10925 : #pragma omp for reduction(inscan,+:r) private(i)
10926 : for (i = 0; i < n; i = i + 1)
10927 : {
10928 : {
10929 : update (r);
10930 : }
10931 : #pragma omp scan inclusive(r)
10932 : {
10933 : use (r);
10934 : }
10935 : }
10936 :
10937 : into two worksharing loops + code to merge results:
10938 :
10939 : num_threads = omp_get_num_threads ();
10940 : thread_num = omp_get_thread_num ();
10941 : if (thread_num == 0) goto <D.2099>; else goto <D.2100>;
10942 : <D.2099>:
10943 : var2 = r;
10944 : goto <D.2101>;
10945 : <D.2100>:
10946 : // For UDRs this is UDR init, or if ctors are needed, copy from
10947 : // var3 that has been constructed to contain the neutral element.
10948 : var2 = 0;
10949 : <D.2101>:
10950 : ivar = 0;
10951 : // The _scantemp_ clauses will arrange for rpriva to be initialized to
10952 : // a shared array with num_threads elements and rprivb to a local array
10953 : // number of elements equal to the number of (contiguous) iterations the
10954 : // current thread will perform. controlb and controlp variables are
10955 : // temporaries to handle deallocation of rprivb at the end of second
10956 : // GOMP_FOR.
10957 : #pragma omp for _scantemp_(rpriva) _scantemp_(rprivb) _scantemp_(controlb) \
10958 : _scantemp_(controlp) reduction(inscan,+:r) private(i) nowait
10959 : for (i = 0; i < n; i = i + 1)
10960 : {
10961 : {
10962 : // For UDRs this is UDR init or copy from var3.
10963 : r = 0;
10964 : // This is the input phase from user code.
10965 : update (r);
10966 : }
10967 : {
10968 : // For UDRs this is UDR merge.
10969 : var2 = var2 + r;
10970 : // Rather than handing it over to the user, save to local thread's
10971 : // array.
10972 : rprivb[ivar] = var2;
10973 : // For exclusive scan, the above two statements are swapped.
10974 : ivar = ivar + 1;
10975 : }
10976 : }
10977 : // And remember the final value from this thread's into the shared
10978 : // rpriva array.
10979 : rpriva[(sizetype) thread_num] = var2;
10980 : // If more than one thread, compute using Work-Efficient prefix sum
10981 : // the inclusive parallel scan of the rpriva array.
10982 : if (num_threads > 1) goto <D.2102>; else goto <D.2103>;
10983 : <D.2102>:
10984 : GOMP_barrier ();
10985 : down = 0;
10986 : k = 1;
10987 : num_threadsu = (unsigned int) num_threads;
10988 : thread_numup1 = (unsigned int) thread_num + 1;
10989 : <D.2108>:
10990 : twok = k << 1;
10991 : if (twok > num_threadsu) goto <D.2110>; else goto <D.2111>;
10992 : <D.2110>:
10993 : down = 4294967295;
10994 : k = k >> 1;
10995 : if (k == num_threadsu) goto <D.2112>; else goto <D.2111>;
10996 : <D.2112>:
10997 : k = k >> 1;
10998 : <D.2111>:
10999 : twok = k << 1;
11000 : cplx = .MUL_OVERFLOW (thread_nump1, twok);
11001 : mul = REALPART_EXPR <cplx>;
11002 : ovf = IMAGPART_EXPR <cplx>;
11003 : if (ovf == 0) goto <D.2116>; else goto <D.2117>;
11004 : <D.2116>:
11005 : andv = k & down;
11006 : andvm1 = andv + 4294967295;
11007 : l = mul + andvm1;
11008 : if (l < num_threadsu) goto <D.2120>; else goto <D.2117>;
11009 : <D.2120>:
11010 : // For UDRs this is UDR merge, performed using var2 variable as temporary,
11011 : // i.e. var2 = rpriva[l - k]; UDR merge (var2, rpriva[l]); rpriva[l] = var2;
11012 : rpriva[l] = rpriva[l - k] + rpriva[l];
11013 : <D.2117>:
11014 : if (down == 0) goto <D.2121>; else goto <D.2122>;
11015 : <D.2121>:
11016 : k = k << 1;
11017 : goto <D.2123>;
11018 : <D.2122>:
11019 : k = k >> 1;
11020 : <D.2123>:
11021 : GOMP_barrier ();
11022 : if (k != 0) goto <D.2108>; else goto <D.2103>;
11023 : <D.2103>:
11024 : if (thread_num == 0) goto <D.2124>; else goto <D.2125>;
11025 : <D.2124>:
11026 : // For UDRs this is UDR init or copy from var3.
11027 : var2 = 0;
11028 : goto <D.2126>;
11029 : <D.2125>:
11030 : var2 = rpriva[thread_num - 1];
11031 : <D.2126>:
11032 : ivar = 0;
11033 : #pragma omp for _scantemp_(controlb) _scantemp_(controlp) \
11034 : reduction(inscan,+:r) private(i)
11035 : for (i = 0; i < n; i = i + 1)
11036 : {
11037 : {
11038 : // For UDRs, this is r = var2; UDR merge (r, rprivb[ivar]);
11039 : r = var2 + rprivb[ivar];
11040 : }
11041 : {
11042 : // This is the scan phase from user code.
11043 : use (r);
11044 : // Plus a bump of the iterator.
11045 : ivar = ivar + 1;
11046 : }
11047 : } */
11048 :
11049 : static void
11050 177 : lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt,
11051 : struct omp_for_data *fd, omp_context *ctx)
11052 : {
11053 177 : bool is_for_simd = gimple_omp_for_combined_p (stmt);
11054 177 : gcc_assert (ctx->scan_inclusive || ctx->scan_exclusive);
11055 :
11056 177 : gimple_seq body = gimple_omp_body (stmt);
11057 177 : gimple_stmt_iterator input1_gsi = gsi_none ();
11058 177 : struct walk_stmt_info wi;
11059 177 : memset (&wi, 0, sizeof (wi));
11060 177 : wi.val_only = true;
11061 177 : wi.info = (void *) &input1_gsi;
11062 177 : walk_gimple_seq_mod (&body, omp_find_scan, NULL, &wi);
11063 177 : gcc_assert (!gsi_end_p (input1_gsi));
11064 :
11065 177 : gimple *input_stmt1 = gsi_stmt (input1_gsi);
11066 177 : gimple_stmt_iterator gsi = input1_gsi;
11067 177 : gsi_next (&gsi);
11068 177 : gimple_stmt_iterator scan1_gsi = gsi;
11069 177 : gimple *scan_stmt1 = gsi_stmt (gsi);
11070 177 : gcc_assert (scan_stmt1 && gimple_code (scan_stmt1) == GIMPLE_OMP_SCAN);
11071 :
11072 177 : gimple_seq input_body = gimple_omp_body (input_stmt1);
11073 177 : gimple_seq scan_body = gimple_omp_body (scan_stmt1);
11074 177 : gimple_omp_set_body (input_stmt1, NULL);
11075 177 : gimple_omp_set_body (scan_stmt1, NULL);
11076 177 : gimple_omp_set_body (stmt, NULL);
11077 :
11078 177 : gomp_for *new_stmt = as_a <gomp_for *> (gimple_copy (stmt));
11079 177 : gimple_seq new_body = copy_gimple_seq_and_replace_locals (body);
11080 177 : gimple_omp_set_body (stmt, body);
11081 177 : gimple_omp_set_body (input_stmt1, input_body);
11082 :
11083 177 : gimple_stmt_iterator input2_gsi = gsi_none ();
11084 177 : memset (&wi, 0, sizeof (wi));
11085 177 : wi.val_only = true;
11086 177 : wi.info = (void *) &input2_gsi;
11087 177 : walk_gimple_seq_mod (&new_body, omp_find_scan, NULL, &wi);
11088 177 : gcc_assert (!gsi_end_p (input2_gsi));
11089 :
11090 177 : gimple *input_stmt2 = gsi_stmt (input2_gsi);
11091 177 : gsi = input2_gsi;
11092 177 : gsi_next (&gsi);
11093 177 : gimple_stmt_iterator scan2_gsi = gsi;
11094 177 : gimple *scan_stmt2 = gsi_stmt (gsi);
11095 177 : gcc_assert (scan_stmt2 && gimple_code (scan_stmt2) == GIMPLE_OMP_SCAN);
11096 177 : gimple_omp_set_body (scan_stmt2, scan_body);
11097 :
11098 177 : gimple_stmt_iterator input3_gsi = gsi_none ();
11099 177 : gimple_stmt_iterator scan3_gsi = gsi_none ();
11100 177 : gimple_stmt_iterator input4_gsi = gsi_none ();
11101 177 : gimple_stmt_iterator scan4_gsi = gsi_none ();
11102 177 : gimple *input_stmt3 = NULL, *scan_stmt3 = NULL;
11103 177 : gimple *input_stmt4 = NULL, *scan_stmt4 = NULL;
11104 177 : omp_context *input_simd_ctx = NULL, *scan_simd_ctx = NULL;
11105 177 : if (is_for_simd)
11106 : {
11107 83 : memset (&wi, 0, sizeof (wi));
11108 83 : wi.val_only = true;
11109 83 : wi.info = (void *) &input3_gsi;
11110 83 : walk_gimple_seq_mod (&input_body, omp_find_scan, NULL, &wi);
11111 83 : gcc_assert (!gsi_end_p (input3_gsi));
11112 :
11113 83 : input_stmt3 = gsi_stmt (input3_gsi);
11114 83 : gsi = input3_gsi;
11115 83 : gsi_next (&gsi);
11116 83 : scan3_gsi = gsi;
11117 83 : scan_stmt3 = gsi_stmt (gsi);
11118 83 : gcc_assert (scan_stmt3 && gimple_code (scan_stmt3) == GIMPLE_OMP_SCAN);
11119 :
11120 83 : memset (&wi, 0, sizeof (wi));
11121 83 : wi.val_only = true;
11122 83 : wi.info = (void *) &input4_gsi;
11123 83 : walk_gimple_seq_mod (&scan_body, omp_find_scan, NULL, &wi);
11124 83 : gcc_assert (!gsi_end_p (input4_gsi));
11125 :
11126 83 : input_stmt4 = gsi_stmt (input4_gsi);
11127 83 : gsi = input4_gsi;
11128 83 : gsi_next (&gsi);
11129 83 : scan4_gsi = gsi;
11130 83 : scan_stmt4 = gsi_stmt (gsi);
11131 83 : gcc_assert (scan_stmt4 && gimple_code (scan_stmt4) == GIMPLE_OMP_SCAN);
11132 :
11133 83 : input_simd_ctx = maybe_lookup_ctx (input_stmt3)->outer;
11134 83 : scan_simd_ctx = maybe_lookup_ctx (input_stmt4)->outer;
11135 : }
11136 :
11137 177 : tree num_threads = create_tmp_var (integer_type_node);
11138 177 : tree thread_num = create_tmp_var (integer_type_node);
11139 177 : tree nthreads_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
11140 177 : tree threadnum_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
11141 177 : gimple *g = gimple_build_call (nthreads_decl, 0);
11142 177 : gimple_call_set_lhs (g, num_threads);
11143 177 : gimple_seq_add_stmt (body_p, g);
11144 177 : g = gimple_build_call (threadnum_decl, 0);
11145 177 : gimple_call_set_lhs (g, thread_num);
11146 177 : gimple_seq_add_stmt (body_p, g);
11147 :
11148 177 : tree ivar = create_tmp_var (sizetype);
11149 177 : tree new_clauses1 = NULL_TREE, new_clauses2 = NULL_TREE;
11150 177 : tree *cp1 = &new_clauses1, *cp2 = &new_clauses2;
11151 177 : tree k = create_tmp_var (unsigned_type_node);
11152 177 : tree l = create_tmp_var (unsigned_type_node);
11153 :
11154 177 : gimple_seq clist = NULL, mdlist = NULL;
11155 177 : gimple_seq thr01_list = NULL, thrn1_list = NULL;
11156 177 : gimple_seq thr02_list = NULL, thrn2_list = NULL;
11157 177 : gimple_seq scan1_list = NULL, input2_list = NULL;
11158 177 : gimple_seq last_list = NULL, reduc_list = NULL;
11159 686 : for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
11160 509 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
11161 509 : && OMP_CLAUSE_REDUCTION_INSCAN (c))
11162 : {
11163 209 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
11164 209 : tree var = OMP_CLAUSE_DECL (c);
11165 209 : tree new_var = lookup_decl (var, ctx);
11166 209 : tree var3 = NULL_TREE;
11167 209 : tree new_vard = new_var;
11168 209 : if (omp_privatize_by_reference (var))
11169 32 : new_var = build_simple_mem_ref_loc (clause_loc, new_var);
11170 209 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
11171 : {
11172 64 : var3 = maybe_lookup_decl (new_vard, ctx);
11173 64 : if (var3 == new_vard)
11174 177 : var3 = NULL_TREE;
11175 : }
11176 :
11177 209 : tree ptype = build_pointer_type (TREE_TYPE (new_var));
11178 209 : tree rpriva = create_tmp_var (ptype);
11179 209 : tree nc = build_omp_clause (clause_loc, OMP_CLAUSE__SCANTEMP_);
11180 209 : OMP_CLAUSE_DECL (nc) = rpriva;
11181 209 : *cp1 = nc;
11182 209 : cp1 = &OMP_CLAUSE_CHAIN (nc);
11183 :
11184 209 : tree rprivb = create_tmp_var (ptype);
11185 209 : nc = build_omp_clause (clause_loc, OMP_CLAUSE__SCANTEMP_);
11186 209 : OMP_CLAUSE_DECL (nc) = rprivb;
11187 209 : OMP_CLAUSE__SCANTEMP__ALLOC (nc) = 1;
11188 209 : *cp1 = nc;
11189 209 : cp1 = &OMP_CLAUSE_CHAIN (nc);
11190 :
11191 209 : tree var2 = create_tmp_var_raw (TREE_TYPE (new_var));
11192 209 : if (new_vard != new_var)
11193 32 : TREE_ADDRESSABLE (var2) = 1;
11194 209 : gimple_add_tmp_var (var2);
11195 :
11196 209 : tree x = fold_convert_loc (clause_loc, sizetype, thread_num);
11197 209 : x = fold_build2_loc (clause_loc, MULT_EXPR, sizetype, x,
11198 209 : TYPE_SIZE_UNIT (TREE_TYPE (ptype)));
11199 209 : x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rpriva), rpriva, x);
11200 209 : tree rpriva_ref = build_simple_mem_ref_loc (clause_loc, x);
11201 :
11202 209 : x = fold_build2_loc (clause_loc, PLUS_EXPR, integer_type_node,
11203 : thread_num, integer_minus_one_node);
11204 209 : x = fold_convert_loc (clause_loc, sizetype, x);
11205 209 : x = fold_build2_loc (clause_loc, MULT_EXPR, sizetype, x,
11206 209 : TYPE_SIZE_UNIT (TREE_TYPE (ptype)));
11207 209 : x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rpriva), rpriva, x);
11208 209 : tree rprivam1_ref = build_simple_mem_ref_loc (clause_loc, x);
11209 :
11210 209 : x = fold_convert_loc (clause_loc, sizetype, l);
11211 209 : x = fold_build2_loc (clause_loc, MULT_EXPR, sizetype, x,
11212 209 : TYPE_SIZE_UNIT (TREE_TYPE (ptype)));
11213 209 : x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rpriva), rpriva, x);
11214 209 : tree rprival_ref = build_simple_mem_ref_loc (clause_loc, x);
11215 :
11216 209 : x = fold_build2_loc (clause_loc, MINUS_EXPR, unsigned_type_node, l, k);
11217 209 : x = fold_convert_loc (clause_loc, sizetype, x);
11218 209 : x = fold_build2_loc (clause_loc, MULT_EXPR, sizetype, x,
11219 209 : TYPE_SIZE_UNIT (TREE_TYPE (ptype)));
11220 209 : x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rpriva), rpriva, x);
11221 209 : tree rprivalmk_ref = build_simple_mem_ref_loc (clause_loc, x);
11222 :
11223 209 : x = fold_build2_loc (clause_loc, MULT_EXPR, sizetype, ivar,
11224 209 : TYPE_SIZE_UNIT (TREE_TYPE (ptype)));
11225 209 : x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rprivb), rprivb, x);
11226 209 : tree rprivb_ref = build_simple_mem_ref_loc (clause_loc, x);
11227 :
11228 209 : tree var4 = is_for_simd ? new_var : var2;
11229 99 : tree var5 = NULL_TREE, var6 = NULL_TREE;
11230 99 : if (is_for_simd)
11231 : {
11232 99 : var5 = lookup_decl (var, input_simd_ctx);
11233 99 : var6 = lookup_decl (var, scan_simd_ctx);
11234 99 : if (new_vard != new_var)
11235 : {
11236 16 : var5 = build_simple_mem_ref_loc (clause_loc, var5);
11237 16 : var6 = build_simple_mem_ref_loc (clause_loc, var6);
11238 : }
11239 : }
11240 209 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
11241 : {
11242 64 : tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
11243 64 : tree val = var2;
11244 :
11245 64 : x = lang_hooks.decls.omp_clause_default_ctor
11246 64 : (c, var2, build_outer_var_ref (var, ctx));
11247 64 : if (x)
11248 32 : gimplify_and_add (x, &clist);
11249 :
11250 64 : x = build_outer_var_ref (var, ctx);
11251 64 : x = lang_hooks.decls.omp_clause_assign_op (c, unshare_expr (var4),
11252 : x);
11253 64 : gimplify_and_add (x, &thr01_list);
11254 :
11255 64 : tree y = (DECL_HAS_VALUE_EXPR_P (new_vard)
11256 64 : ? DECL_VALUE_EXPR (new_vard) : NULL_TREE);
11257 64 : if (var3)
11258 : {
11259 32 : x = unshare_expr (var4);
11260 32 : x = lang_hooks.decls.omp_clause_assign_op (c, x, var3);
11261 32 : gimplify_and_add (x, &thrn1_list);
11262 32 : x = unshare_expr (var4);
11263 32 : x = lang_hooks.decls.omp_clause_assign_op (c, x, var3);
11264 32 : gimplify_and_add (x, &thr02_list);
11265 : }
11266 32 : else if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
11267 : {
11268 : /* Otherwise, assign to it the identity element. */
11269 32 : gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
11270 32 : tseq = copy_gimple_seq_and_replace_locals (tseq);
11271 32 : if (!is_for_simd)
11272 : {
11273 16 : if (new_vard != new_var)
11274 4 : val = build_fold_addr_expr_loc (clause_loc, val);
11275 16 : SET_DECL_VALUE_EXPR (new_vard, val);
11276 16 : DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
11277 : }
11278 32 : SET_DECL_VALUE_EXPR (placeholder, error_mark_node);
11279 32 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
11280 32 : lower_omp (&tseq, ctx);
11281 32 : gimple_seq_add_seq (&thrn1_list, tseq);
11282 32 : tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
11283 32 : lower_omp (&tseq, ctx);
11284 32 : gimple_seq_add_seq (&thr02_list, tseq);
11285 32 : SET_DECL_VALUE_EXPR (placeholder, NULL_TREE);
11286 32 : DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
11287 32 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
11288 32 : if (y)
11289 0 : SET_DECL_VALUE_EXPR (new_vard, y);
11290 : else
11291 : {
11292 32 : DECL_HAS_VALUE_EXPR_P (new_vard) = 0;
11293 32 : SET_DECL_VALUE_EXPR (new_vard, NULL_TREE);
11294 : }
11295 : }
11296 :
11297 64 : x = unshare_expr (var4);
11298 64 : x = lang_hooks.decls.omp_clause_assign_op (c, x, rprivam1_ref);
11299 64 : gimplify_and_add (x, &thrn2_list);
11300 :
11301 64 : if (is_for_simd)
11302 : {
11303 32 : x = unshare_expr (rprivb_ref);
11304 32 : x = lang_hooks.decls.omp_clause_assign_op (c, x, var5);
11305 32 : gimplify_and_add (x, &scan1_list);
11306 : }
11307 : else
11308 : {
11309 32 : if (ctx->scan_exclusive)
11310 : {
11311 16 : x = unshare_expr (rprivb_ref);
11312 16 : x = lang_hooks.decls.omp_clause_assign_op (c, x, var2);
11313 16 : gimplify_and_add (x, &scan1_list);
11314 : }
11315 :
11316 32 : gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
11317 32 : tseq = copy_gimple_seq_and_replace_locals (tseq);
11318 32 : SET_DECL_VALUE_EXPR (placeholder, var2);
11319 32 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
11320 32 : lower_omp (&tseq, ctx);
11321 32 : gimple_seq_add_seq (&scan1_list, tseq);
11322 :
11323 32 : if (ctx->scan_inclusive)
11324 : {
11325 16 : x = unshare_expr (rprivb_ref);
11326 16 : x = lang_hooks.decls.omp_clause_assign_op (c, x, var2);
11327 16 : gimplify_and_add (x, &scan1_list);
11328 : }
11329 : }
11330 :
11331 64 : x = unshare_expr (rpriva_ref);
11332 64 : x = lang_hooks.decls.omp_clause_assign_op (c, x,
11333 : unshare_expr (var4));
11334 64 : gimplify_and_add (x, &mdlist);
11335 :
11336 96 : x = unshare_expr (is_for_simd ? var6 : new_var);
11337 64 : x = lang_hooks.decls.omp_clause_assign_op (c, x, var4);
11338 64 : gimplify_and_add (x, &input2_list);
11339 :
11340 64 : val = rprivb_ref;
11341 64 : if (new_vard != new_var)
11342 24 : val = build_fold_addr_expr_loc (clause_loc, val);
11343 :
11344 64 : gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
11345 64 : tseq = copy_gimple_seq_and_replace_locals (tseq);
11346 64 : SET_DECL_VALUE_EXPR (new_vard, val);
11347 64 : DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
11348 64 : if (is_for_simd)
11349 : {
11350 32 : SET_DECL_VALUE_EXPR (placeholder, var6);
11351 32 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
11352 : }
11353 : else
11354 32 : DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
11355 64 : lower_omp (&tseq, ctx);
11356 64 : if (y)
11357 0 : SET_DECL_VALUE_EXPR (new_vard, y);
11358 : else
11359 : {
11360 64 : DECL_HAS_VALUE_EXPR_P (new_vard) = 0;
11361 64 : SET_DECL_VALUE_EXPR (new_vard, NULL_TREE);
11362 : }
11363 64 : if (!is_for_simd)
11364 : {
11365 32 : SET_DECL_VALUE_EXPR (placeholder, new_var);
11366 32 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
11367 32 : lower_omp (&tseq, ctx);
11368 : }
11369 64 : gimple_seq_add_seq (&input2_list, tseq);
11370 :
11371 64 : x = build_outer_var_ref (var, ctx);
11372 64 : x = lang_hooks.decls.omp_clause_assign_op (c, x, rpriva_ref);
11373 64 : gimplify_and_add (x, &last_list);
11374 :
11375 64 : x = lang_hooks.decls.omp_clause_assign_op (c, var2, rprivalmk_ref);
11376 64 : gimplify_and_add (x, &reduc_list);
11377 64 : tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
11378 64 : tseq = copy_gimple_seq_and_replace_locals (tseq);
11379 64 : val = rprival_ref;
11380 64 : if (new_vard != new_var)
11381 24 : val = build_fold_addr_expr_loc (clause_loc, val);
11382 64 : SET_DECL_VALUE_EXPR (new_vard, val);
11383 64 : DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
11384 64 : SET_DECL_VALUE_EXPR (placeholder, var2);
11385 64 : lower_omp (&tseq, ctx);
11386 64 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
11387 64 : SET_DECL_VALUE_EXPR (placeholder, NULL_TREE);
11388 64 : DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
11389 64 : if (y)
11390 0 : SET_DECL_VALUE_EXPR (new_vard, y);
11391 : else
11392 : {
11393 64 : DECL_HAS_VALUE_EXPR_P (new_vard) = 0;
11394 64 : SET_DECL_VALUE_EXPR (new_vard, NULL_TREE);
11395 : }
11396 64 : gimple_seq_add_seq (&reduc_list, tseq);
11397 64 : x = lang_hooks.decls.omp_clause_assign_op (c, rprival_ref, var2);
11398 64 : gimplify_and_add (x, &reduc_list);
11399 :
11400 64 : x = lang_hooks.decls.omp_clause_dtor (c, var2);
11401 64 : if (x)
11402 32 : gimplify_and_add (x, dlist);
11403 : }
11404 : else
11405 : {
11406 145 : x = build_outer_var_ref (var, ctx);
11407 145 : gimplify_assign (unshare_expr (var4), x, &thr01_list);
11408 :
11409 145 : x = omp_reduction_init (c, TREE_TYPE (new_var));
11410 145 : gimplify_assign (unshare_expr (var4), unshare_expr (x),
11411 : &thrn1_list);
11412 145 : gimplify_assign (unshare_expr (var4), x, &thr02_list);
11413 :
11414 145 : gimplify_assign (unshare_expr (var4), rprivam1_ref, &thrn2_list);
11415 :
11416 145 : enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
11417 145 : if (code == MINUS_EXPR)
11418 0 : code = PLUS_EXPR;
11419 :
11420 145 : if (is_for_simd)
11421 67 : gimplify_assign (unshare_expr (rprivb_ref), var5, &scan1_list);
11422 : else
11423 : {
11424 78 : if (ctx->scan_exclusive)
11425 28 : gimplify_assign (unshare_expr (rprivb_ref), var2,
11426 : &scan1_list);
11427 78 : x = build2 (code, TREE_TYPE (new_var), var2, new_var);
11428 78 : gimplify_assign (var2, x, &scan1_list);
11429 78 : if (ctx->scan_inclusive)
11430 50 : gimplify_assign (unshare_expr (rprivb_ref), var2,
11431 : &scan1_list);
11432 : }
11433 :
11434 145 : gimplify_assign (unshare_expr (rpriva_ref), unshare_expr (var4),
11435 : &mdlist);
11436 :
11437 145 : x = build2 (code, TREE_TYPE (new_var), var4, rprivb_ref);
11438 223 : gimplify_assign (is_for_simd ? var6 : new_var, x, &input2_list);
11439 :
11440 145 : gimplify_assign (build_outer_var_ref (var, ctx), rpriva_ref,
11441 : &last_list);
11442 :
11443 145 : x = build2 (code, TREE_TYPE (new_var), rprivalmk_ref,
11444 : unshare_expr (rprival_ref));
11445 145 : gimplify_assign (rprival_ref, x, &reduc_list);
11446 : }
11447 : }
11448 :
11449 177 : g = gimple_build_assign (ivar, PLUS_EXPR, ivar, size_one_node);
11450 177 : gimple_seq_add_stmt (&scan1_list, g);
11451 177 : g = gimple_build_assign (ivar, PLUS_EXPR, ivar, size_one_node);
11452 271 : gimple_seq_add_stmt (gimple_omp_body_ptr (is_for_simd
11453 : ? scan_stmt4 : scan_stmt2), g);
11454 :
11455 177 : tree controlb = create_tmp_var (boolean_type_node);
11456 177 : tree controlp = create_tmp_var (ptr_type_node);
11457 177 : tree nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SCANTEMP_);
11458 177 : OMP_CLAUSE_DECL (nc) = controlb;
11459 177 : OMP_CLAUSE__SCANTEMP__CONTROL (nc) = 1;
11460 177 : *cp1 = nc;
11461 177 : cp1 = &OMP_CLAUSE_CHAIN (nc);
11462 177 : nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SCANTEMP_);
11463 177 : OMP_CLAUSE_DECL (nc) = controlp;
11464 177 : OMP_CLAUSE__SCANTEMP__CONTROL (nc) = 1;
11465 177 : *cp1 = nc;
11466 177 : cp1 = &OMP_CLAUSE_CHAIN (nc);
11467 177 : nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SCANTEMP_);
11468 177 : OMP_CLAUSE_DECL (nc) = controlb;
11469 177 : OMP_CLAUSE__SCANTEMP__CONTROL (nc) = 1;
11470 177 : *cp2 = nc;
11471 177 : cp2 = &OMP_CLAUSE_CHAIN (nc);
11472 177 : nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SCANTEMP_);
11473 177 : OMP_CLAUSE_DECL (nc) = controlp;
11474 177 : OMP_CLAUSE__SCANTEMP__CONTROL (nc) = 1;
11475 177 : *cp2 = nc;
11476 177 : cp2 = &OMP_CLAUSE_CHAIN (nc);
11477 :
11478 177 : *cp1 = gimple_omp_for_clauses (stmt);
11479 177 : gimple_omp_for_set_clauses (stmt, new_clauses1);
11480 177 : *cp2 = gimple_omp_for_clauses (new_stmt);
11481 177 : gimple_omp_for_set_clauses (new_stmt, new_clauses2);
11482 :
11483 177 : if (is_for_simd)
11484 : {
11485 83 : gimple_seq_add_seq (gimple_omp_body_ptr (scan_stmt3), scan1_list);
11486 83 : gimple_seq_add_seq (gimple_omp_body_ptr (input_stmt4), input2_list);
11487 :
11488 83 : gsi_insert_seq_after (&input3_gsi, gimple_omp_body (input_stmt3),
11489 : GSI_SAME_STMT);
11490 83 : gsi_remove (&input3_gsi, true);
11491 83 : gsi_insert_seq_after (&scan3_gsi, gimple_omp_body (scan_stmt3),
11492 : GSI_SAME_STMT);
11493 83 : gsi_remove (&scan3_gsi, true);
11494 83 : gsi_insert_seq_after (&input4_gsi, gimple_omp_body (input_stmt4),
11495 : GSI_SAME_STMT);
11496 83 : gsi_remove (&input4_gsi, true);
11497 83 : gsi_insert_seq_after (&scan4_gsi, gimple_omp_body (scan_stmt4),
11498 : GSI_SAME_STMT);
11499 83 : gsi_remove (&scan4_gsi, true);
11500 : }
11501 : else
11502 : {
11503 94 : gimple_omp_set_body (scan_stmt1, scan1_list);
11504 94 : gimple_omp_set_body (input_stmt2, input2_list);
11505 : }
11506 :
11507 177 : gsi_insert_seq_after (&input1_gsi, gimple_omp_body (input_stmt1),
11508 : GSI_SAME_STMT);
11509 177 : gsi_remove (&input1_gsi, true);
11510 177 : gsi_insert_seq_after (&scan1_gsi, gimple_omp_body (scan_stmt1),
11511 : GSI_SAME_STMT);
11512 177 : gsi_remove (&scan1_gsi, true);
11513 177 : gsi_insert_seq_after (&input2_gsi, gimple_omp_body (input_stmt2),
11514 : GSI_SAME_STMT);
11515 177 : gsi_remove (&input2_gsi, true);
11516 177 : gsi_insert_seq_after (&scan2_gsi, gimple_omp_body (scan_stmt2),
11517 : GSI_SAME_STMT);
11518 177 : gsi_remove (&scan2_gsi, true);
11519 :
11520 177 : gimple_seq_add_seq (body_p, clist);
11521 :
11522 177 : tree lab1 = create_artificial_label (UNKNOWN_LOCATION);
11523 177 : tree lab2 = create_artificial_label (UNKNOWN_LOCATION);
11524 177 : tree lab3 = create_artificial_label (UNKNOWN_LOCATION);
11525 177 : g = gimple_build_cond (EQ_EXPR, thread_num, integer_zero_node, lab1, lab2);
11526 177 : gimple_seq_add_stmt (body_p, g);
11527 177 : g = gimple_build_label (lab1);
11528 177 : gimple_seq_add_stmt (body_p, g);
11529 177 : gimple_seq_add_seq (body_p, thr01_list);
11530 177 : g = gimple_build_goto (lab3);
11531 177 : gimple_seq_add_stmt (body_p, g);
11532 177 : g = gimple_build_label (lab2);
11533 177 : gimple_seq_add_stmt (body_p, g);
11534 177 : gimple_seq_add_seq (body_p, thrn1_list);
11535 177 : g = gimple_build_label (lab3);
11536 177 : gimple_seq_add_stmt (body_p, g);
11537 :
11538 177 : g = gimple_build_assign (ivar, size_zero_node);
11539 177 : gimple_seq_add_stmt (body_p, g);
11540 :
11541 177 : gimple_seq_add_stmt (body_p, stmt);
11542 177 : gimple_seq_add_seq (body_p, body);
11543 177 : gimple_seq_add_stmt (body_p, gimple_build_omp_continue (fd->loop.v,
11544 : fd->loop.v));
11545 :
11546 177 : g = gimple_build_omp_return (true);
11547 177 : gimple_seq_add_stmt (body_p, g);
11548 177 : gimple_seq_add_seq (body_p, mdlist);
11549 :
11550 177 : lab1 = create_artificial_label (UNKNOWN_LOCATION);
11551 177 : lab2 = create_artificial_label (UNKNOWN_LOCATION);
11552 177 : g = gimple_build_cond (GT_EXPR, num_threads, integer_one_node, lab1, lab2);
11553 177 : gimple_seq_add_stmt (body_p, g);
11554 177 : g = gimple_build_label (lab1);
11555 177 : gimple_seq_add_stmt (body_p, g);
11556 :
11557 177 : g = omp_build_barrier (NULL, GOMP_BARRIER_IMPLICIT_WORKSHARE);
11558 177 : gimple_seq_add_stmt (body_p, g);
11559 :
11560 177 : tree down = create_tmp_var (unsigned_type_node);
11561 177 : g = gimple_build_assign (down, build_zero_cst (unsigned_type_node));
11562 177 : gimple_seq_add_stmt (body_p, g);
11563 :
11564 177 : g = gimple_build_assign (k, build_one_cst (unsigned_type_node));
11565 177 : gimple_seq_add_stmt (body_p, g);
11566 :
11567 177 : tree num_threadsu = create_tmp_var (unsigned_type_node);
11568 177 : g = gimple_build_assign (num_threadsu, NOP_EXPR, num_threads);
11569 177 : gimple_seq_add_stmt (body_p, g);
11570 :
11571 177 : tree thread_numu = create_tmp_var (unsigned_type_node);
11572 177 : g = gimple_build_assign (thread_numu, NOP_EXPR, thread_num);
11573 177 : gimple_seq_add_stmt (body_p, g);
11574 :
11575 177 : tree thread_nump1 = create_tmp_var (unsigned_type_node);
11576 177 : g = gimple_build_assign (thread_nump1, PLUS_EXPR, thread_numu,
11577 : build_int_cst (unsigned_type_node, 1));
11578 177 : gimple_seq_add_stmt (body_p, g);
11579 :
11580 177 : lab3 = create_artificial_label (UNKNOWN_LOCATION);
11581 177 : g = gimple_build_label (lab3);
11582 177 : gimple_seq_add_stmt (body_p, g);
11583 :
11584 177 : tree twok = create_tmp_var (unsigned_type_node);
11585 177 : g = gimple_build_assign (twok, LSHIFT_EXPR, k, integer_one_node);
11586 177 : gimple_seq_add_stmt (body_p, g);
11587 :
11588 177 : tree lab4 = create_artificial_label (UNKNOWN_LOCATION);
11589 177 : tree lab5 = create_artificial_label (UNKNOWN_LOCATION);
11590 177 : tree lab6 = create_artificial_label (UNKNOWN_LOCATION);
11591 177 : g = gimple_build_cond (GT_EXPR, twok, num_threadsu, lab4, lab5);
11592 177 : gimple_seq_add_stmt (body_p, g);
11593 177 : g = gimple_build_label (lab4);
11594 177 : gimple_seq_add_stmt (body_p, g);
11595 177 : g = gimple_build_assign (down, build_all_ones_cst (unsigned_type_node));
11596 177 : gimple_seq_add_stmt (body_p, g);
11597 177 : g = gimple_build_assign (k, RSHIFT_EXPR, k, integer_one_node);
11598 177 : gimple_seq_add_stmt (body_p, g);
11599 :
11600 177 : g = gimple_build_cond (EQ_EXPR, k, num_threadsu, lab6, lab5);
11601 177 : gimple_seq_add_stmt (body_p, g);
11602 177 : g = gimple_build_label (lab6);
11603 177 : gimple_seq_add_stmt (body_p, g);
11604 :
11605 177 : g = gimple_build_assign (k, RSHIFT_EXPR, k, integer_one_node);
11606 177 : gimple_seq_add_stmt (body_p, g);
11607 :
11608 177 : g = gimple_build_label (lab5);
11609 177 : gimple_seq_add_stmt (body_p, g);
11610 :
11611 177 : g = gimple_build_assign (twok, LSHIFT_EXPR, k, integer_one_node);
11612 177 : gimple_seq_add_stmt (body_p, g);
11613 :
11614 177 : tree cplx = create_tmp_var (build_complex_type (unsigned_type_node, false));
11615 177 : g = gimple_build_call_internal (IFN_MUL_OVERFLOW, 2, thread_nump1, twok);
11616 177 : gimple_call_set_lhs (g, cplx);
11617 177 : gimple_seq_add_stmt (body_p, g);
11618 177 : tree mul = create_tmp_var (unsigned_type_node);
11619 177 : g = gimple_build_assign (mul, REALPART_EXPR,
11620 : build1 (REALPART_EXPR, unsigned_type_node, cplx));
11621 177 : gimple_seq_add_stmt (body_p, g);
11622 177 : tree ovf = create_tmp_var (unsigned_type_node);
11623 177 : g = gimple_build_assign (ovf, IMAGPART_EXPR,
11624 : build1 (IMAGPART_EXPR, unsigned_type_node, cplx));
11625 177 : gimple_seq_add_stmt (body_p, g);
11626 :
11627 177 : tree lab7 = create_artificial_label (UNKNOWN_LOCATION);
11628 177 : tree lab8 = create_artificial_label (UNKNOWN_LOCATION);
11629 177 : g = gimple_build_cond (EQ_EXPR, ovf, build_zero_cst (unsigned_type_node),
11630 : lab7, lab8);
11631 177 : gimple_seq_add_stmt (body_p, g);
11632 177 : g = gimple_build_label (lab7);
11633 177 : gimple_seq_add_stmt (body_p, g);
11634 :
11635 177 : tree andv = create_tmp_var (unsigned_type_node);
11636 177 : g = gimple_build_assign (andv, BIT_AND_EXPR, k, down);
11637 177 : gimple_seq_add_stmt (body_p, g);
11638 177 : tree andvm1 = create_tmp_var (unsigned_type_node);
11639 177 : g = gimple_build_assign (andvm1, PLUS_EXPR, andv,
11640 : build_minus_one_cst (unsigned_type_node));
11641 177 : gimple_seq_add_stmt (body_p, g);
11642 :
11643 177 : g = gimple_build_assign (l, PLUS_EXPR, mul, andvm1);
11644 177 : gimple_seq_add_stmt (body_p, g);
11645 :
11646 177 : tree lab9 = create_artificial_label (UNKNOWN_LOCATION);
11647 177 : g = gimple_build_cond (LT_EXPR, l, num_threadsu, lab9, lab8);
11648 177 : gimple_seq_add_stmt (body_p, g);
11649 177 : g = gimple_build_label (lab9);
11650 177 : gimple_seq_add_stmt (body_p, g);
11651 177 : gimple_seq_add_seq (body_p, reduc_list);
11652 177 : g = gimple_build_label (lab8);
11653 177 : gimple_seq_add_stmt (body_p, g);
11654 :
11655 177 : tree lab10 = create_artificial_label (UNKNOWN_LOCATION);
11656 177 : tree lab11 = create_artificial_label (UNKNOWN_LOCATION);
11657 177 : tree lab12 = create_artificial_label (UNKNOWN_LOCATION);
11658 177 : g = gimple_build_cond (EQ_EXPR, down, build_zero_cst (unsigned_type_node),
11659 : lab10, lab11);
11660 177 : gimple_seq_add_stmt (body_p, g);
11661 177 : g = gimple_build_label (lab10);
11662 177 : gimple_seq_add_stmt (body_p, g);
11663 177 : g = gimple_build_assign (k, LSHIFT_EXPR, k, integer_one_node);
11664 177 : gimple_seq_add_stmt (body_p, g);
11665 177 : g = gimple_build_goto (lab12);
11666 177 : gimple_seq_add_stmt (body_p, g);
11667 177 : g = gimple_build_label (lab11);
11668 177 : gimple_seq_add_stmt (body_p, g);
11669 177 : g = gimple_build_assign (k, RSHIFT_EXPR, k, integer_one_node);
11670 177 : gimple_seq_add_stmt (body_p, g);
11671 177 : g = gimple_build_label (lab12);
11672 177 : gimple_seq_add_stmt (body_p, g);
11673 :
11674 177 : g = omp_build_barrier (NULL, GOMP_BARRIER_IMPLICIT_WORKSHARE);
11675 177 : gimple_seq_add_stmt (body_p, g);
11676 :
11677 177 : g = gimple_build_cond (NE_EXPR, k, build_zero_cst (unsigned_type_node),
11678 : lab3, lab2);
11679 177 : gimple_seq_add_stmt (body_p, g);
11680 :
11681 177 : g = gimple_build_label (lab2);
11682 177 : gimple_seq_add_stmt (body_p, g);
11683 :
11684 177 : lab1 = create_artificial_label (UNKNOWN_LOCATION);
11685 177 : lab2 = create_artificial_label (UNKNOWN_LOCATION);
11686 177 : lab3 = create_artificial_label (UNKNOWN_LOCATION);
11687 177 : g = gimple_build_cond (EQ_EXPR, thread_num, integer_zero_node, lab1, lab2);
11688 177 : gimple_seq_add_stmt (body_p, g);
11689 177 : g = gimple_build_label (lab1);
11690 177 : gimple_seq_add_stmt (body_p, g);
11691 177 : gimple_seq_add_seq (body_p, thr02_list);
11692 177 : g = gimple_build_goto (lab3);
11693 177 : gimple_seq_add_stmt (body_p, g);
11694 177 : g = gimple_build_label (lab2);
11695 177 : gimple_seq_add_stmt (body_p, g);
11696 177 : gimple_seq_add_seq (body_p, thrn2_list);
11697 177 : g = gimple_build_label (lab3);
11698 177 : gimple_seq_add_stmt (body_p, g);
11699 :
11700 177 : g = gimple_build_assign (ivar, size_zero_node);
11701 177 : gimple_seq_add_stmt (body_p, g);
11702 177 : gimple_seq_add_stmt (body_p, new_stmt);
11703 177 : gimple_seq_add_seq (body_p, new_body);
11704 :
11705 177 : gimple_seq new_dlist = NULL;
11706 177 : lab1 = create_artificial_label (UNKNOWN_LOCATION);
11707 177 : lab2 = create_artificial_label (UNKNOWN_LOCATION);
11708 177 : tree num_threadsm1 = create_tmp_var (integer_type_node);
11709 177 : g = gimple_build_assign (num_threadsm1, PLUS_EXPR, num_threads,
11710 : integer_minus_one_node);
11711 177 : gimple_seq_add_stmt (&new_dlist, g);
11712 177 : g = gimple_build_cond (EQ_EXPR, thread_num, num_threadsm1, lab1, lab2);
11713 177 : gimple_seq_add_stmt (&new_dlist, g);
11714 177 : g = gimple_build_label (lab1);
11715 177 : gimple_seq_add_stmt (&new_dlist, g);
11716 177 : gimple_seq_add_seq (&new_dlist, last_list);
11717 177 : g = gimple_build_label (lab2);
11718 177 : gimple_seq_add_stmt (&new_dlist, g);
11719 177 : gimple_seq_add_seq (&new_dlist, *dlist);
11720 177 : *dlist = new_dlist;
11721 177 : }
11722 :
11723 : /* Build an internal UNIQUE function with type IFN_UNIQUE_OACC_PRIVATE listing
11724 : the addresses of variables to be made private at the surrounding
11725 : parallelism level. Such functions appear in the gimple code stream in two
11726 : forms, e.g. for a partitioned loop:
11727 :
11728 : .data_dep.6 = .UNIQUE (OACC_HEAD_MARK, .data_dep.6, 1, 68);
11729 : .data_dep.6 = .UNIQUE (OACC_PRIVATE, .data_dep.6, -1, &w);
11730 : .data_dep.6 = .UNIQUE (OACC_FORK, .data_dep.6, -1);
11731 : .data_dep.6 = .UNIQUE (OACC_HEAD_MARK, .data_dep.6);
11732 :
11733 : or alternatively, OACC_PRIVATE can appear at the top level of a parallel,
11734 : not as part of a HEAD_MARK sequence:
11735 :
11736 : .UNIQUE (OACC_PRIVATE, 0, 0, &w);
11737 :
11738 : For such stand-alone appearances, the 3rd argument is always 0, denoting
11739 : gang partitioning. */
11740 :
11741 : static gcall *
11742 19728 : lower_oacc_private_marker (omp_context *ctx)
11743 : {
11744 19728 : if (ctx->oacc_privatization_candidates.length () == 0)
11745 : return NULL;
11746 :
11747 308 : auto_vec<tree, 5> args;
11748 :
11749 308 : args.quick_push (build_int_cst (integer_type_node, IFN_UNIQUE_OACC_PRIVATE));
11750 308 : args.quick_push (integer_zero_node);
11751 308 : args.quick_push (integer_minus_one_node);
11752 :
11753 308 : int i;
11754 308 : tree decl;
11755 696 : FOR_EACH_VEC_ELT (ctx->oacc_privatization_candidates, i, decl)
11756 : {
11757 388 : gcc_checking_assert (TREE_ADDRESSABLE (decl));
11758 388 : tree addr = build_fold_addr_expr (decl);
11759 388 : args.safe_push (addr);
11760 : }
11761 :
11762 308 : return gimple_build_call_internal_vec (IFN_UNIQUE, args);
11763 308 : }
11764 :
11765 : /* Lower code for an OMP loop directive. */
11766 :
11767 : static void
11768 46859 : lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11769 : {
11770 46859 : tree *rhs_p, block;
11771 46859 : struct omp_for_data fd, *fdp = NULL;
11772 46859 : gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
11773 46859 : gbind *new_stmt;
11774 46859 : gimple_seq omp_for_body, body, dlist, tred_ilist = NULL, tred_dlist = NULL;
11775 46859 : gimple_seq cnt_list = NULL, clist = NULL;
11776 46859 : gimple_seq oacc_head = NULL, oacc_tail = NULL;
11777 46859 : size_t i;
11778 :
11779 46859 : push_gimplify_context ();
11780 :
11781 46859 : if (is_gimple_omp_oacc (ctx->stmt))
11782 11325 : oacc_privatization_scan_clause_chain (ctx, gimple_omp_for_clauses (stmt));
11783 :
11784 46859 : lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
11785 :
11786 46859 : block = make_node (BLOCK);
11787 46859 : new_stmt = gimple_build_bind (NULL, NULL, block);
11788 : /* Replace at gsi right away, so that 'stmt' is no member
11789 : of a sequence anymore as we're going to add to a different
11790 : one below. */
11791 46859 : gsi_replace (gsi_p, new_stmt, true);
11792 :
11793 : /* Move declaration of temporaries in the loop body before we make
11794 : it go away. */
11795 46859 : omp_for_body = gimple_omp_body (stmt);
11796 46859 : if (!gimple_seq_empty_p (omp_for_body)
11797 46859 : && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
11798 : {
11799 19551 : gbind *inner_bind
11800 19551 : = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
11801 19551 : tree vars = gimple_bind_vars (inner_bind);
11802 19551 : if (is_gimple_omp_oacc (ctx->stmt))
11803 5305 : oacc_privatization_scan_decl_chain (ctx, vars);
11804 19551 : gimple_bind_append_vars (new_stmt, vars);
11805 : /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
11806 : keep them on the inner_bind and it's block. */
11807 19551 : gimple_bind_set_vars (inner_bind, NULL_TREE);
11808 19551 : if (gimple_bind_block (inner_bind))
11809 16995 : BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
11810 : }
11811 :
11812 46859 : if (gimple_omp_for_combined_into_p (stmt))
11813 : {
11814 14598 : omp_extract_for_data (stmt, &fd, NULL);
11815 14598 : fdp = &fd;
11816 :
11817 : /* We need two temporaries with fd.loop.v type (istart/iend)
11818 : and then (fd.collapse - 1) temporaries with the same
11819 : type for count2 ... countN-1 vars if not constant. */
11820 14598 : size_t count = 2;
11821 14598 : tree type = fd.iter_type;
11822 14598 : if (fd.collapse > 1
11823 4867 : && TREE_CODE (fd.loop.n2) != INTEGER_CST)
11824 2692 : count += fd.collapse - 1;
11825 14598 : size_t count2 = 0;
11826 14598 : tree type2 = NULL_TREE;
11827 14598 : bool taskreg_for
11828 14598 : = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
11829 14598 : || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
11830 14598 : tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
11831 14598 : tree simtc = NULL;
11832 14598 : tree clauses = *pc;
11833 14598 : if (fd.collapse > 1
11834 4867 : && fd.non_rect
11835 137 : && fd.last_nonrect == fd.first_nonrect + 1
11836 89 : && TREE_CODE (fd.loop.n2) != INTEGER_CST)
11837 64 : if (tree v = gimple_omp_for_index (stmt, fd.last_nonrect))
11838 64 : if (!TYPE_UNSIGNED (TREE_TYPE (v)))
11839 : {
11840 60 : v = gimple_omp_for_index (stmt, fd.first_nonrect);
11841 60 : type2 = TREE_TYPE (v);
11842 60 : count++;
11843 60 : count2 = 3;
11844 : }
11845 14598 : if (taskreg_for)
11846 7594 : outerc
11847 7594 : = omp_find_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
11848 : OMP_CLAUSE__LOOPTEMP_);
11849 14598 : if (ctx->simt_stmt)
11850 0 : simtc = omp_find_clause (gimple_omp_for_clauses (ctx->simt_stmt),
11851 : OMP_CLAUSE__LOOPTEMP_);
11852 49203 : for (i = 0; i < count + count2; i++)
11853 : {
11854 34605 : tree temp;
11855 34605 : if (taskreg_for)
11856 : {
11857 18069 : gcc_assert (outerc);
11858 18069 : temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
11859 18069 : outerc = omp_find_clause (OMP_CLAUSE_CHAIN (outerc),
11860 : OMP_CLAUSE__LOOPTEMP_);
11861 : }
11862 : else
11863 : {
11864 : /* If there are 2 adjacent SIMD stmts, one with _simt_
11865 : clause, another without, make sure they have the same
11866 : decls in _looptemp_ clauses, because the outer stmt
11867 : they are combined into will look up just one inner_stmt. */
11868 16536 : if (ctx->simt_stmt)
11869 0 : temp = OMP_CLAUSE_DECL (simtc);
11870 : else
11871 32928 : temp = create_tmp_var (i >= count ? type2 : type);
11872 16536 : insert_decl_map (&ctx->outer->cb, temp, temp);
11873 : }
11874 34605 : *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
11875 34605 : OMP_CLAUSE_DECL (*pc) = temp;
11876 34605 : pc = &OMP_CLAUSE_CHAIN (*pc);
11877 34605 : if (ctx->simt_stmt)
11878 0 : simtc = omp_find_clause (OMP_CLAUSE_CHAIN (simtc),
11879 : OMP_CLAUSE__LOOPTEMP_);
11880 : }
11881 14598 : *pc = clauses;
11882 : }
11883 :
11884 : /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
11885 46859 : dlist = NULL;
11886 46859 : body = NULL;
11887 46859 : tree rclauses
11888 46859 : = omp_task_reductions_find_first (gimple_omp_for_clauses (stmt), OMP_FOR,
11889 : OMP_CLAUSE_REDUCTION);
11890 46859 : tree rtmp = NULL_TREE;
11891 46859 : if (rclauses)
11892 : {
11893 227 : tree type = build_pointer_type (pointer_sized_int_node);
11894 227 : tree temp = create_tmp_var (type);
11895 227 : tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__REDUCTEMP_);
11896 227 : OMP_CLAUSE_DECL (c) = temp;
11897 227 : OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (stmt);
11898 227 : gimple_omp_for_set_clauses (stmt, c);
11899 227 : lower_omp_task_reductions (ctx, OMP_FOR,
11900 : gimple_omp_for_clauses (stmt),
11901 : &tred_ilist, &tred_dlist);
11902 227 : rclauses = c;
11903 227 : rtmp = make_ssa_name (type);
11904 227 : gimple_seq_add_stmt (&body, gimple_build_assign (rtmp, temp));
11905 : }
11906 :
11907 46859 : lower_lastprivate_conditional_clauses (gimple_omp_for_clauses_ptr (stmt),
11908 : ctx);
11909 :
11910 46859 : lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
11911 : fdp);
11912 93491 : gimple_seq_add_seq (rclauses ? &tred_ilist : &body,
11913 : gimple_omp_for_pre_body (stmt));
11914 :
11915 46859 : lower_omp (gimple_omp_body_ptr (stmt), ctx);
11916 :
11917 46859 : gcall *private_marker = NULL;
11918 46859 : if (is_gimple_omp_oacc (ctx->stmt)
11919 46859 : && !gimple_seq_empty_p (omp_for_body))
11920 10333 : private_marker = lower_oacc_private_marker (ctx);
11921 :
11922 : /* Lower the header expressions. At this point, we can assume that
11923 : the header is of the form:
11924 :
11925 : #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
11926 :
11927 : We just need to make sure that VAL1, VAL2 and VAL3 are lowered
11928 : using the .omp_data_s mapping, if needed. */
11929 114984 : for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
11930 : {
11931 68125 : rhs_p = gimple_omp_for_initial_ptr (stmt, i);
11932 68125 : if (TREE_CODE (*rhs_p) == TREE_VEC)
11933 : {
11934 639 : if (!is_gimple_min_invariant (TREE_VEC_ELT (*rhs_p, 1)))
11935 149 : TREE_VEC_ELT (*rhs_p, 1)
11936 298 : = get_formal_tmp_var (TREE_VEC_ELT (*rhs_p, 1), &cnt_list);
11937 639 : if (!is_gimple_min_invariant (TREE_VEC_ELT (*rhs_p, 2)))
11938 161 : TREE_VEC_ELT (*rhs_p, 2)
11939 322 : = get_formal_tmp_var (TREE_VEC_ELT (*rhs_p, 2), &cnt_list);
11940 : }
11941 67486 : else if (!is_gimple_min_invariant (*rhs_p))
11942 11465 : *rhs_p = get_formal_tmp_var (*rhs_p, &cnt_list);
11943 56021 : else if (TREE_CODE (*rhs_p) == ADDR_EXPR)
11944 4713 : recompute_tree_invariant_for_addr_expr (*rhs_p);
11945 :
11946 68125 : rhs_p = gimple_omp_for_final_ptr (stmt, i);
11947 68125 : if (TREE_CODE (*rhs_p) == TREE_VEC)
11948 : {
11949 519 : if (!is_gimple_min_invariant (TREE_VEC_ELT (*rhs_p, 1)))
11950 142 : TREE_VEC_ELT (*rhs_p, 1)
11951 284 : = get_formal_tmp_var (TREE_VEC_ELT (*rhs_p, 1), &cnt_list);
11952 519 : if (!is_gimple_min_invariant (TREE_VEC_ELT (*rhs_p, 2)))
11953 157 : TREE_VEC_ELT (*rhs_p, 2)
11954 314 : = get_formal_tmp_var (TREE_VEC_ELT (*rhs_p, 2), &cnt_list);
11955 : }
11956 67606 : else if (!is_gimple_min_invariant (*rhs_p))
11957 16851 : *rhs_p = get_formal_tmp_var (*rhs_p, &cnt_list);
11958 50755 : else if (TREE_CODE (*rhs_p) == ADDR_EXPR)
11959 4630 : recompute_tree_invariant_for_addr_expr (*rhs_p);
11960 :
11961 68125 : rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
11962 68125 : if (!is_gimple_min_invariant (*rhs_p))
11963 6318 : *rhs_p = get_formal_tmp_var (*rhs_p, &cnt_list);
11964 : }
11965 46859 : if (rclauses)
11966 227 : gimple_seq_add_seq (&tred_ilist, cnt_list);
11967 : else
11968 46632 : gimple_seq_add_seq (&body, cnt_list);
11969 :
11970 : /* Once lowered, extract the bounds and clauses. */
11971 46859 : omp_extract_for_data (stmt, &fd, NULL);
11972 :
11973 46859 : if (is_gimple_omp_oacc (ctx->stmt)
11974 46859 : && !ctx_in_oacc_kernels_region (ctx))
11975 9665 : lower_oacc_head_tail (gimple_location (stmt),
11976 : gimple_omp_for_clauses (stmt), private_marker,
11977 : &oacc_head, &oacc_tail, ctx);
11978 :
11979 : /* Add OpenACC partitioning and reduction markers just before the loop. */
11980 46859 : if (oacc_head)
11981 9665 : gimple_seq_add_seq (&body, oacc_head);
11982 :
11983 46859 : lower_omp_for_lastprivate (&fd, &body, &dlist, &clist, ctx);
11984 :
11985 46859 : if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
11986 85430 : for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
11987 69910 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
11988 69910 : && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
11989 : {
11990 203 : OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
11991 203 : if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
11992 42 : OMP_CLAUSE_LINEAR_STEP (c)
11993 84 : = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
11994 : ctx);
11995 : }
11996 :
11997 46489 : if ((ctx->scan_inclusive || ctx->scan_exclusive)
11998 47127 : && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
11999 177 : lower_omp_for_scan (&body, &dlist, stmt, &fd, ctx);
12000 : else
12001 : {
12002 46682 : gimple_seq_add_stmt (&body, stmt);
12003 46682 : gimple_seq_add_seq (&body, gimple_omp_body (stmt));
12004 : }
12005 :
12006 46859 : gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
12007 : fd.loop.v));
12008 :
12009 : /* After the loop, add exit clauses. */
12010 46859 : lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, &clist, ctx);
12011 :
12012 46859 : if (clist)
12013 : {
12014 173 : tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_START);
12015 173 : gcall *g = gimple_build_call (fndecl, 0);
12016 173 : gimple_seq_add_stmt (&body, g);
12017 173 : gimple_seq_add_seq (&body, clist);
12018 173 : fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_END);
12019 173 : g = gimple_build_call (fndecl, 0);
12020 173 : gimple_seq_add_stmt (&body, g);
12021 : }
12022 :
12023 46859 : if (ctx->cancellable)
12024 36 : gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
12025 :
12026 46859 : gimple_seq_add_seq (&body, dlist);
12027 :
12028 46859 : if (rclauses)
12029 : {
12030 227 : gimple_seq_add_seq (&tred_ilist, body);
12031 227 : body = tred_ilist;
12032 : }
12033 :
12034 46859 : body = maybe_catch_exception (body);
12035 :
12036 : /* Region exit marker goes at the end of the loop body. */
12037 46859 : gimple *g = gimple_build_omp_return (fd.have_nowait);
12038 46859 : gimple_seq_add_stmt (&body, g);
12039 :
12040 46859 : gimple_seq_add_seq (&body, tred_dlist);
12041 :
12042 46859 : maybe_add_implicit_barrier_cancel (ctx, g, &body);
12043 :
12044 46859 : if (rclauses)
12045 227 : OMP_CLAUSE_DECL (rclauses) = rtmp;
12046 :
12047 : /* Add OpenACC joining and reduction markers just after the loop. */
12048 46859 : if (oacc_tail)
12049 9665 : gimple_seq_add_seq (&body, oacc_tail);
12050 :
12051 46859 : pop_gimplify_context (new_stmt);
12052 :
12053 46859 : gimple_bind_append_vars (new_stmt, ctx->block_vars);
12054 46859 : maybe_remove_omp_member_access_dummy_vars (new_stmt);
12055 46859 : BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
12056 46859 : if (BLOCK_VARS (block))
12057 46216 : TREE_USED (block) = 1;
12058 :
12059 46859 : gimple_bind_set_body (new_stmt, body);
12060 46859 : gimple_omp_set_body (stmt, NULL);
12061 46859 : gimple_omp_for_set_pre_body (stmt, NULL);
12062 46859 : }
12063 :
12064 : /* Callback for walk_stmts. Check if the current statement only contains
12065 : GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
12066 :
12067 : static tree
12068 213311 : check_combined_parallel (gimple_stmt_iterator *gsi_p,
12069 : bool *handled_ops_p,
12070 : struct walk_stmt_info *wi)
12071 : {
12072 213311 : int *info = (int *) wi->info;
12073 213311 : gimple *stmt = gsi_stmt (*gsi_p);
12074 :
12075 213311 : *handled_ops_p = true;
12076 213311 : switch (gimple_code (stmt))
12077 : {
12078 11592 : WALK_SUBSTMTS;
12079 :
12080 : case GIMPLE_DEBUG:
12081 : break;
12082 1826 : case GIMPLE_OMP_FOR:
12083 1826 : case GIMPLE_OMP_SECTIONS:
12084 1826 : *info = *info == 0 ? 1 : -1;
12085 1826 : break;
12086 199854 : default:
12087 199854 : *info = -1;
12088 199854 : break;
12089 : }
12090 213311 : return NULL;
12091 : }
12092 :
12093 : struct omp_taskcopy_context
12094 : {
12095 : /* This field must be at the beginning, as we do "inheritance": Some
12096 : callback functions for tree-inline.cc (e.g., omp_copy_decl)
12097 : receive a copy_body_data pointer that is up-casted to an
12098 : omp_context pointer. */
12099 : copy_body_data cb;
12100 : omp_context *ctx;
12101 : };
12102 :
12103 : static tree
12104 366 : task_copyfn_copy_decl (tree var, copy_body_data *cb)
12105 : {
12106 366 : struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
12107 :
12108 366 : if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
12109 158 : return create_tmp_var (TREE_TYPE (var));
12110 :
12111 : return var;
12112 : }
12113 :
12114 : static tree
12115 50 : task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
12116 : {
12117 50 : tree name, new_fields = NULL, type, f;
12118 :
12119 50 : type = lang_hooks.types.make_type (RECORD_TYPE);
12120 50 : name = DECL_NAME (TYPE_NAME (orig_type));
12121 50 : name = build_decl (gimple_location (tcctx->ctx->stmt),
12122 : TYPE_DECL, name, type);
12123 50 : TYPE_NAME (type) = name;
12124 :
12125 1140 : for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
12126 : {
12127 1090 : tree new_f = copy_node (f);
12128 1090 : DECL_CONTEXT (new_f) = type;
12129 1090 : TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
12130 1090 : TREE_CHAIN (new_f) = new_fields;
12131 1090 : walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
12132 1090 : walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
12133 1090 : walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
12134 : &tcctx->cb, NULL);
12135 1090 : new_fields = new_f;
12136 1090 : tcctx->cb.decl_map->put (f, new_f);
12137 : }
12138 50 : TYPE_FIELDS (type) = nreverse (new_fields);
12139 50 : layout_type (type);
12140 50 : return type;
12141 : }
12142 :
12143 : /* Create task copyfn. */
12144 :
12145 : static void
12146 480 : create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
12147 : {
12148 480 : struct function *child_cfun;
12149 480 : tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
12150 480 : tree record_type, srecord_type, bind, list;
12151 480 : bool record_needs_remap = false, srecord_needs_remap = false;
12152 480 : splay_tree_node n;
12153 480 : struct omp_taskcopy_context tcctx;
12154 480 : location_t loc = gimple_location (task_stmt);
12155 480 : size_t looptempno = 0;
12156 :
12157 480 : child_fn = gimple_omp_task_copy_fn (task_stmt);
12158 480 : task_cpyfns.safe_push (task_stmt);
12159 480 : child_cfun = DECL_STRUCT_FUNCTION (child_fn);
12160 480 : gcc_assert (child_cfun->cfg == NULL);
12161 480 : DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
12162 :
12163 : /* Reset DECL_CONTEXT on function arguments. */
12164 1440 : for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
12165 960 : DECL_CONTEXT (t) = child_fn;
12166 :
12167 : /* Populate the function. */
12168 480 : push_gimplify_context ();
12169 480 : push_cfun (child_cfun);
12170 :
12171 480 : bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
12172 480 : TREE_SIDE_EFFECTS (bind) = 1;
12173 480 : list = NULL;
12174 480 : DECL_SAVED_TREE (child_fn) = bind;
12175 480 : DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
12176 :
12177 : /* Remap src and dst argument types if needed. */
12178 480 : record_type = ctx->record_type;
12179 480 : srecord_type = ctx->srecord_type;
12180 3018 : for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
12181 2563 : if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
12182 : {
12183 : record_needs_remap = true;
12184 : break;
12185 : }
12186 2757 : for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
12187 2302 : if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
12188 : {
12189 : srecord_needs_remap = true;
12190 : break;
12191 : }
12192 :
12193 480 : if (record_needs_remap || srecord_needs_remap)
12194 : {
12195 25 : memset (&tcctx, '\0', sizeof (tcctx));
12196 25 : tcctx.cb.src_fn = ctx->cb.src_fn;
12197 25 : tcctx.cb.dst_fn = child_fn;
12198 25 : tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
12199 25 : gcc_checking_assert (tcctx.cb.src_node);
12200 25 : tcctx.cb.dst_node = tcctx.cb.src_node;
12201 25 : tcctx.cb.src_cfun = ctx->cb.src_cfun;
12202 25 : tcctx.cb.copy_decl = task_copyfn_copy_decl;
12203 25 : tcctx.cb.eh_lp_nr = 0;
12204 25 : tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
12205 25 : tcctx.cb.decl_map = new hash_map<tree, tree>;
12206 25 : tcctx.ctx = ctx;
12207 :
12208 25 : if (record_needs_remap)
12209 25 : record_type = task_copyfn_remap_type (&tcctx, record_type);
12210 25 : if (srecord_needs_remap)
12211 25 : srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
12212 : }
12213 : else
12214 455 : tcctx.cb.decl_map = NULL;
12215 :
12216 480 : arg = DECL_ARGUMENTS (child_fn);
12217 480 : TREE_TYPE (arg) = build_pointer_type (record_type);
12218 480 : sarg = DECL_CHAIN (arg);
12219 480 : TREE_TYPE (sarg) = build_pointer_type (srecord_type);
12220 :
12221 : /* First pass: initialize temporaries used in record_type and srecord_type
12222 : sizes and field offsets. */
12223 480 : if (tcctx.cb.decl_map)
12224 631 : for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
12225 606 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
12226 : {
12227 497 : tree *p;
12228 :
12229 497 : decl = OMP_CLAUSE_DECL (c);
12230 497 : p = tcctx.cb.decl_map->get (decl);
12231 497 : if (p == NULL)
12232 339 : continue;
12233 158 : n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
12234 158 : sf = (tree) n->value;
12235 158 : sf = *tcctx.cb.decl_map->get (sf);
12236 158 : src = build_simple_mem_ref_loc (loc, sarg);
12237 158 : src = omp_build_component_ref (src, sf);
12238 158 : t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
12239 158 : append_to_statement_list (t, &list);
12240 : }
12241 :
12242 : /* Second pass: copy shared var pointers and copy construct non-VLA
12243 : firstprivate vars. */
12244 5694 : for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
12245 5214 : switch (OMP_CLAUSE_CODE (c))
12246 : {
12247 559 : splay_tree_key key;
12248 559 : case OMP_CLAUSE_SHARED:
12249 559 : decl = OMP_CLAUSE_DECL (c);
12250 559 : key = (splay_tree_key) decl;
12251 559 : if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
12252 273 : key = (splay_tree_key) &DECL_UID (decl);
12253 559 : n = splay_tree_lookup (ctx->field_map, key);
12254 559 : if (n == NULL)
12255 : break;
12256 125 : f = (tree) n->value;
12257 125 : if (tcctx.cb.decl_map)
12258 12 : f = *tcctx.cb.decl_map->get (f);
12259 125 : n = splay_tree_lookup (ctx->sfield_map, key);
12260 125 : sf = (tree) n->value;
12261 125 : if (tcctx.cb.decl_map)
12262 12 : sf = *tcctx.cb.decl_map->get (sf);
12263 125 : src = build_simple_mem_ref_loc (loc, sarg);
12264 125 : src = omp_build_component_ref (src, sf);
12265 125 : dst = build_simple_mem_ref_loc (loc, arg);
12266 125 : dst = omp_build_component_ref (dst, f);
12267 125 : t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
12268 125 : append_to_statement_list (t, &list);
12269 125 : break;
12270 460 : case OMP_CLAUSE_REDUCTION:
12271 460 : case OMP_CLAUSE_IN_REDUCTION:
12272 460 : decl = OMP_CLAUSE_DECL (c);
12273 460 : if (TREE_CODE (decl) == MEM_REF)
12274 : {
12275 160 : decl = TREE_OPERAND (decl, 0);
12276 160 : if (TREE_CODE (decl) == POINTER_PLUS_EXPR)
12277 38 : decl = TREE_OPERAND (decl, 0);
12278 160 : if (TREE_CODE (decl) == INDIRECT_REF
12279 128 : || TREE_CODE (decl) == ADDR_EXPR)
12280 95 : decl = TREE_OPERAND (decl, 0);
12281 : }
12282 460 : key = (splay_tree_key) decl;
12283 460 : n = splay_tree_lookup (ctx->field_map, key);
12284 460 : if (n == NULL)
12285 : break;
12286 101 : f = (tree) n->value;
12287 101 : if (tcctx.cb.decl_map)
12288 20 : f = *tcctx.cb.decl_map->get (f);
12289 101 : n = splay_tree_lookup (ctx->sfield_map, key);
12290 101 : sf = (tree) n->value;
12291 101 : if (tcctx.cb.decl_map)
12292 20 : sf = *tcctx.cb.decl_map->get (sf);
12293 101 : src = build_simple_mem_ref_loc (loc, sarg);
12294 101 : src = omp_build_component_ref (src, sf);
12295 101 : if (decl != OMP_CLAUSE_DECL (c)
12296 95 : && TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
12297 173 : && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == POINTER_TYPE)
12298 32 : src = build_simple_mem_ref_loc (loc, src);
12299 101 : dst = build_simple_mem_ref_loc (loc, arg);
12300 101 : dst = omp_build_component_ref (dst, f);
12301 101 : t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
12302 101 : append_to_statement_list (t, &list);
12303 101 : break;
12304 754 : case OMP_CLAUSE__LOOPTEMP_:
12305 : /* Fields for first two _looptemp_ clauses are initialized by
12306 : GOMP_taskloop*, the rest are handled like firstprivate. */
12307 754 : if (looptempno < 2)
12308 : {
12309 748 : looptempno++;
12310 748 : break;
12311 : }
12312 : /* FALLTHRU */
12313 1695 : case OMP_CLAUSE__REDUCTEMP_:
12314 1695 : case OMP_CLAUSE_FIRSTPRIVATE:
12315 1695 : decl = OMP_CLAUSE_DECL (c);
12316 1695 : if (is_variable_sized (decl))
12317 : break;
12318 1681 : n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
12319 1681 : if (n == NULL)
12320 : break;
12321 1681 : f = (tree) n->value;
12322 1681 : if (tcctx.cb.decl_map)
12323 490 : f = *tcctx.cb.decl_map->get (f);
12324 1681 : n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
12325 1681 : if (n != NULL)
12326 : {
12327 1431 : sf = (tree) n->value;
12328 1431 : if (tcctx.cb.decl_map)
12329 490 : sf = *tcctx.cb.decl_map->get (sf);
12330 1431 : src = build_simple_mem_ref_loc (loc, sarg);
12331 1431 : src = omp_build_component_ref (src, sf);
12332 1431 : if (use_pointer_for_field (decl, NULL)
12333 1431 : || omp_privatize_by_reference (decl))
12334 293 : src = build_simple_mem_ref_loc (loc, src);
12335 : }
12336 : else
12337 : src = decl;
12338 1681 : dst = build_simple_mem_ref_loc (loc, arg);
12339 1681 : dst = omp_build_component_ref (dst, f);
12340 1681 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE)
12341 192 : t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
12342 : else
12343 : {
12344 1489 : if (ctx->allocate_map)
12345 48 : if (tree *allocatorp = ctx->allocate_map->get (decl))
12346 : {
12347 26 : tree allocator = *allocatorp;
12348 26 : HOST_WIDE_INT ialign = 0;
12349 26 : if (TREE_CODE (allocator) == TREE_LIST)
12350 : {
12351 4 : ialign = tree_to_uhwi (TREE_VALUE (allocator));
12352 4 : allocator = TREE_PURPOSE (allocator);
12353 : }
12354 26 : if (TREE_CODE (allocator) != INTEGER_CST)
12355 : {
12356 10 : n = splay_tree_lookup (ctx->sfield_map,
12357 : (splay_tree_key) allocator);
12358 10 : allocator = (tree) n->value;
12359 10 : if (tcctx.cb.decl_map)
12360 0 : allocator = *tcctx.cb.decl_map->get (allocator);
12361 10 : tree a = build_simple_mem_ref_loc (loc, sarg);
12362 10 : allocator = omp_build_component_ref (a, allocator);
12363 : }
12364 26 : allocator = fold_convert (pointer_sized_int_node, allocator);
12365 26 : tree a = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
12366 26 : tree align = build_int_cst (size_type_node,
12367 26 : MAX (ialign,
12368 : DECL_ALIGN_UNIT (decl)));
12369 26 : tree sz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (dst)));
12370 26 : tree ptr = build_call_expr_loc (loc, a, 3, align, sz,
12371 : allocator);
12372 26 : ptr = fold_convert (TREE_TYPE (dst), ptr);
12373 26 : t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, ptr);
12374 26 : append_to_statement_list (t, &list);
12375 26 : dst = build_simple_mem_ref_loc (loc, dst);
12376 : }
12377 1489 : t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
12378 : }
12379 1681 : append_to_statement_list (t, &list);
12380 1681 : break;
12381 465 : case OMP_CLAUSE_PRIVATE:
12382 465 : if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
12383 : break;
12384 12 : decl = OMP_CLAUSE_DECL (c);
12385 12 : n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
12386 12 : f = (tree) n->value;
12387 12 : if (tcctx.cb.decl_map)
12388 0 : f = *tcctx.cb.decl_map->get (f);
12389 12 : n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
12390 12 : if (n != NULL)
12391 : {
12392 12 : sf = (tree) n->value;
12393 12 : if (tcctx.cb.decl_map)
12394 0 : sf = *tcctx.cb.decl_map->get (sf);
12395 12 : src = build_simple_mem_ref_loc (loc, sarg);
12396 12 : src = omp_build_component_ref (src, sf);
12397 12 : if (use_pointer_for_field (decl, NULL))
12398 12 : src = build_simple_mem_ref_loc (loc, src);
12399 : }
12400 : else
12401 : src = decl;
12402 12 : dst = build_simple_mem_ref_loc (loc, arg);
12403 12 : dst = omp_build_component_ref (dst, f);
12404 12 : t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
12405 12 : append_to_statement_list (t, &list);
12406 12 : break;
12407 : default:
12408 : break;
12409 : }
12410 :
12411 : /* Last pass: handle VLA firstprivates. */
12412 480 : if (tcctx.cb.decl_map)
12413 631 : for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
12414 606 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
12415 : {
12416 497 : tree ind, ptr, df;
12417 :
12418 497 : decl = OMP_CLAUSE_DECL (c);
12419 497 : if (!is_variable_sized (decl))
12420 483 : continue;
12421 14 : n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
12422 14 : if (n == NULL)
12423 0 : continue;
12424 14 : f = (tree) n->value;
12425 14 : f = *tcctx.cb.decl_map->get (f);
12426 14 : gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
12427 14 : ind = DECL_VALUE_EXPR (decl);
12428 14 : gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
12429 14 : gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
12430 42 : n = splay_tree_lookup (ctx->sfield_map,
12431 14 : (splay_tree_key) TREE_OPERAND (ind, 0));
12432 14 : sf = (tree) n->value;
12433 14 : sf = *tcctx.cb.decl_map->get (sf);
12434 14 : src = build_simple_mem_ref_loc (loc, sarg);
12435 14 : src = omp_build_component_ref (src, sf);
12436 14 : src = build_simple_mem_ref_loc (loc, src);
12437 14 : dst = build_simple_mem_ref_loc (loc, arg);
12438 14 : dst = omp_build_component_ref (dst, f);
12439 14 : t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
12440 14 : append_to_statement_list (t, &list);
12441 42 : n = splay_tree_lookup (ctx->field_map,
12442 14 : (splay_tree_key) TREE_OPERAND (ind, 0));
12443 14 : df = (tree) n->value;
12444 14 : df = *tcctx.cb.decl_map->get (df);
12445 14 : ptr = build_simple_mem_ref_loc (loc, arg);
12446 14 : ptr = omp_build_component_ref (ptr, df);
12447 14 : t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
12448 : build_fold_addr_expr_loc (loc, dst));
12449 14 : append_to_statement_list (t, &list);
12450 : }
12451 :
12452 480 : t = build1 (RETURN_EXPR, void_type_node, NULL);
12453 480 : append_to_statement_list (t, &list);
12454 :
12455 480 : if (tcctx.cb.decl_map)
12456 25 : delete tcctx.cb.decl_map;
12457 480 : pop_gimplify_context (NULL);
12458 480 : BIND_EXPR_BODY (bind) = list;
12459 480 : pop_cfun ();
12460 480 : }
12461 :
12462 : static void
12463 1553 : lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
12464 : {
12465 1553 : tree c, clauses;
12466 1553 : gimple *g;
12467 1553 : size_t cnt[5] = { 0, 0, 0, 0, 0 }, idx = 2, i;
12468 :
12469 1553 : clauses = omp_find_clause (*pclauses, OMP_CLAUSE_DEPEND);
12470 1553 : gcc_assert (clauses);
12471 6314 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
12472 4886 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
12473 1713 : switch (OMP_CLAUSE_DEPEND_KIND (c))
12474 : {
12475 125 : case OMP_CLAUSE_DEPEND_LAST:
12476 : /* Lowering already done at gimplification. */
12477 125 : return;
12478 481 : case OMP_CLAUSE_DEPEND_IN:
12479 481 : cnt[2]++;
12480 481 : break;
12481 969 : case OMP_CLAUSE_DEPEND_OUT:
12482 969 : case OMP_CLAUSE_DEPEND_INOUT:
12483 969 : cnt[0]++;
12484 969 : break;
12485 30 : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
12486 30 : cnt[1]++;
12487 30 : break;
12488 76 : case OMP_CLAUSE_DEPEND_DEPOBJ:
12489 76 : cnt[3]++;
12490 76 : break;
12491 32 : case OMP_CLAUSE_DEPEND_INOUTSET:
12492 32 : cnt[4]++;
12493 32 : break;
12494 0 : default:
12495 0 : gcc_unreachable ();
12496 : }
12497 1428 : if (cnt[1] || cnt[3] || cnt[4])
12498 135 : idx = 5;
12499 1428 : size_t total = cnt[0] + cnt[1] + cnt[2] + cnt[3] + cnt[4];
12500 1428 : size_t inoutidx = total + idx;
12501 1428 : tree type = build_array_type_nelts (ptr_type_node, total + idx + 2 * cnt[4]);
12502 1428 : tree array = create_tmp_var (type);
12503 1428 : TREE_ADDRESSABLE (array) = 1;
12504 1428 : tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
12505 : NULL_TREE);
12506 1428 : if (idx == 5)
12507 : {
12508 135 : g = gimple_build_assign (r, build_int_cst (ptr_type_node, 0));
12509 135 : gimple_seq_add_stmt (iseq, g);
12510 135 : r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
12511 : NULL_TREE);
12512 : }
12513 1428 : g = gimple_build_assign (r, build_int_cst (ptr_type_node, total));
12514 1428 : gimple_seq_add_stmt (iseq, g);
12515 7140 : for (i = 0; i < (idx == 5 ? 3 : 1); i++)
12516 : {
12517 1698 : r = build4 (ARRAY_REF, ptr_type_node, array,
12518 1698 : size_int (i + 1 + (idx == 5)), NULL_TREE, NULL_TREE);
12519 1698 : g = gimple_build_assign (r, build_int_cst (ptr_type_node, cnt[i]));
12520 1698 : gimple_seq_add_stmt (iseq, g);
12521 : }
12522 8568 : for (i = 0; i < 5; i++)
12523 : {
12524 7140 : if (cnt[i] == 0)
12525 5656 : continue;
12526 6563 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
12527 5079 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
12528 3352 : continue;
12529 : else
12530 : {
12531 1727 : switch (OMP_CLAUSE_DEPEND_KIND (c))
12532 : {
12533 547 : case OMP_CLAUSE_DEPEND_IN:
12534 547 : if (i != 2)
12535 139 : continue;
12536 : break;
12537 1025 : case OMP_CLAUSE_DEPEND_OUT:
12538 1025 : case OMP_CLAUSE_DEPEND_INOUT:
12539 1025 : if (i != 0)
12540 56 : continue;
12541 : break;
12542 44 : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
12543 44 : if (i != 1)
12544 14 : continue;
12545 : break;
12546 79 : case OMP_CLAUSE_DEPEND_DEPOBJ:
12547 79 : if (i != 3)
12548 3 : continue;
12549 : break;
12550 32 : case OMP_CLAUSE_DEPEND_INOUTSET:
12551 32 : if (i != 4)
12552 0 : continue;
12553 : break;
12554 0 : default:
12555 0 : gcc_unreachable ();
12556 : }
12557 1588 : tree t = OMP_CLAUSE_DECL (c);
12558 1588 : if (i == 4)
12559 : {
12560 32 : t = build4 (ARRAY_REF, ptr_type_node, array,
12561 32 : size_int (inoutidx), NULL_TREE, NULL_TREE);
12562 32 : t = build_fold_addr_expr (t);
12563 32 : inoutidx += 2;
12564 : }
12565 1588 : t = fold_convert (ptr_type_node, t);
12566 1588 : gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
12567 1588 : r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
12568 : NULL_TREE, NULL_TREE);
12569 1588 : g = gimple_build_assign (r, t);
12570 1588 : gimple_seq_add_stmt (iseq, g);
12571 : }
12572 : }
12573 1428 : if (cnt[4])
12574 81 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
12575 49 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
12576 49 : && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_INOUTSET)
12577 : {
12578 32 : tree t = OMP_CLAUSE_DECL (c);
12579 32 : t = fold_convert (ptr_type_node, t);
12580 32 : gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
12581 32 : r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
12582 : NULL_TREE, NULL_TREE);
12583 32 : g = gimple_build_assign (r, t);
12584 32 : gimple_seq_add_stmt (iseq, g);
12585 32 : t = build_int_cst (ptr_type_node, GOMP_DEPEND_INOUTSET);
12586 32 : r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
12587 : NULL_TREE, NULL_TREE);
12588 32 : g = gimple_build_assign (r, t);
12589 32 : gimple_seq_add_stmt (iseq, g);
12590 : }
12591 :
12592 1428 : c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
12593 1428 : OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_LAST;
12594 1428 : OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
12595 1428 : OMP_CLAUSE_CHAIN (c) = *pclauses;
12596 1428 : *pclauses = c;
12597 1428 : tree clobber = build_clobber (type);
12598 1428 : g = gimple_build_assign (array, clobber);
12599 1428 : gimple_seq_add_stmt (oseq, g);
12600 : }
12601 :
12602 : /* Lower the OpenMP parallel or task directive in the current statement
12603 : in GSI_P. CTX holds context information for the directive. */
12604 :
12605 : static void
12606 22471 : lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
12607 : {
12608 22471 : tree clauses;
12609 22471 : tree child_fn, t;
12610 22471 : gimple *stmt = gsi_stmt (*gsi_p);
12611 22471 : gbind *par_bind, *bind, *dep_bind = NULL;
12612 22471 : gimple_seq par_body;
12613 22471 : location_t loc = gimple_location (stmt);
12614 :
12615 22471 : clauses = gimple_omp_taskreg_clauses (stmt);
12616 22471 : if (gimple_code (stmt) == GIMPLE_OMP_TASK
12617 22471 : && gimple_omp_task_taskwait_p (stmt))
12618 : {
12619 84 : par_bind = NULL;
12620 84 : par_body = NULL;
12621 : }
12622 : else
12623 : {
12624 22387 : par_bind
12625 22387 : = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
12626 22387 : par_body = gimple_bind_body (par_bind);
12627 : }
12628 22471 : child_fn = ctx->cb.dst_fn;
12629 22471 : if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
12630 22471 : && !gimple_omp_parallel_combined_p (stmt))
12631 : {
12632 4218 : struct walk_stmt_info wi;
12633 4218 : int ws_num = 0;
12634 :
12635 4218 : memset (&wi, 0, sizeof (wi));
12636 4218 : wi.info = &ws_num;
12637 4218 : wi.val_only = true;
12638 4218 : walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
12639 4218 : if (ws_num == 1)
12640 386 : gimple_omp_parallel_set_combined_p (stmt, true);
12641 : }
12642 22471 : gimple_seq dep_ilist = NULL;
12643 22471 : gimple_seq dep_olist = NULL;
12644 22471 : if (gimple_code (stmt) == GIMPLE_OMP_TASK
12645 22471 : && omp_find_clause (clauses, OMP_CLAUSE_DEPEND))
12646 : {
12647 1189 : push_gimplify_context ();
12648 1189 : dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
12649 1189 : lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
12650 : &dep_ilist, &dep_olist);
12651 : }
12652 :
12653 22471 : if (gimple_code (stmt) == GIMPLE_OMP_TASK
12654 22471 : && gimple_omp_task_taskwait_p (stmt))
12655 : {
12656 84 : if (dep_bind)
12657 : {
12658 84 : gsi_replace (gsi_p, dep_bind, true);
12659 84 : gimple_bind_add_seq (dep_bind, dep_ilist);
12660 84 : gimple_bind_add_stmt (dep_bind, stmt);
12661 84 : gimple_bind_add_seq (dep_bind, dep_olist);
12662 84 : pop_gimplify_context (dep_bind);
12663 : }
12664 84 : return;
12665 : }
12666 :
12667 22387 : if (ctx->srecord_type)
12668 480 : create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
12669 :
12670 22387 : gimple_seq tskred_ilist = NULL;
12671 22387 : gimple_seq tskred_olist = NULL;
12672 22387 : if ((is_task_ctx (ctx)
12673 3748 : && gimple_omp_task_taskloop_p (ctx->stmt)
12674 1330 : && omp_find_clause (gimple_omp_task_clauses (ctx->stmt),
12675 : OMP_CLAUSE_REDUCTION))
12676 25638 : || (is_parallel_ctx (ctx)
12677 16121 : && omp_find_clause (gimple_omp_parallel_clauses (stmt),
12678 : OMP_CLAUSE__REDUCTEMP_)))
12679 : {
12680 557 : if (dep_bind == NULL)
12681 : {
12682 557 : push_gimplify_context ();
12683 557 : dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
12684 : }
12685 617 : lower_omp_task_reductions (ctx, is_task_ctx (ctx) ? OMP_TASKLOOP
12686 : : OMP_PARALLEL,
12687 557 : gimple_omp_taskreg_clauses (ctx->stmt),
12688 : &tskred_ilist, &tskred_olist);
12689 : }
12690 :
12691 22387 : push_gimplify_context ();
12692 :
12693 22387 : gimple_seq par_olist = NULL;
12694 22387 : gimple_seq par_ilist = NULL;
12695 22387 : gimple_seq par_rlist = NULL;
12696 22387 : lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
12697 22383 : lower_omp (&par_body, ctx);
12698 22383 : if (gimple_code (stmt) != GIMPLE_OMP_TASK)
12699 18635 : lower_reduction_clauses (clauses, &par_rlist, NULL, ctx);
12700 :
12701 : /* Declare all the variables created by mapping and the variables
12702 : declared in the scope of the parallel body. */
12703 22383 : record_vars_into (ctx->block_vars, child_fn);
12704 22383 : maybe_remove_omp_member_access_dummy_vars (par_bind);
12705 22383 : record_vars_into (gimple_bind_vars (par_bind), child_fn);
12706 :
12707 22383 : if (ctx->record_type)
12708 : {
12709 17927 : ctx->sender_decl
12710 35374 : = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
12711 : : ctx->record_type, ".omp_data_o");
12712 17927 : DECL_NAMELESS (ctx->sender_decl) = 1;
12713 17927 : TREE_ADDRESSABLE (ctx->sender_decl) = 1;
12714 17927 : gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
12715 : }
12716 :
12717 22383 : gimple_seq olist = NULL;
12718 22383 : gimple_seq ilist = NULL;
12719 22383 : lower_send_clauses (clauses, &ilist, &olist, ctx);
12720 22383 : lower_send_shared_vars (&ilist, &olist, ctx);
12721 :
12722 22383 : if (ctx->record_type)
12723 : {
12724 17927 : tree clobber = build_clobber (TREE_TYPE (ctx->sender_decl));
12725 17927 : gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
12726 : clobber));
12727 : }
12728 :
12729 : /* Once all the expansions are done, sequence all the different
12730 : fragments inside gimple_omp_body. */
12731 :
12732 22383 : gimple_seq new_body = NULL;
12733 :
12734 22383 : if (ctx->record_type)
12735 : {
12736 17927 : t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
12737 : /* fixup_child_record_type might have changed receiver_decl's type. */
12738 17927 : t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
12739 17927 : gimple_seq_add_stmt (&new_body,
12740 17927 : gimple_build_assign (ctx->receiver_decl, t));
12741 : }
12742 :
12743 22383 : gimple_seq_add_seq (&new_body, par_ilist);
12744 22383 : gimple_seq_add_seq (&new_body, par_body);
12745 22383 : gimple_seq_add_seq (&new_body, par_rlist);
12746 22383 : if (ctx->cancellable)
12747 129 : gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
12748 22383 : gimple_seq_add_seq (&new_body, par_olist);
12749 22383 : new_body = maybe_catch_exception (new_body);
12750 22383 : if (gimple_code (stmt) == GIMPLE_OMP_TASK)
12751 3748 : gimple_seq_add_stmt (&new_body,
12752 3748 : gimple_build_omp_continue (integer_zero_node,
12753 : integer_zero_node));
12754 22383 : gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
12755 22383 : gimple_omp_set_body (stmt, new_body);
12756 :
12757 22383 : if (dep_bind && gimple_bind_block (par_bind) == NULL_TREE)
12758 497 : bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
12759 : else
12760 21886 : bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
12761 43104 : gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
12762 22383 : gimple_bind_add_seq (bind, ilist);
12763 22383 : gimple_bind_add_stmt (bind, stmt);
12764 22383 : gimple_bind_add_seq (bind, olist);
12765 :
12766 22383 : pop_gimplify_context (NULL);
12767 :
12768 22383 : if (dep_bind)
12769 : {
12770 1662 : gimple_bind_add_seq (dep_bind, dep_ilist);
12771 1662 : gimple_bind_add_seq (dep_bind, tskred_ilist);
12772 1662 : gimple_bind_add_stmt (dep_bind, bind);
12773 1662 : gimple_bind_add_seq (dep_bind, tskred_olist);
12774 1662 : gimple_bind_add_seq (dep_bind, dep_olist);
12775 1662 : pop_gimplify_context (dep_bind);
12776 : }
12777 : }
12778 :
12779 : /* Set EXPR as the hostaddr expression that should result from the clause C
12780 : in the target statement STMT. Returns the tree that should be
12781 : passed as the hostaddr (a pointer to the array containing the expanded
12782 : hostaddrs and sizes of the clause). */
12783 :
12784 : static tree
12785 37307 : lower_omp_map_iterator_expr (tree expr, tree c, gomp_target *stmt)
12786 : {
12787 37307 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
12788 : return expr;
12789 :
12790 215 : tree iterator = OMP_CLAUSE_ITERATORS (c);
12791 215 : tree index = OMP_ITERATOR_INDEX (iterator);
12792 215 : tree elems = OMP_ITERATOR_ELEMS (iterator);
12793 215 : gimple_seq *loop_body_p = enter_omp_iterator_loop_context (c, stmt);
12794 :
12795 : /* IN LOOP BODY: */
12796 : /* elems[idx] = <expr>; */
12797 215 : tree lhs = build4 (ARRAY_REF, ptr_type_node, elems, index,
12798 : NULL_TREE, NULL_TREE);
12799 215 : tree mod_expr = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
12800 : void_type_node, lhs, expr);
12801 215 : gimplify_and_add (mod_expr, loop_body_p);
12802 215 : exit_omp_iterator_loop_context (c);
12803 :
12804 215 : return build_fold_addr_expr_with_type (elems, ptr_type_node);
12805 : }
12806 :
12807 : /* Set SIZE as the size expression that should result from the clause C
12808 : in the target statement STMT. Returns the tree that should be
12809 : passed as the clause size (a size_int with the value SIZE_MAX, indicating
12810 : that the clause uses an iterator). */
12811 :
12812 : static tree
12813 80132 : lower_omp_map_iterator_size (tree size, tree c, gomp_target *stmt)
12814 : {
12815 80132 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
12816 : return size;
12817 :
12818 219 : tree iterator = OMP_CLAUSE_ITERATORS (c);
12819 219 : tree index = OMP_ITERATOR_INDEX (iterator);
12820 219 : tree elems = OMP_ITERATOR_ELEMS (iterator);
12821 219 : gimple_seq *loop_body_p = enter_omp_iterator_loop_context (c, stmt);
12822 :
12823 : /* IN LOOP BODY: */
12824 : /* elems[idx+1] = <size>; */
12825 219 : tree lhs = build4 (ARRAY_REF, ptr_type_node, elems,
12826 : size_binop (PLUS_EXPR, index, size_int (1)),
12827 : NULL_TREE, NULL_TREE);
12828 219 : tree mod_expr = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
12829 : void_type_node, lhs, size);
12830 219 : gimplify_and_add (mod_expr, loop_body_p);
12831 219 : exit_omp_iterator_loop_context (c);
12832 :
12833 219 : return size_int (SIZE_MAX);
12834 : }
12835 :
12836 : /* Lower the GIMPLE_OMP_TARGET in the current statement
12837 : in GSI_P. CTX holds context information for the directive. */
12838 :
12839 : static void
12840 37147 : lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
12841 : {
12842 37147 : tree clauses;
12843 37147 : tree child_fn, t, c;
12844 37147 : gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
12845 37147 : gbind *tgt_bind, *bind, *dep_bind = NULL;
12846 37147 : gimple_seq tgt_body, olist, ilist, fplist, new_body;
12847 37147 : location_t loc = gimple_location (stmt);
12848 37147 : bool offloaded, data_region;
12849 37147 : unsigned int map_cnt = 0;
12850 37147 : tree in_reduction_clauses = NULL_TREE;
12851 :
12852 37147 : tree deep_map_cnt = NULL_TREE;
12853 37147 : tree deep_map_data = NULL_TREE;
12854 37147 : tree deep_map_offset_data = NULL_TREE;
12855 37147 : tree deep_map_offset = NULL_TREE;
12856 :
12857 37147 : offloaded = is_gimple_omp_offloaded (stmt);
12858 37147 : switch (gimple_omp_target_kind (stmt))
12859 : {
12860 11792 : case GF_OMP_TARGET_KIND_REGION:
12861 11792 : tree *p, *q;
12862 11792 : q = &in_reduction_clauses;
12863 79316 : for (p = gimple_omp_target_clauses_ptr (stmt); *p; )
12864 67524 : if (OMP_CLAUSE_CODE (*p) == OMP_CLAUSE_IN_REDUCTION)
12865 : {
12866 422 : *q = *p;
12867 422 : q = &OMP_CLAUSE_CHAIN (*q);
12868 422 : *p = OMP_CLAUSE_CHAIN (*p);
12869 : }
12870 : else
12871 67102 : p = &OMP_CLAUSE_CHAIN (*p);
12872 11792 : *q = NULL_TREE;
12873 11792 : *p = in_reduction_clauses;
12874 : /* FALLTHRU */
12875 : case GF_OMP_TARGET_KIND_UPDATE:
12876 : case GF_OMP_TARGET_KIND_ENTER_DATA:
12877 : case GF_OMP_TARGET_KIND_EXIT_DATA:
12878 : case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12879 : case GF_OMP_TARGET_KIND_OACC_KERNELS:
12880 : case GF_OMP_TARGET_KIND_OACC_SERIAL:
12881 : case GF_OMP_TARGET_KIND_OACC_UPDATE:
12882 : case GF_OMP_TARGET_KIND_OACC_ENTER_DATA:
12883 : case GF_OMP_TARGET_KIND_OACC_EXIT_DATA:
12884 : case GF_OMP_TARGET_KIND_OACC_DECLARE:
12885 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
12886 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
12887 : data_region = false;
12888 : break;
12889 : case GF_OMP_TARGET_KIND_DATA:
12890 : case GF_OMP_TARGET_KIND_OACC_DATA:
12891 : case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
12892 : case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
12893 : data_region = true;
12894 : break;
12895 0 : default:
12896 0 : gcc_unreachable ();
12897 : }
12898 :
12899 : /* Ensure that requires map is written via output_offload_tables, even if only
12900 : 'target (enter/exit) data' is used in the translation unit. */
12901 37147 : if (ENABLE_OFFLOADING && (omp_requires_mask & OMP_REQUIRES_TARGET_USED))
12902 : g->have_offload = true;
12903 :
12904 37147 : clauses = gimple_omp_target_clauses (stmt);
12905 :
12906 37147 : gimple_seq dep_ilist = NULL;
12907 37147 : gimple_seq dep_olist = NULL;
12908 37147 : bool has_depend = omp_find_clause (clauses, OMP_CLAUSE_DEPEND) != NULL_TREE;
12909 37147 : if (has_depend || in_reduction_clauses)
12910 : {
12911 392 : push_gimplify_context ();
12912 392 : dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
12913 392 : if (has_depend)
12914 329 : lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
12915 : &dep_ilist, &dep_olist);
12916 392 : if (in_reduction_clauses)
12917 314 : lower_rec_input_clauses (in_reduction_clauses, &dep_ilist, &dep_olist,
12918 : ctx, NULL);
12919 : }
12920 :
12921 37147 : tgt_bind = NULL;
12922 37147 : tgt_body = NULL;
12923 37147 : if (offloaded)
12924 : {
12925 21187 : tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
12926 21187 : tgt_body = gimple_bind_body (tgt_bind);
12927 : }
12928 15960 : else if (data_region)
12929 4021 : tgt_body = gimple_omp_body (stmt);
12930 37147 : child_fn = ctx->cb.dst_fn;
12931 :
12932 37147 : push_gimplify_context ();
12933 37147 : fplist = NULL;
12934 :
12935 37147 : ilist = NULL;
12936 37147 : olist = NULL;
12937 :
12938 37147 : gimple_seq alloc_dlist = NULL;
12939 37147 : hash_map<tree, tree> alloc_map;
12940 74294 : hash_map<tree, gimple_seq> alloc_seq_map;
12941 :
12942 176349 : for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
12943 139202 : switch (OMP_CLAUSE_CODE (c))
12944 : {
12945 : tree var, x, new_var, allocator, allocate_ptr, size;
12946 : gimple_seq alloc_seq;
12947 : bool by_ref;
12948 :
12949 : default:
12950 92788 : break;
12951 77857 : case OMP_CLAUSE_MAP:
12952 : #if CHECKING_P
12953 : /* First check what we're prepared to handle in the following. */
12954 77857 : switch (OMP_CLAUSE_MAP_KIND (c))
12955 : {
12956 : case GOMP_MAP_ALLOC:
12957 : case GOMP_MAP_TO:
12958 : case GOMP_MAP_FROM:
12959 : case GOMP_MAP_TOFROM:
12960 : case GOMP_MAP_POINTER:
12961 : case GOMP_MAP_TO_PSET:
12962 : case GOMP_MAP_DELETE:
12963 : case GOMP_MAP_RELEASE:
12964 : case GOMP_MAP_ALWAYS_TO:
12965 : case GOMP_MAP_ALWAYS_FROM:
12966 : case GOMP_MAP_ALWAYS_TOFROM:
12967 : case GOMP_MAP_FORCE_PRESENT:
12968 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
12969 : case GOMP_MAP_ALWAYS_PRESENT_TO:
12970 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
12971 :
12972 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
12973 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
12974 : case GOMP_MAP_STRUCT:
12975 : case GOMP_MAP_STRUCT_UNORD:
12976 : case GOMP_MAP_ALWAYS_POINTER:
12977 : case GOMP_MAP_ATTACH:
12978 : case GOMP_MAP_DETACH:
12979 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
12980 : case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
12981 : break;
12982 2587 : case GOMP_MAP_IF_PRESENT:
12983 2587 : case GOMP_MAP_FORCE_ALLOC:
12984 2587 : case GOMP_MAP_FORCE_TO:
12985 2587 : case GOMP_MAP_FORCE_FROM:
12986 2587 : case GOMP_MAP_FORCE_TOFROM:
12987 2587 : case GOMP_MAP_FORCE_DEVICEPTR:
12988 2587 : case GOMP_MAP_DEVICE_RESIDENT:
12989 2587 : case GOMP_MAP_LINK:
12990 2587 : case GOMP_MAP_FORCE_DETACH:
12991 2587 : gcc_assert (is_gimple_omp_oacc (stmt));
12992 : break;
12993 0 : default:
12994 0 : gcc_unreachable ();
12995 : }
12996 : #endif
12997 : /* FALLTHRU */
12998 89427 : case OMP_CLAUSE_TO:
12999 89427 : case OMP_CLAUSE_FROM:
13000 89427 : oacc_firstprivate:
13001 89427 : var = OMP_CLAUSE_DECL (c);
13002 89427 : {
13003 89427 : tree extra = lang_hooks.decls.omp_deep_mapping_cnt (stmt, c, &ilist);
13004 89427 : if (extra != NULL_TREE && deep_map_cnt != NULL_TREE)
13005 59 : deep_map_cnt = fold_build2_loc (OMP_CLAUSE_LOCATION (c), PLUS_EXPR,
13006 : size_type_node, deep_map_cnt,
13007 : extra);
13008 89368 : else if (extra != NULL_TREE)
13009 : deep_map_cnt = extra;
13010 : }
13011 :
13012 89283 : if (deep_map_cnt
13013 89649 : && OMP_CLAUSE_HAS_ITERATORS (c))
13014 0 : sorry ("iterators used together with deep mapping are not "
13015 : "supported yet");
13016 :
13017 89427 : if (!DECL_P (var))
13018 : {
13019 36882 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
13020 36882 : || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
13021 35276 : && (OMP_CLAUSE_MAP_KIND (c)
13022 : != GOMP_MAP_FIRSTPRIVATE_POINTER)))
13023 36882 : map_cnt++;
13024 46414 : continue;
13025 : }
13026 :
13027 52545 : if (DECL_SIZE (var)
13028 52545 : && !poly_int_tree_p (DECL_SIZE (var)))
13029 : {
13030 717 : tree var2 = DECL_VALUE_EXPR (var);
13031 717 : gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
13032 717 : var2 = TREE_OPERAND (var2, 0);
13033 717 : gcc_assert (DECL_P (var2));
13034 : var = var2;
13035 : }
13036 :
13037 52545 : if (offloaded
13038 36679 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13039 85328 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
13040 29548 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
13041 : {
13042 3664 : if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
13043 : {
13044 415 : if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
13045 415 : && varpool_node::get_create (var)->offloadable)
13046 2 : continue;
13047 :
13048 413 : tree type = build_pointer_type (TREE_TYPE (var));
13049 413 : tree new_var = lookup_decl (var, ctx);
13050 413 : x = create_tmp_var_raw (type, get_name (new_var));
13051 413 : gimple_add_tmp_var (x);
13052 413 : x = build_simple_mem_ref (x);
13053 413 : SET_DECL_VALUE_EXPR (new_var, x);
13054 413 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
13055 : }
13056 3662 : continue;
13057 3662 : }
13058 :
13059 48881 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13060 38917 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
13061 38710 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
13062 49142 : && is_omp_target (stmt))
13063 : {
13064 237 : gcc_assert (maybe_lookup_field (c, ctx));
13065 237 : map_cnt++;
13066 237 : continue;
13067 : }
13068 :
13069 48644 : if (!maybe_lookup_field (c, ctx))
13070 5631 : continue;
13071 :
13072 : /* Don't remap compute constructs' reduction variables, because the
13073 : intermediate result must be local to each gang. */
13074 70854 : if (offloaded && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13075 23945 : && is_gimple_omp_oacc (ctx->stmt)
13076 13572 : && OMP_CLAUSE_MAP_IN_REDUCTION (c)))
13077 : {
13078 27061 : x = build_receiver_ref (c, true, ctx);
13079 27061 : tree new_var = lookup_decl (var, ctx);
13080 :
13081 27061 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13082 23165 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
13083 3014 : && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
13084 30075 : && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
13085 425 : x = build_simple_mem_ref (x);
13086 27061 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
13087 : {
13088 3896 : gcc_assert (is_gimple_omp_oacc (ctx->stmt));
13089 3896 : if (omp_privatize_by_reference (new_var)
13090 3896 : && (TREE_CODE (TREE_TYPE (new_var)) != POINTER_TYPE
13091 44 : || DECL_BY_REFERENCE (var)))
13092 : {
13093 : /* Create a local object to hold the instance
13094 : value. */
13095 455 : tree type = TREE_TYPE (TREE_TYPE (new_var));
13096 455 : const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
13097 455 : tree inst = create_tmp_var (type, id);
13098 455 : gimplify_assign (inst, fold_indirect_ref (x), &fplist);
13099 455 : x = build_fold_addr_expr (inst);
13100 : }
13101 3896 : gimplify_assign (new_var, x, &fplist);
13102 : }
13103 23165 : else if (DECL_P (new_var))
13104 : {
13105 23165 : SET_DECL_VALUE_EXPR (new_var, x);
13106 23165 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
13107 : }
13108 : else
13109 0 : gcc_unreachable ();
13110 : }
13111 43013 : map_cnt++;
13112 43013 : break;
13113 :
13114 15294 : case OMP_CLAUSE_FIRSTPRIVATE:
13115 15294 : omp_firstprivate_recv:
13116 15294 : gcc_checking_assert (offloaded);
13117 15294 : if (is_gimple_omp_oacc (ctx->stmt))
13118 : {
13119 : /* No 'firstprivate' clauses on OpenACC 'kernels'. */
13120 3896 : gcc_checking_assert (!is_oacc_kernels (ctx));
13121 : /* Likewise, on OpenACC 'kernels' decomposed parts. */
13122 3896 : gcc_checking_assert (!is_oacc_kernels_decomposed_part (ctx));
13123 :
13124 3896 : goto oacc_firstprivate;
13125 : }
13126 11398 : map_cnt++;
13127 11398 : var = OMP_CLAUSE_DECL (c);
13128 11398 : new_var = lookup_decl (var, ctx);
13129 11398 : allocator = NULL_TREE;
13130 11398 : allocate_ptr = NULL_TREE;
13131 11398 : size = TREE_TYPE (var);
13132 11398 : by_ref = omp_privatize_by_reference (var);
13133 11398 : if (by_ref)
13134 822 : size = TREE_TYPE (size);
13135 11398 : size = TYPE_SIZE_UNIT (size);
13136 11398 : if (is_variable_sized (var, by_ref))
13137 35 : size = lookup_decl (size, ctx);
13138 11398 : alloc_seq = NULL;
13139 11398 : if (lower_private_allocate (var, new_var, allocator, allocate_ptr,
13140 : &alloc_seq, ctx, by_ref, size))
13141 : {
13142 63 : alloc_map.put (new_var, allocate_ptr);
13143 63 : alloc_seq_map.put (new_var, alloc_seq);
13144 : }
13145 11398 : if (!by_ref && !is_gimple_reg_type (TREE_TYPE (var)))
13146 : {
13147 143 : if (is_variable_sized (var))
13148 : {
13149 6 : tree pvar = DECL_VALUE_EXPR (var);
13150 6 : gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
13151 6 : pvar = TREE_OPERAND (pvar, 0);
13152 6 : gcc_assert (DECL_P (pvar));
13153 6 : tree new_pvar = lookup_decl (pvar, ctx);
13154 6 : x = build_fold_indirect_ref (new_pvar);
13155 6 : TREE_THIS_NOTRAP (x) = 1;
13156 : }
13157 137 : else if (allocate_ptr)
13158 19 : x = build_fold_indirect_ref (allocate_ptr);
13159 : else
13160 118 : x = build_receiver_ref (var, true, ctx);
13161 143 : SET_DECL_VALUE_EXPR (new_var, x);
13162 143 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
13163 : }
13164 : /* Fortran array descriptors: firstprivate of data + attach. */
13165 11398 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR
13166 11379 : && lang_hooks.decls.omp_array_data (var, true)
13167 11429 : && lang_hooks.decls.omp_array_data_privatize (var))
13168 23 : map_cnt += 2;
13169 :
13170 11544 : do_dtor:
13171 11544 : if (allocator)
13172 : {
13173 118 : if (!is_gimple_val (allocator))
13174 : {
13175 0 : tree avar = create_tmp_var (TREE_TYPE (allocator));
13176 0 : gimplify_assign (avar, allocator, &alloc_dlist);
13177 0 : allocator = avar;
13178 : }
13179 118 : if (!is_gimple_val (allocate_ptr))
13180 : {
13181 0 : tree apvar = create_tmp_var (TREE_TYPE (allocate_ptr));
13182 0 : gimplify_assign (apvar, allocate_ptr, &alloc_dlist);
13183 0 : allocate_ptr = apvar;
13184 : }
13185 118 : tree f = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
13186 118 : gimple *g = gimple_build_call (f, 2, allocate_ptr, allocator);
13187 118 : gimple_seq_add_stmt (&alloc_dlist, g);
13188 : }
13189 : break;
13190 :
13191 226 : case OMP_CLAUSE_PRIVATE:
13192 226 : gcc_checking_assert (offloaded);
13193 226 : if (is_gimple_omp_oacc (ctx->stmt))
13194 : {
13195 : /* No 'private' clauses on OpenACC 'kernels'. */
13196 80 : gcc_checking_assert (!is_oacc_kernels (ctx));
13197 : /* Likewise, on OpenACC 'kernels' decomposed parts. */
13198 80 : gcc_checking_assert (!is_oacc_kernels_decomposed_part (ctx));
13199 :
13200 : break;
13201 : }
13202 146 : var = OMP_CLAUSE_DECL (c);
13203 146 : new_var = lookup_decl (var, ctx);
13204 146 : allocator = NULL_TREE;
13205 146 : allocate_ptr = NULL_TREE;
13206 146 : alloc_seq = NULL;
13207 146 : size = TREE_TYPE (var);
13208 146 : by_ref = omp_privatize_by_reference (var);
13209 146 : if (by_ref)
13210 22 : size = TREE_TYPE (size);
13211 146 : size = TYPE_SIZE_UNIT (size);
13212 146 : if (is_variable_sized (var, by_ref))
13213 21 : size = lookup_decl (size, ctx);
13214 146 : lower_private_allocate (var, new_var, allocator, allocate_ptr,
13215 : &alloc_seq, ctx, by_ref, size);
13216 146 : if (allocate_ptr)
13217 : {
13218 55 : alloc_map.put (new_var, allocate_ptr);
13219 55 : alloc_seq_map.put (new_var, alloc_seq);
13220 : }
13221 146 : if (!allocate_ptr && is_variable_sized (var))
13222 : {
13223 1 : tree new_var = lookup_decl (var, ctx);
13224 1 : tree pvar = DECL_VALUE_EXPR (var);
13225 1 : gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
13226 1 : pvar = TREE_OPERAND (pvar, 0);
13227 1 : gcc_assert (DECL_P (pvar));
13228 1 : tree new_pvar = lookup_decl (pvar, ctx);
13229 1 : x = build_fold_indirect_ref (new_pvar);
13230 1 : TREE_THIS_NOTRAP (x) = 1;
13231 1 : SET_DECL_VALUE_EXPR (new_var, x);
13232 1 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
13233 : }
13234 146 : goto do_dtor;
13235 :
13236 2430 : case OMP_CLAUSE_USE_DEVICE_PTR:
13237 2430 : case OMP_CLAUSE_USE_DEVICE_ADDR:
13238 2430 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
13239 2430 : case OMP_CLAUSE_IS_DEVICE_PTR:
13240 2430 : var = OMP_CLAUSE_DECL (c);
13241 2430 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
13242 : {
13243 252 : while (TREE_CODE (var) == INDIRECT_REF
13244 252 : || TREE_CODE (var) == ARRAY_REF)
13245 17 : var = TREE_OPERAND (var, 0);
13246 235 : if (lang_hooks.decls.omp_array_data (var, true))
13247 19 : goto omp_firstprivate_recv;
13248 : }
13249 2411 : map_cnt++;
13250 2411 : if (is_variable_sized (var))
13251 : {
13252 12 : tree new_var = lookup_decl (var, ctx);
13253 12 : tree pvar = DECL_VALUE_EXPR (var);
13254 12 : gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
13255 12 : pvar = TREE_OPERAND (pvar, 0);
13256 12 : gcc_assert (DECL_P (pvar));
13257 12 : tree new_pvar = lookup_decl (pvar, ctx);
13258 12 : x = build_fold_indirect_ref (new_pvar);
13259 12 : TREE_THIS_NOTRAP (x) = 1;
13260 12 : SET_DECL_VALUE_EXPR (new_var, x);
13261 12 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
13262 : }
13263 2399 : else if (((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_ADDR
13264 542 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
13265 2071 : && !omp_privatize_by_reference (var)
13266 703 : && !omp_is_allocatable_or_ptr (var)
13267 564 : && !lang_hooks.decls.omp_array_data (var, true))
13268 4433 : || TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
13269 : {
13270 389 : tree new_var = lookup_decl (var, ctx);
13271 389 : tree type = build_pointer_type (TREE_TYPE (var));
13272 389 : x = create_tmp_var_raw (type, get_name (new_var));
13273 389 : gimple_add_tmp_var (x);
13274 389 : x = build_simple_mem_ref (x);
13275 389 : SET_DECL_VALUE_EXPR (new_var, x);
13276 389 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
13277 : }
13278 : else
13279 : {
13280 2010 : tree new_var = lookup_decl (var, ctx);
13281 2010 : x = create_tmp_var_raw (TREE_TYPE (new_var), get_name (new_var));
13282 2010 : gimple_add_tmp_var (x);
13283 2010 : SET_DECL_VALUE_EXPR (new_var, x);
13284 2010 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
13285 : }
13286 : break;
13287 10 : case OMP_CLAUSE_DEVICE_TYPE:
13288 : /* FIXME: Ensure that 'nohost' also has not implied before that
13289 : 'g->have_offload = true' or an implicit declare target. */
13290 10 : if (OMP_CLAUSE_DEVICE_TYPE_KIND (c) != OMP_CLAUSE_DEVICE_TYPE_ANY)
13291 5 : sorry_at (OMP_CLAUSE_LOCATION (c),
13292 : "only the %<device_type(any)%> is supported");
13293 : break;
13294 68 : case OMP_CLAUSE_USES_ALLOCATORS:
13295 68 : allocator = OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR (c);
13296 68 : tree new_allocator = lookup_decl (allocator, ctx);
13297 68 : x = build_receiver_ref (allocator, false, ctx);
13298 68 : SET_DECL_VALUE_EXPR (new_allocator, x);
13299 68 : DECL_HAS_VALUE_EXPR_P (new_allocator) = 1;
13300 68 : map_cnt++;
13301 68 : break;
13302 : }
13303 :
13304 37147 : if (offloaded)
13305 : {
13306 21187 : target_nesting_level++;
13307 21187 : lower_omp (&tgt_body, ctx);
13308 21187 : target_nesting_level--;
13309 : }
13310 15960 : else if (data_region)
13311 4021 : lower_omp (&tgt_body, ctx);
13312 :
13313 37147 : if (offloaded)
13314 : {
13315 : /* Declare all the variables created by mapping and the variables
13316 : declared in the scope of the target body. */
13317 21187 : record_vars_into (ctx->block_vars, child_fn);
13318 21187 : maybe_remove_omp_member_access_dummy_vars (tgt_bind);
13319 21187 : record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
13320 : }
13321 :
13322 37147 : if (ctx->record_type)
13323 : {
13324 32260 : if (deep_map_cnt && TREE_CODE (deep_map_cnt) == INTEGER_CST)
13325 : /* map_cnt = map_cnt + tree_to_hwi (deep_map_cnt); */
13326 : /* deep_map_cnt = NULL_TREE; */
13327 0 : gcc_unreachable ();
13328 144 : else if (deep_map_cnt)
13329 : {
13330 144 : gcc_assert (flexible_array_type_p (ctx->record_type));
13331 144 : tree n = create_tmp_var_raw (size_type_node, "nn_map");
13332 144 : gimple_add_tmp_var (n);
13333 144 : gimplify_assign (n, deep_map_cnt, &ilist);
13334 144 : deep_map_cnt = n;
13335 : }
13336 144 : ctx->sender_decl
13337 32260 : = create_tmp_var (deep_map_cnt ? build_pointer_type (ctx->record_type)
13338 : : ctx->record_type, ".omp_data_arr");
13339 32260 : DECL_NAMELESS (ctx->sender_decl) = 1;
13340 32260 : TREE_ADDRESSABLE (ctx->sender_decl) = 1;
13341 64376 : t = make_tree_vec (deep_map_cnt ? 4 : 3);
13342 32260 : TREE_VEC_ELT (t, 0) = ctx->sender_decl;
13343 32260 : TREE_VEC_ELT (t, 1)
13344 64520 : = create_tmp_var (deep_map_cnt
13345 144 : ? build_pointer_type (size_type_node)
13346 32116 : : build_array_type_nelts (size_type_node, map_cnt),
13347 : ".omp_data_sizes");
13348 32260 : DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
13349 32260 : TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
13350 32260 : TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
13351 32260 : tree tkind_type = short_unsigned_type_node;
13352 32260 : int talign_shift = 8;
13353 32260 : TREE_VEC_ELT (t, 2)
13354 64520 : = create_tmp_var (deep_map_cnt
13355 144 : ? build_pointer_type (tkind_type)
13356 32116 : : build_array_type_nelts (tkind_type, map_cnt),
13357 : ".omp_data_kinds");
13358 32260 : DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
13359 32260 : TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
13360 32260 : TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
13361 32260 : gimple_omp_target_set_data_arg (stmt, t);
13362 :
13363 32260 : if (deep_map_cnt)
13364 : {
13365 144 : tree tmp, size;
13366 144 : size = create_tmp_var (size_type_node, NULL);
13367 144 : DECL_NAMELESS (size) = 1;
13368 144 : gimplify_assign (size,
13369 : fold_build2_loc (UNKNOWN_LOCATION, PLUS_EXPR,
13370 : size_type_node, deep_map_cnt,
13371 : build_int_cst (size_type_node,
13372 144 : map_cnt)), &ilist);
13373 144 : TREE_VEC_ELT (t, 3) = size;
13374 :
13375 144 : tree call = builtin_decl_explicit (BUILT_IN_MALLOC);
13376 144 : size = fold_build2_loc (UNKNOWN_LOCATION, MULT_EXPR,
13377 : size_type_node, deep_map_cnt,
13378 144 : TYPE_SIZE_UNIT (ptr_type_node));
13379 144 : size = fold_build2_loc (UNKNOWN_LOCATION, PLUS_EXPR,
13380 : size_type_node, size,
13381 144 : TYPE_SIZE_UNIT (ctx->record_type));
13382 144 : tmp = build_call_expr_loc (input_location, call, 1, size);
13383 144 : gimplify_assign (ctx->sender_decl, tmp, &ilist);
13384 :
13385 144 : size = fold_build2_loc (UNKNOWN_LOCATION, MULT_EXPR,
13386 144 : size_type_node, TREE_VEC_ELT (t, 3),
13387 144 : TYPE_SIZE_UNIT (size_type_node));
13388 144 : tmp = build_call_expr_loc (input_location, call, 1, size);
13389 144 : gimplify_assign (TREE_VEC_ELT (t, 1), tmp, &ilist);
13390 :
13391 144 : size = fold_build2_loc (UNKNOWN_LOCATION, MULT_EXPR,
13392 144 : size_type_node, TREE_VEC_ELT (t, 3),
13393 144 : TYPE_SIZE_UNIT (tkind_type));
13394 144 : tmp = build_call_expr_loc (input_location, call, 1, size);
13395 144 : gimplify_assign (TREE_VEC_ELT (t, 2), tmp, &ilist);
13396 144 : tree field = TYPE_FIELDS (TREE_TYPE (TREE_TYPE (ctx->sender_decl)));
13397 595 : for ( ; DECL_CHAIN (field) != NULL_TREE; field = DECL_CHAIN (field))
13398 : ;
13399 144 : gcc_assert (TREE_CODE (TREE_TYPE (field)));
13400 144 : tmp = build_fold_indirect_ref (ctx->sender_decl);
13401 144 : deep_map_data = omp_build_component_ref (tmp, field);
13402 144 : deep_map_offset_data = create_tmp_var_raw (size_type_node,
13403 : "map_offset_data");
13404 144 : deep_map_offset = create_tmp_var_raw (size_type_node, "map_offset");
13405 144 : gimple_add_tmp_var (deep_map_offset_data);
13406 144 : gimple_add_tmp_var (deep_map_offset);
13407 144 : gimplify_assign (deep_map_offset_data, build_int_cst (size_type_node,
13408 : 0), &ilist);
13409 144 : gimplify_assign (deep_map_offset, build_int_cst (size_type_node,
13410 144 : map_cnt), &ilist);
13411 : }
13412 :
13413 32260 : vec<constructor_elt, va_gc> *vsize;
13414 32260 : vec<constructor_elt, va_gc> *vkind;
13415 32260 : vec_alloc (vsize, map_cnt);
13416 32260 : vec_alloc (vkind, map_cnt);
13417 32260 : unsigned int map_idx = 0;
13418 :
13419 162084 : for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
13420 129824 : switch (OMP_CLAUSE_CODE (c))
13421 : {
13422 : tree ovar, nc, s, purpose, var, x, type;
13423 : unsigned int talign;
13424 :
13425 : default:
13426 125860 : break;
13427 :
13428 87928 : case OMP_CLAUSE_MAP:
13429 87928 : case OMP_CLAUSE_TO:
13430 87928 : case OMP_CLAUSE_FROM:
13431 87928 : oacc_firstprivate_map:
13432 87928 : nc = c;
13433 87928 : ovar = OMP_CLAUSE_DECL (c);
13434 87928 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13435 87928 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
13436 72955 : || (OMP_CLAUSE_MAP_KIND (c)
13437 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
13438 : break;
13439 84096 : if (deep_map_cnt)
13440 : {
13441 428 : unsigned HOST_WIDE_INT tkind2;
13442 428 : switch (OMP_CLAUSE_CODE (c))
13443 : {
13444 424 : case OMP_CLAUSE_MAP:
13445 424 : tkind2 = OMP_CLAUSE_MAP_KIND (c);
13446 424 : if (OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (c)
13447 424 : && (((tkind2 & GOMP_MAP_FLAG_SPECIAL_BITS)
13448 : & ~GOMP_MAP_IMPLICIT)
13449 : == 0))
13450 : {
13451 : /* If this is an implicit map, and the GOMP_MAP_IMPLICIT
13452 : bits are not interfered by other special bit
13453 : encodings, then turn the GOMP_IMPLICIT_BIT flag on
13454 : for the runtime to see. */
13455 120 : tkind2 |= GOMP_MAP_IMPLICIT;
13456 : }
13457 : break;
13458 : case OMP_CLAUSE_FIRSTPRIVATE: tkind2 = GOMP_MAP_TO; break;
13459 : case OMP_CLAUSE_TO: tkind2 = GOMP_MAP_TO; break;
13460 2 : case OMP_CLAUSE_FROM: tkind2 = GOMP_MAP_FROM; break;
13461 0 : default: gcc_unreachable ();
13462 : }
13463 428 : lang_hooks.decls.omp_deep_mapping (stmt, c, tkind2,
13464 : deep_map_data,
13465 428 : TREE_VEC_ELT (t, 1),
13466 428 : TREE_VEC_ELT (t, 2),
13467 : deep_map_offset_data,
13468 : deep_map_offset, &ilist);
13469 : }
13470 84096 : if (!DECL_P (ovar))
13471 : {
13472 36882 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13473 36882 : && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
13474 : {
13475 0 : nc = OMP_CLAUSE_CHAIN (c);
13476 0 : gcc_checking_assert (OMP_CLAUSE_DECL (nc)
13477 : == get_base_address (ovar));
13478 0 : ovar = OMP_CLAUSE_DECL (nc);
13479 : }
13480 : else
13481 : {
13482 36882 : tree x = build_sender_ref (c, ctx);
13483 36882 : tree v = ovar;
13484 36882 : if (in_reduction_clauses
13485 163 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13486 37045 : && OMP_CLAUSE_MAP_IN_REDUCTION (c))
13487 : {
13488 104 : v = unshare_expr (v);
13489 104 : tree *p = &v;
13490 104 : while (handled_component_p (*p)
13491 : || TREE_CODE (*p) == INDIRECT_REF
13492 : || TREE_CODE (*p) == ADDR_EXPR
13493 : || TREE_CODE (*p) == MEM_REF
13494 256 : || TREE_CODE (*p) == NON_LVALUE_EXPR)
13495 152 : p = &TREE_OPERAND (*p, 0);
13496 104 : tree d = *p;
13497 104 : if (is_variable_sized (d))
13498 : {
13499 16 : gcc_assert (DECL_HAS_VALUE_EXPR_P (d));
13500 16 : d = DECL_VALUE_EXPR (d);
13501 16 : gcc_assert (TREE_CODE (d) == INDIRECT_REF);
13502 16 : d = TREE_OPERAND (d, 0);
13503 16 : gcc_assert (DECL_P (d));
13504 : }
13505 104 : splay_tree_key key
13506 104 : = (splay_tree_key) &DECL_CONTEXT (d);
13507 104 : tree nd = (tree) splay_tree_lookup (ctx->field_map,
13508 104 : key)->value;
13509 104 : if (d == *p)
13510 88 : *p = nd;
13511 : else
13512 16 : *p = build_fold_indirect_ref (nd);
13513 : }
13514 36882 : v = build_fold_addr_expr_with_type (v, ptr_type_node);
13515 36882 : v = lower_omp_map_iterator_expr (v, c, stmt);
13516 36882 : gimplify_assign (x, v, &ilist);
13517 36882 : nc = NULL_TREE;
13518 : }
13519 : }
13520 : else
13521 : {
13522 47214 : if (DECL_SIZE (ovar)
13523 47214 : && !poly_int_tree_p (DECL_SIZE (ovar)))
13524 : {
13525 7 : tree ovar2 = DECL_VALUE_EXPR (ovar);
13526 7 : gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
13527 7 : ovar2 = TREE_OPERAND (ovar2, 0);
13528 7 : gcc_assert (DECL_P (ovar2));
13529 : ovar = ovar2;
13530 : }
13531 47214 : if (!maybe_lookup_field (c, ctx)
13532 51178 : && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13533 3964 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
13534 3964 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)))
13535 3964 : continue;
13536 : }
13537 :
13538 80132 : talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
13539 80132 : if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
13540 6409 : talign = DECL_ALIGN_UNIT (ovar);
13541 :
13542 80132 : var = NULL_TREE;
13543 80132 : if (nc)
13544 : {
13545 43250 : if (in_reduction_clauses
13546 897 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13547 44147 : && OMP_CLAUSE_MAP_IN_REDUCTION (c))
13548 : {
13549 268 : tree d = ovar;
13550 268 : if (is_variable_sized (d))
13551 : {
13552 0 : gcc_assert (DECL_HAS_VALUE_EXPR_P (d));
13553 0 : d = DECL_VALUE_EXPR (d);
13554 0 : gcc_assert (TREE_CODE (d) == INDIRECT_REF);
13555 0 : d = TREE_OPERAND (d, 0);
13556 0 : gcc_assert (DECL_P (d));
13557 : }
13558 268 : splay_tree_key key
13559 268 : = (splay_tree_key) &DECL_CONTEXT (d);
13560 268 : tree nd = (tree) splay_tree_lookup (ctx->field_map,
13561 268 : key)->value;
13562 268 : if (d == ovar)
13563 : var = nd;
13564 : else
13565 0 : var = build_fold_indirect_ref (nd);
13566 : }
13567 : else
13568 42982 : var = lookup_decl_in_outer_ctx (ovar, ctx);
13569 : }
13570 43250 : if (nc
13571 43250 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13572 33286 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
13573 33079 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
13574 261 : && is_omp_target (stmt))
13575 : {
13576 237 : x = build_sender_ref (c, ctx);
13577 237 : gimplify_assign (x, build_fold_addr_expr (var), &ilist);
13578 : }
13579 79895 : else if (nc)
13580 : {
13581 43013 : x = build_sender_ref (nc, ctx);
13582 :
13583 43013 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13584 33049 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
13585 5184 : && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
13586 48197 : && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
13587 : {
13588 425 : gcc_assert (offloaded);
13589 425 : tree avar = build_fold_addr_expr (var);
13590 425 : if (!OMP_CLAUSE_ITERATORS (c))
13591 : {
13592 425 : tree tmp = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
13593 425 : mark_addressable (tmp);
13594 425 : gimplify_assign (tmp, avar, &ilist);
13595 425 : avar = tmp;
13596 : }
13597 425 : talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (x)));
13598 425 : avar = build_fold_addr_expr (avar);
13599 425 : avar = lower_omp_map_iterator_expr (avar, c, stmt);
13600 425 : gimplify_assign (x, avar, &ilist);
13601 : }
13602 42588 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
13603 : {
13604 3896 : gcc_assert (is_gimple_omp_oacc (ctx->stmt));
13605 3896 : if (!omp_privatize_by_reference (var))
13606 : {
13607 3441 : if (is_gimple_reg (var)
13608 3441 : && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
13609 2578 : suppress_warning (var);
13610 3441 : var = build_fold_addr_expr (var);
13611 : }
13612 : else
13613 455 : talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
13614 3896 : gimplify_assign (x, var, &ilist);
13615 : }
13616 38692 : else if (is_gimple_reg (var))
13617 : {
13618 5283 : gcc_assert (offloaded);
13619 5283 : tree avar = create_tmp_var (TREE_TYPE (var));
13620 5283 : mark_addressable (avar);
13621 5283 : enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
13622 5283 : if (GOMP_MAP_COPY_TO_P (map_kind)
13623 : || map_kind == GOMP_MAP_POINTER
13624 475 : || map_kind == GOMP_MAP_TO_PSET
13625 2 : || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
13626 : {
13627 : /* If we need to initialize a temporary
13628 : with VAR because it is not addressable, and
13629 : the variable hasn't been initialized yet, then
13630 : we'll get a warning for the store to avar.
13631 : Don't warn in that case, the mapping might
13632 : be implicit. */
13633 5281 : suppress_warning (var, OPT_Wuninitialized);
13634 5281 : gimplify_assign (avar, var, &ilist);
13635 : }
13636 5283 : avar = build_fold_addr_expr (avar);
13637 5283 : gimplify_assign (x, avar, &ilist);
13638 5283 : if ((GOMP_MAP_COPY_FROM_P (map_kind)
13639 1486 : || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
13640 9080 : && !TYPE_READONLY (TREE_TYPE (var)))
13641 : {
13642 3797 : x = unshare_expr (x);
13643 3797 : x = build_simple_mem_ref (x);
13644 3797 : gimplify_assign (var, x, &olist);
13645 : }
13646 : }
13647 : else
13648 : {
13649 : /* While MAP is handled explicitly by the FE,
13650 : for 'target update', only the identified is passed. */
13651 33409 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM
13652 28285 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO)
13653 34353 : && (omp_is_allocatable_or_ptr (var)
13654 120 : && omp_check_optional_argument (var, false)))
13655 0 : var = build_fold_indirect_ref (var);
13656 33409 : else if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FROM
13657 28285 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_TO)
13658 34353 : || (!omp_is_allocatable_or_ptr (var)
13659 5948 : && !omp_check_optional_argument (var, false)))
13660 33289 : var = build_fold_addr_expr (var);
13661 33409 : gimplify_assign (x, var, &ilist);
13662 : }
13663 : }
13664 80132 : s = NULL_TREE;
13665 80132 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
13666 : {
13667 3896 : gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
13668 3896 : s = TREE_TYPE (ovar);
13669 3896 : if (TREE_CODE (s) == REFERENCE_TYPE
13670 3896 : || omp_check_optional_argument (ovar, false))
13671 449 : s = TREE_TYPE (s);
13672 3896 : s = TYPE_SIZE_UNIT (s);
13673 : }
13674 : else
13675 76236 : s = OMP_CLAUSE_SIZE (c);
13676 80132 : if (s == NULL_TREE)
13677 153 : s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
13678 80132 : s = fold_convert (size_type_node, s);
13679 80132 : s = lower_omp_map_iterator_size (s, c, stmt);
13680 80132 : purpose = size_int (map_idx++);
13681 80132 : CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
13682 80132 : if (TREE_CODE (s) != INTEGER_CST)
13683 16154 : TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
13684 :
13685 80132 : unsigned HOST_WIDE_INT tkind, tkind_zero;
13686 80132 : switch (OMP_CLAUSE_CODE (c))
13687 : {
13688 68562 : case OMP_CLAUSE_MAP:
13689 68562 : tkind = OMP_CLAUSE_MAP_KIND (c);
13690 68562 : tkind_zero = tkind;
13691 68562 : if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
13692 5276 : switch (tkind)
13693 : {
13694 : case GOMP_MAP_ALLOC:
13695 : case GOMP_MAP_IF_PRESENT:
13696 : case GOMP_MAP_TO:
13697 : case GOMP_MAP_FROM:
13698 : case GOMP_MAP_TOFROM:
13699 : case GOMP_MAP_ALWAYS_TO:
13700 : case GOMP_MAP_ALWAYS_FROM:
13701 : case GOMP_MAP_ALWAYS_TOFROM:
13702 : case GOMP_MAP_ALWAYS_PRESENT_TO:
13703 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
13704 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
13705 : case GOMP_MAP_RELEASE:
13706 : case GOMP_MAP_FORCE_TO:
13707 : case GOMP_MAP_FORCE_FROM:
13708 : case GOMP_MAP_FORCE_TOFROM:
13709 : case GOMP_MAP_FORCE_PRESENT:
13710 68562 : tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
13711 : break;
13712 21 : case GOMP_MAP_DELETE:
13713 21 : tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
13714 : default:
13715 : break;
13716 : }
13717 68562 : if (tkind_zero != tkind)
13718 : {
13719 5276 : if (integer_zerop (s))
13720 : tkind = tkind_zero;
13721 4550 : else if (integer_nonzerop (s))
13722 68562 : tkind_zero = tkind;
13723 : }
13724 68562 : if (tkind_zero == tkind
13725 67101 : && OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (c)
13726 68562 : && (((tkind & GOMP_MAP_FLAG_SPECIAL_BITS)
13727 5232 : & ~GOMP_MAP_IMPLICIT)
13728 : == 0))
13729 : {
13730 : /* If this is an implicit map, and the GOMP_MAP_IMPLICIT
13731 : bits are not interfered by other special bit encodings,
13732 : then turn the GOMP_IMPLICIT_BIT flag on for the runtime
13733 : to see. */
13734 5189 : tkind |= GOMP_MAP_IMPLICIT;
13735 5189 : tkind_zero = tkind;
13736 : }
13737 : break;
13738 3896 : case OMP_CLAUSE_FIRSTPRIVATE:
13739 3896 : gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
13740 : tkind = GOMP_MAP_TO;
13741 : tkind_zero = tkind;
13742 : break;
13743 1651 : case OMP_CLAUSE_TO:
13744 1651 : tkind
13745 1651 : = (OMP_CLAUSE_MOTION_PRESENT (c)
13746 1651 : ? GOMP_MAP_ALWAYS_PRESENT_TO : GOMP_MAP_TO);
13747 : tkind_zero = tkind;
13748 : break;
13749 6023 : case OMP_CLAUSE_FROM:
13750 6023 : tkind
13751 6023 : = (OMP_CLAUSE_MOTION_PRESENT (c)
13752 6023 : ? GOMP_MAP_ALWAYS_PRESENT_FROM : GOMP_MAP_FROM);
13753 : tkind_zero = tkind;
13754 : break;
13755 0 : default:
13756 0 : gcc_unreachable ();
13757 : }
13758 68562 : gcc_checking_assert (tkind
13759 : < (HOST_WIDE_INT_C (1U) << talign_shift));
13760 80132 : gcc_checking_assert (tkind_zero
13761 : < (HOST_WIDE_INT_C (1U) << talign_shift));
13762 80132 : talign = ceil_log2 (talign);
13763 80132 : tkind |= talign << talign_shift;
13764 80132 : tkind_zero |= talign << talign_shift;
13765 80132 : gcc_checking_assert (tkind
13766 : <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
13767 80132 : gcc_checking_assert (tkind_zero
13768 : <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
13769 80132 : if (tkind == tkind_zero)
13770 78671 : x = build_int_cstu (tkind_type, tkind);
13771 : else
13772 : {
13773 1461 : TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
13774 1461 : x = build3 (COND_EXPR, tkind_type,
13775 : fold_build2 (EQ_EXPR, boolean_type_node,
13776 : unshare_expr (s), size_zero_node),
13777 1461 : build_int_cstu (tkind_type, tkind_zero),
13778 1461 : build_int_cstu (tkind_type, tkind));
13779 : }
13780 80132 : CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
13781 80132 : if (nc && nc != c)
13782 0 : c = nc;
13783 : break;
13784 :
13785 15294 : case OMP_CLAUSE_FIRSTPRIVATE:
13786 15294 : omp_has_device_addr_descr:
13787 15294 : if (is_gimple_omp_oacc (ctx->stmt))
13788 3896 : goto oacc_firstprivate_map;
13789 11398 : ovar = OMP_CLAUSE_DECL (c);
13790 11398 : if (omp_privatize_by_reference (ovar))
13791 822 : talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
13792 : else
13793 10576 : talign = DECL_ALIGN_UNIT (ovar);
13794 11398 : var = lookup_decl_in_outer_ctx (ovar, ctx);
13795 11398 : x = build_sender_ref (ovar, ctx);
13796 11398 : tkind = GOMP_MAP_FIRSTPRIVATE;
13797 11398 : type = TREE_TYPE (ovar);
13798 11398 : if (omp_privatize_by_reference (ovar))
13799 822 : type = TREE_TYPE (type);
13800 11398 : if ((INTEGRAL_TYPE_P (type)
13801 10996 : && TYPE_PRECISION (type) <= POINTER_SIZE)
13802 11408 : || TREE_CODE (type) == POINTER_TYPE)
13803 : {
13804 11141 : tkind = GOMP_MAP_FIRSTPRIVATE_INT;
13805 11141 : tree t = var;
13806 11141 : if (omp_privatize_by_reference (var))
13807 767 : t = build_simple_mem_ref (var);
13808 10374 : else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
13809 9310 : suppress_warning (var);
13810 11141 : if (TREE_CODE (type) != POINTER_TYPE)
13811 10986 : t = fold_convert (pointer_sized_int_node, t);
13812 11141 : t = fold_convert (TREE_TYPE (x), t);
13813 11141 : gimplify_assign (x, t, &ilist);
13814 : }
13815 257 : else if (omp_privatize_by_reference (var))
13816 55 : gimplify_assign (x, var, &ilist);
13817 202 : else if (is_gimple_reg (var))
13818 : {
13819 47 : tree avar = create_tmp_var (TREE_TYPE (var));
13820 47 : mark_addressable (avar);
13821 47 : if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
13822 40 : suppress_warning (var);
13823 47 : gimplify_assign (avar, var, &ilist);
13824 47 : avar = build_fold_addr_expr (avar);
13825 47 : gimplify_assign (x, avar, &ilist);
13826 : }
13827 : else
13828 : {
13829 155 : var = build_fold_addr_expr (var);
13830 155 : gimplify_assign (x, var, &ilist);
13831 : }
13832 257 : if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
13833 11141 : s = size_int (0);
13834 257 : else if (omp_privatize_by_reference (ovar))
13835 55 : s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
13836 : else
13837 202 : s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
13838 11398 : s = fold_convert (size_type_node, s);
13839 11398 : purpose = size_int (map_idx++);
13840 11398 : CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
13841 11398 : if (TREE_CODE (s) != INTEGER_CST)
13842 35 : TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
13843 :
13844 11398 : gcc_checking_assert (tkind
13845 : < (HOST_WIDE_INT_C (1U) << talign_shift));
13846 11398 : talign = ceil_log2 (talign);
13847 11398 : tkind |= talign << talign_shift;
13848 11398 : gcc_checking_assert (tkind
13849 : <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
13850 11398 : CONSTRUCTOR_APPEND_ELT (vkind, purpose,
13851 : build_int_cstu (tkind_type, tkind));
13852 : /* Fortran array descriptors: firstprivate of data + attach. */
13853 11398 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR
13854 11379 : && lang_hooks.decls.omp_array_data (ovar, true)
13855 11429 : && lang_hooks.decls.omp_array_data_privatize (ovar))
13856 : {
13857 23 : tree not_null_lb, null_lb, after_lb;
13858 23 : tree var1, var2, size1, size2;
13859 23 : tree present = omp_check_optional_argument (ovar, true);
13860 23 : if (present)
13861 : {
13862 1 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
13863 1 : not_null_lb = create_artificial_label (clause_loc);
13864 1 : null_lb = create_artificial_label (clause_loc);
13865 1 : after_lb = create_artificial_label (clause_loc);
13866 1 : gimple_seq seq = NULL;
13867 1 : present = force_gimple_operand (present, &seq, true,
13868 : NULL_TREE);
13869 1 : gimple_seq_add_seq (&ilist, seq);
13870 1 : gimple_seq_add_stmt (&ilist,
13871 1 : gimple_build_cond_from_tree (present,
13872 : not_null_lb, null_lb));
13873 1 : gimple_seq_add_stmt (&ilist,
13874 1 : gimple_build_label (not_null_lb));
13875 : }
13876 23 : var1 = lang_hooks.decls.omp_array_data (var, false);
13877 23 : size1 = lang_hooks.decls.omp_array_size (var, &ilist);
13878 23 : var2 = build_fold_addr_expr (x);
13879 23 : if (!POINTER_TYPE_P (TREE_TYPE (var)))
13880 0 : var = build_fold_addr_expr (var);
13881 23 : size2 = fold_build2 (POINTER_DIFF_EXPR, ssizetype,
13882 : build_fold_addr_expr (var1), var);
13883 23 : size2 = fold_convert (sizetype, size2);
13884 23 : if (present)
13885 : {
13886 1 : tree tmp = create_tmp_var (TREE_TYPE (var1));
13887 1 : gimplify_assign (tmp, var1, &ilist);
13888 1 : var1 = tmp;
13889 1 : tmp = create_tmp_var (TREE_TYPE (var2));
13890 1 : gimplify_assign (tmp, var2, &ilist);
13891 1 : var2 = tmp;
13892 1 : tmp = create_tmp_var (TREE_TYPE (size1));
13893 1 : gimplify_assign (tmp, size1, &ilist);
13894 1 : size1 = tmp;
13895 1 : tmp = create_tmp_var (TREE_TYPE (size2));
13896 1 : gimplify_assign (tmp, size2, &ilist);
13897 1 : size2 = tmp;
13898 1 : gimple_seq_add_stmt (&ilist, gimple_build_goto (after_lb));
13899 1 : gimple_seq_add_stmt (&ilist, gimple_build_label (null_lb));
13900 1 : gimplify_assign (var1, null_pointer_node, &ilist);
13901 1 : gimplify_assign (var2, null_pointer_node, &ilist);
13902 1 : gimplify_assign (size1, size_zero_node, &ilist);
13903 1 : gimplify_assign (size2, size_zero_node, &ilist);
13904 1 : gimple_seq_add_stmt (&ilist, gimple_build_label (after_lb));
13905 : }
13906 23 : x = build_sender_ref ((splay_tree_key) &DECL_NAME (ovar), ctx);
13907 23 : gimplify_assign (x, var1, &ilist);
13908 23 : tkind = GOMP_MAP_FIRSTPRIVATE;
13909 23 : talign = DECL_ALIGN_UNIT (ovar);
13910 23 : talign = ceil_log2 (talign);
13911 23 : tkind |= talign << talign_shift;
13912 23 : gcc_checking_assert (tkind
13913 : <= tree_to_uhwi (
13914 : TYPE_MAX_VALUE (tkind_type)));
13915 23 : purpose = size_int (map_idx++);
13916 23 : CONSTRUCTOR_APPEND_ELT (vsize, purpose, size1);
13917 23 : if (TREE_CODE (size1) != INTEGER_CST)
13918 23 : TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
13919 23 : CONSTRUCTOR_APPEND_ELT (vkind, purpose,
13920 : build_int_cstu (tkind_type, tkind));
13921 23 : x = build_sender_ref ((splay_tree_key) &DECL_UID (ovar), ctx);
13922 23 : gimplify_assign (x, var2, &ilist);
13923 23 : tkind = GOMP_MAP_ATTACH;
13924 23 : purpose = size_int (map_idx++);
13925 23 : CONSTRUCTOR_APPEND_ELT (vsize, purpose, size2);
13926 23 : CONSTRUCTOR_APPEND_ELT (vkind, purpose,
13927 : build_int_cstu (tkind_type, tkind));
13928 : }
13929 : break;
13930 :
13931 2430 : case OMP_CLAUSE_USE_DEVICE_PTR:
13932 2430 : case OMP_CLAUSE_USE_DEVICE_ADDR:
13933 2430 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
13934 2430 : case OMP_CLAUSE_IS_DEVICE_PTR:
13935 2430 : ovar = OMP_CLAUSE_DECL (c);
13936 2430 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
13937 : {
13938 235 : if (lang_hooks.decls.omp_array_data (ovar, true))
13939 19 : goto omp_has_device_addr_descr;
13940 233 : while (TREE_CODE (ovar) == INDIRECT_REF
13941 233 : || TREE_CODE (ovar) == ARRAY_REF)
13942 17 : ovar = TREE_OPERAND (ovar, 0);
13943 : }
13944 2411 : var = lookup_decl_in_outer_ctx (ovar, ctx);
13945 :
13946 2411 : if (lang_hooks.decls.omp_array_data (ovar, true))
13947 : {
13948 601 : tkind = ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IS_DEVICE_PTR
13949 601 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR)
13950 601 : ? GOMP_MAP_USE_DEVICE_PTR : GOMP_MAP_FIRSTPRIVATE_INT);
13951 601 : x = build_sender_ref ((splay_tree_key) &DECL_NAME (ovar), ctx);
13952 : }
13953 1810 : else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IS_DEVICE_PTR
13954 1810 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR)
13955 : {
13956 1453 : tkind = GOMP_MAP_USE_DEVICE_PTR;
13957 1453 : x = build_sender_ref ((splay_tree_key) &DECL_UID (ovar), ctx);
13958 : }
13959 : else
13960 : {
13961 357 : tkind = GOMP_MAP_FIRSTPRIVATE_INT;
13962 357 : x = build_sender_ref (ovar, ctx);
13963 : }
13964 :
13965 2411 : if (is_gimple_omp_oacc (ctx->stmt))
13966 : {
13967 147 : gcc_assert (tkind == GOMP_MAP_USE_DEVICE_PTR);
13968 :
13969 147 : if (OMP_CLAUSE_USE_DEVICE_PTR_IF_PRESENT (c))
13970 57 : tkind = GOMP_MAP_USE_DEVICE_PTR_IF_PRESENT;
13971 : }
13972 :
13973 2411 : type = TREE_TYPE (ovar);
13974 2411 : if (lang_hooks.decls.omp_array_data (ovar, true))
13975 601 : var = lang_hooks.decls.omp_array_data (var, false);
13976 1810 : else if (((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_ADDR
13977 542 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
13978 1484 : && !omp_privatize_by_reference (ovar)
13979 512 : && !omp_is_allocatable_or_ptr (ovar))
13980 3247 : || TREE_CODE (type) == ARRAY_TYPE)
13981 401 : var = build_fold_addr_expr (var);
13982 : else
13983 : {
13984 1409 : if (omp_privatize_by_reference (ovar)
13985 370 : || omp_check_optional_argument (ovar, false)
13986 1779 : || omp_is_allocatable_or_ptr (ovar))
13987 : {
13988 1212 : type = TREE_TYPE (type);
13989 1212 : if (POINTER_TYPE_P (type)
13990 1212 : && TREE_CODE (type) != ARRAY_TYPE
13991 1571 : && ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_USE_DEVICE_ADDR
13992 36 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR
13993 28 : && !omp_is_allocatable_or_ptr (ovar))
13994 337 : || (omp_privatize_by_reference (ovar)
13995 337 : && omp_is_allocatable_or_ptr (ovar))))
13996 357 : var = build_simple_mem_ref (var);
13997 1212 : var = fold_convert (TREE_TYPE (x), var);
13998 : }
13999 : }
14000 2411 : tree present;
14001 2411 : present = omp_check_optional_argument (ovar, true);
14002 2411 : if (present)
14003 : {
14004 878 : tree null_label = create_artificial_label (UNKNOWN_LOCATION);
14005 878 : tree notnull_label = create_artificial_label (UNKNOWN_LOCATION);
14006 878 : tree opt_arg_label = create_artificial_label (UNKNOWN_LOCATION);
14007 878 : tree new_x = unshare_expr (x);
14008 878 : gimplify_expr (&present, &ilist, NULL, is_gimple_val,
14009 : fb_rvalue);
14010 878 : gcond *cond = gimple_build_cond_from_tree (present,
14011 : notnull_label,
14012 : null_label);
14013 878 : gimple_seq_add_stmt (&ilist, cond);
14014 878 : gimple_seq_add_stmt (&ilist, gimple_build_label (null_label));
14015 878 : gimplify_assign (new_x, null_pointer_node, &ilist);
14016 878 : gimple_seq_add_stmt (&ilist, gimple_build_goto (opt_arg_label));
14017 878 : gimple_seq_add_stmt (&ilist,
14018 878 : gimple_build_label (notnull_label));
14019 878 : gimplify_assign (x, var, &ilist);
14020 878 : gimple_seq_add_stmt (&ilist,
14021 878 : gimple_build_label (opt_arg_label));
14022 : }
14023 : else
14024 1533 : gimplify_assign (x, var, &ilist);
14025 2411 : s = size_int (0);
14026 2411 : purpose = size_int (map_idx++);
14027 2411 : CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
14028 2411 : gcc_checking_assert (tkind
14029 : < (HOST_WIDE_INT_C (1U) << talign_shift));
14030 2411 : gcc_checking_assert (tkind
14031 : <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
14032 2411 : CONSTRUCTOR_APPEND_ELT (vkind, purpose,
14033 : build_int_cstu (tkind_type, tkind));
14034 2411 : break;
14035 :
14036 68 : case OMP_CLAUSE_USES_ALLOCATORS:
14037 68 : tree allocator = OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR (c);
14038 68 : tree memspace = OMP_CLAUSE_USES_ALLOCATORS_MEMSPACE (c);
14039 68 : tree traits = OMP_CLAUSE_USES_ALLOCATORS_TRAITS (c);
14040 :
14041 68 : tree ntraits, traits_var;
14042 68 : if (traits == NULL_TREE)
14043 : {
14044 27 : ntraits = integer_zero_node;
14045 27 : traits_var = null_pointer_node;
14046 : }
14047 41 : else if (DECL_INITIAL (traits))
14048 : {
14049 29 : location_t loc = OMP_CLAUSE_LOCATION (c);
14050 29 : ntraits = array_type_nelts_top (TREE_TYPE (traits));
14051 29 : tree t = DECL_INITIAL (traits);
14052 29 : t = get_initialized_tmp_var (t, &ilist, NULL);
14053 29 : traits_var = build_fold_addr_expr_loc (loc, t);
14054 : }
14055 : else
14056 : {
14057 : /* This happens for VLAs, which probably aren't useful
14058 : because they can't be const initialized in the same
14059 : scope.... is there something else? */
14060 12 : location_t loc = OMP_CLAUSE_LOCATION (c);
14061 12 : gcc_assert (TREE_CODE (TREE_TYPE (traits)) == ARRAY_TYPE);
14062 12 : ntraits = array_type_nelts_top (TREE_TYPE (traits));
14063 12 : traits_var = build_fold_addr_expr_loc (loc, traits);
14064 : }
14065 :
14066 68 : if (memspace == NULL_TREE)
14067 55 : memspace = build_int_cst (pointer_sized_int_node, 0);
14068 : else
14069 13 : memspace = fold_convert (pointer_sized_int_node, memspace);
14070 :
14071 68 : tree arr_type
14072 68 : = build_array_type_nelts (pointer_sized_int_node, 3);
14073 68 : tree uses_allocators_descr
14074 68 : = create_tmp_var (arr_type, "uses_allocator_descr");
14075 68 : tree ua_descr[3];
14076 272 : for (int i = 0; i < 3; i++)
14077 204 : ua_descr[i] = build4 (ARRAY_REF, pointer_sized_int_node,
14078 : uses_allocators_descr,
14079 204 : build_int_cst (size_type_node, i),
14080 : NULL_TREE, NULL_TREE);
14081 68 : gimplify_assign (ua_descr[0],
14082 : fold_convert (pointer_sized_int_node, memspace),
14083 : &ilist);
14084 68 : gimplify_assign (ua_descr[1],
14085 : fold_convert (pointer_sized_int_node, ntraits),
14086 : &ilist);
14087 68 : gimplify_assign (ua_descr[2],
14088 : fold_convert (pointer_sized_int_node, traits_var),
14089 : &ilist);
14090 :
14091 68 : x = build_sender_ref (allocator, ctx);
14092 68 : tree ptr = build_fold_addr_expr (uses_allocators_descr);
14093 68 : gimplify_assign (x, fold_convert (TREE_TYPE (x), ptr), &ilist);
14094 :
14095 68 : s = size_int (0);
14096 68 : purpose = size_int (map_idx++);
14097 68 : CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
14098 68 : tkind = GOMP_MAP_USES_ALLOCATORS;
14099 68 : gcc_checking_assert (tkind
14100 : < (HOST_WIDE_INT_C (1U) << talign_shift));
14101 68 : talign = TYPE_ALIGN_UNIT (pointer_sized_int_node);
14102 68 : talign = ceil_log2 (talign);
14103 68 : tkind |= talign << talign_shift;
14104 68 : gcc_checking_assert (tkind
14105 : <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
14106 68 : CONSTRUCTOR_APPEND_ELT (vkind, purpose,
14107 : build_int_cstu (tkind_type, tkind));
14108 68 : break;
14109 : }
14110 :
14111 32260 : gcc_assert (map_idx == map_cnt);
14112 :
14113 32260 : if (!deep_map_cnt)
14114 : {
14115 32116 : DECL_INITIAL (TREE_VEC_ELT (t, 1))
14116 32116 : = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
14117 32116 : DECL_INITIAL (TREE_VEC_ELT (t, 2))
14118 64232 : = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
14119 : }
14120 96780 : for (int i = 1; i <= 2; i++)
14121 64520 : if (deep_map_cnt || !TREE_STATIC (TREE_VEC_ELT (t, i)))
14122 : {
14123 9657 : tree tmp = TREE_VEC_ELT (t, i);
14124 9657 : if (deep_map_cnt)
14125 : {
14126 288 : const char *prefix = (i == 1 ? ".omp_data_sizes0"
14127 : : ".omp_data_kinds0");
14128 144 : tree type = (i == 1) ? size_type_node : tkind_type;
14129 288 : type = build_array_type_nelts (type, map_cnt);
14130 288 : tree var = create_tmp_var (type, prefix);
14131 288 : DECL_NAMELESS (var) = 1;
14132 288 : TREE_ADDRESSABLE (var) = 1;
14133 288 : TREE_STATIC (var) = TREE_STATIC (tmp);
14134 288 : DECL_INITIAL (var) = build_constructor (type, i == 1
14135 : ? vsize : vkind);
14136 288 : tmp = var;
14137 288 : TREE_STATIC (TREE_VEC_ELT (t, i)) = 0;
14138 : }
14139 :
14140 9657 : gimple_seq initlist = NULL;
14141 9657 : force_gimple_operand (build1 (DECL_EXPR, void_type_node, tmp),
14142 : &initlist, true, NULL_TREE);
14143 9657 : gimple_seq_add_seq (&ilist, initlist);
14144 :
14145 9657 : if (deep_map_cnt)
14146 : {
14147 288 : tree tmp2;
14148 288 : tree call = builtin_decl_explicit (BUILT_IN_MEMCPY);
14149 288 : tmp2 = TYPE_SIZE_UNIT (TREE_TYPE (tmp));
14150 576 : call = build_call_expr_loc (input_location, call, 3,
14151 288 : TREE_VEC_ELT (t, i),
14152 : build_fold_addr_expr (tmp), tmp2);
14153 288 : gimplify_and_add (call, &ilist);
14154 : }
14155 :
14156 9657 : if (!TREE_STATIC (tmp))
14157 : {
14158 9439 : tree clobber = build_clobber (TREE_TYPE (tmp));
14159 9439 : gimple_seq_add_stmt (&olist,
14160 9439 : gimple_build_assign (tmp, clobber));
14161 : }
14162 9657 : if (deep_map_cnt)
14163 : {
14164 288 : tmp = TREE_VEC_ELT (t, i);
14165 288 : tree call = builtin_decl_explicit (BUILT_IN_FREE);
14166 288 : call = build_call_expr_loc (input_location, call, 1, tmp);
14167 288 : gimplify_and_add (call, &olist);
14168 288 : tree clobber = build_clobber (TREE_TYPE (tmp));
14169 288 : gimple_seq_add_stmt (&olist,
14170 288 : gimple_build_assign (tmp, clobber));
14171 : }
14172 : }
14173 54863 : else if (omp_maybe_offloaded_ctx (ctx->outer))
14174 : {
14175 3296 : tree id = get_identifier ("omp declare target");
14176 3296 : tree decl = TREE_VEC_ELT (t, i);
14177 3296 : DECL_ATTRIBUTES (decl)
14178 3296 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl));
14179 3296 : varpool_node *node = varpool_node::get (decl);
14180 3296 : if (node)
14181 : {
14182 0 : node->offloadable = 1;
14183 0 : if (ENABLE_OFFLOADING)
14184 : {
14185 : g->have_offload = true;
14186 : vec_safe_push (offload_vars, t);
14187 : }
14188 : }
14189 : }
14190 :
14191 32260 : if (deep_map_cnt)
14192 : {
14193 144 : tree call = builtin_decl_explicit (BUILT_IN_FREE);
14194 144 : call = build_call_expr_loc (input_location, call, 1,
14195 144 : TREE_VEC_ELT (t, 0));
14196 144 : gimplify_and_add (call, &olist);
14197 :
14198 144 : gimplify_expr (&TREE_VEC_ELT (t, 1), &ilist, NULL, is_gimple_val,
14199 : fb_rvalue);
14200 : }
14201 :
14202 32260 : tree clobber = build_clobber (TREE_TYPE (ctx->sender_decl));
14203 32260 : gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
14204 : clobber));
14205 : }
14206 :
14207 : /* Once all the expansions are done, sequence all the different
14208 : fragments inside gimple_omp_body. */
14209 :
14210 37147 : new_body = NULL;
14211 :
14212 37147 : if (offloaded
14213 21187 : && ctx->record_type)
14214 : {
14215 16537 : t = ctx->sender_decl;
14216 16537 : if (!deep_map_cnt)
14217 16430 : t = build_fold_addr_expr_loc (loc, t);
14218 : /* fixup_child_record_type might have changed receiver_decl's type. */
14219 16537 : t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
14220 16537 : if (!AGGREGATE_TYPE_P (TREE_TYPE (ctx->sender_decl)))
14221 107 : gimplify_assign (ctx->receiver_decl, t, &new_body);
14222 : else
14223 16430 : gimple_seq_add_stmt (&new_body,
14224 16430 : gimple_build_assign (ctx->receiver_decl, t));
14225 : }
14226 37147 : gimple_seq_add_seq (&new_body, fplist);
14227 :
14228 37147 : if (offloaded || data_region)
14229 : {
14230 141038 : tree prev = NULL_TREE;
14231 : bool by_ref;
14232 141038 : for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
14233 115830 : switch (OMP_CLAUSE_CODE (c))
14234 : {
14235 : tree var, x, new_var, *allocate_ptr;
14236 : default:
14237 : break;
14238 15294 : case OMP_CLAUSE_FIRSTPRIVATE:
14239 15294 : omp_firstprivatize_data_region:
14240 15294 : if (is_gimple_omp_oacc (ctx->stmt))
14241 : break;
14242 11398 : var = OMP_CLAUSE_DECL (c);
14243 11398 : new_var = lookup_decl (var, ctx);
14244 11398 : allocate_ptr = alloc_map.get (new_var);
14245 11398 : by_ref = omp_privatize_by_reference (var);
14246 11398 : if (allocate_ptr)
14247 : {
14248 63 : if (is_variable_sized (var, by_ref))
14249 : /* Handle this in the next pass when the size is
14250 : available. */
14251 : break;
14252 :
14253 48 : gimple_seq *allocate_seq = alloc_seq_map.get (new_var);
14254 48 : gcc_assert (allocate_seq);
14255 48 : gimple_seq_add_seq (&new_body, *allocate_seq);
14256 :
14257 48 : if (by_ref)
14258 : {
14259 4 : x = fold_convert (TREE_TYPE (new_var), *allocate_ptr);
14260 4 : gimplify_assign (new_var, x, &new_body);
14261 4 : new_var = build_fold_indirect_ref (new_var);
14262 : }
14263 : else
14264 44 : new_var = build_simple_mem_ref (*allocate_ptr);
14265 : }
14266 11383 : if (by_ref || is_gimple_reg_type (TREE_TYPE (var)))
14267 : {
14268 11242 : tree type;
14269 11242 : type = TREE_TYPE (var);
14270 11242 : if (by_ref)
14271 809 : type = TREE_TYPE (type);
14272 11242 : if ((INTEGRAL_TYPE_P (type)
14273 10996 : && TYPE_PRECISION (type) <= POINTER_SIZE)
14274 11252 : || TREE_CODE (type) == POINTER_TYPE)
14275 : {
14276 11141 : x = build_receiver_ref (var, false, ctx);
14277 11141 : if (TREE_CODE (type) != POINTER_TYPE)
14278 10986 : x = fold_convert (pointer_sized_int_node, x);
14279 11141 : x = fold_convert (type, x);
14280 11141 : gimplify_expr (&x, &new_body, NULL, is_gimple_val,
14281 : fb_rvalue);
14282 11141 : if (by_ref && !allocate_ptr)
14283 : {
14284 766 : tree v = create_tmp_var_raw (type, get_name (var));
14285 766 : gimple_add_tmp_var (v);
14286 766 : TREE_ADDRESSABLE (v) = 1;
14287 766 : gimple_seq_add_stmt (&new_body,
14288 766 : gimple_build_assign (v, x));
14289 766 : x = build_fold_addr_expr (v);
14290 : }
14291 11141 : gimplify_assign (new_var, x, &new_body);
14292 : }
14293 : else
14294 : {
14295 101 : x = build_receiver_ref (var, allocate_ptr || !by_ref, ctx);
14296 101 : gimplify_expr (&x, &new_body, NULL, is_gimple_val,
14297 : fb_rvalue);
14298 101 : gimplify_assign (new_var, x, &new_body);
14299 : }
14300 : }
14301 141 : else if (is_variable_sized (var))
14302 : {
14303 4 : tree pvar = DECL_VALUE_EXPR (var);
14304 4 : gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
14305 4 : pvar = TREE_OPERAND (pvar, 0);
14306 4 : gcc_assert (DECL_P (pvar));
14307 4 : tree new_var = lookup_decl (pvar, ctx);
14308 4 : x = build_receiver_ref (var, false, ctx);
14309 4 : gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
14310 4 : gimple_seq_add_stmt (&new_body,
14311 4 : gimple_build_assign (new_var, x));
14312 : }
14313 137 : else if (allocate_ptr)
14314 : {
14315 19 : x = build_receiver_ref (var, true, ctx);
14316 19 : new_var = unshare_expr (new_var);
14317 19 : x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
14318 19 : gimplify_and_add (x, &new_body);
14319 : }
14320 : break;
14321 226 : case OMP_CLAUSE_PRIVATE:
14322 226 : if (is_gimple_omp_oacc (ctx->stmt))
14323 : break;
14324 146 : var = OMP_CLAUSE_DECL (c);
14325 146 : new_var = lookup_decl (var, ctx);
14326 146 : allocate_ptr = alloc_map.get (new_var);
14327 146 : by_ref = omp_privatize_by_reference (var);
14328 146 : if (allocate_ptr)
14329 : {
14330 55 : if (is_variable_sized (var, by_ref))
14331 : /* Handle this in the next pass when the size is
14332 : available. */
14333 : break;
14334 :
14335 43 : gimple_seq *allocate_seq = alloc_seq_map.get (new_var);
14336 43 : gcc_assert (allocate_seq);
14337 43 : gimple_seq_add_seq (&new_body, *allocate_seq);
14338 :
14339 43 : if (!by_ref)
14340 42 : new_var = build_simple_mem_ref (*allocate_ptr);
14341 : }
14342 133 : if (by_ref)
14343 : {
14344 12 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
14345 12 : if (!allocate_ptr)
14346 : {
14347 11 : x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
14348 11 : if (TREE_CONSTANT (x))
14349 : {
14350 3 : x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
14351 : get_name (var));
14352 3 : gimple_add_tmp_var (x);
14353 3 : TREE_ADDRESSABLE (x) = 1;
14354 3 : x = build_fold_addr_expr_loc (clause_loc, x);
14355 : }
14356 : else
14357 : break;
14358 :
14359 3 : x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
14360 3 : gimplify_expr (&x, &new_body, NULL, is_gimple_val,
14361 : fb_rvalue);
14362 : }
14363 : else
14364 1 : x = *allocate_ptr;
14365 :
14366 4 : gimple_seq_add_stmt (&new_body,
14367 4 : gimple_build_assign (new_var, x));
14368 : }
14369 : break;
14370 2430 : case OMP_CLAUSE_USE_DEVICE_PTR:
14371 2430 : case OMP_CLAUSE_USE_DEVICE_ADDR:
14372 2430 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
14373 2430 : case OMP_CLAUSE_IS_DEVICE_PTR:
14374 2430 : gimple_seq assign_body;
14375 2430 : bool is_array_data;
14376 2430 : bool do_optional_check;
14377 2430 : assign_body = NULL;
14378 2430 : do_optional_check = false;
14379 2430 : var = OMP_CLAUSE_DECL (c);
14380 2430 : is_array_data = lang_hooks.decls.omp_array_data (var, true) != NULL;
14381 2430 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR && is_array_data)
14382 19 : goto omp_firstprivatize_data_region;
14383 :
14384 2411 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IS_DEVICE_PTR
14385 2411 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR)
14386 4108 : x = build_sender_ref (is_array_data
14387 601 : ? (splay_tree_key) &DECL_NAME (var)
14388 1453 : : (splay_tree_key) &DECL_UID (var), ctx);
14389 : else
14390 : {
14391 357 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
14392 : {
14393 233 : while (TREE_CODE (var) == INDIRECT_REF
14394 233 : || TREE_CODE (var) == ARRAY_REF)
14395 17 : var = TREE_OPERAND (var, 0);
14396 : }
14397 357 : x = build_receiver_ref (var, false, ctx);
14398 : }
14399 :
14400 2411 : if (is_array_data)
14401 : {
14402 601 : bool is_ref = omp_privatize_by_reference (var);
14403 601 : do_optional_check = true;
14404 : /* First, we copy the descriptor data from the host; then
14405 : we update its data to point to the target address. */
14406 601 : new_var = lookup_decl (var, ctx);
14407 601 : new_var = DECL_VALUE_EXPR (new_var);
14408 601 : tree v = new_var;
14409 601 : tree v2 = var;
14410 601 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR
14411 601 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_ADDR)
14412 601 : v2 = maybe_lookup_decl_in_outer_ctx (var, ctx);
14413 :
14414 601 : if (is_ref)
14415 : {
14416 396 : v2 = build_fold_indirect_ref (v2);
14417 396 : v = create_tmp_var_raw (TREE_TYPE (v2), get_name (var));
14418 396 : gimple_add_tmp_var (v);
14419 396 : TREE_ADDRESSABLE (v) = 1;
14420 396 : gimplify_assign (v, v2, &assign_body);
14421 396 : tree rhs = build_fold_addr_expr (v);
14422 396 : gimple_seq_add_stmt (&assign_body,
14423 396 : gimple_build_assign (new_var, rhs));
14424 : }
14425 : else
14426 205 : gimplify_assign (new_var, v2, &assign_body);
14427 :
14428 601 : v2 = lang_hooks.decls.omp_array_data (unshare_expr (v), false);
14429 601 : gcc_assert (v2);
14430 601 : gimplify_expr (&x, &assign_body, NULL, is_gimple_val, fb_rvalue);
14431 1202 : gimple_seq_add_stmt (&assign_body,
14432 601 : gimple_build_assign (v2, x));
14433 : }
14434 1810 : else if (is_variable_sized (var))
14435 : {
14436 12 : tree pvar = DECL_VALUE_EXPR (var);
14437 12 : gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
14438 12 : pvar = TREE_OPERAND (pvar, 0);
14439 12 : gcc_assert (DECL_P (pvar));
14440 12 : new_var = lookup_decl (pvar, ctx);
14441 12 : gimplify_expr (&x, &assign_body, NULL, is_gimple_val, fb_rvalue);
14442 24 : gimple_seq_add_stmt (&assign_body,
14443 12 : gimple_build_assign (new_var, x));
14444 : }
14445 1798 : else if (((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_ADDR
14446 536 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
14447 1476 : && !omp_privatize_by_reference (var)
14448 504 : && !omp_is_allocatable_or_ptr (var))
14449 3231 : || TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
14450 : {
14451 389 : new_var = lookup_decl (var, ctx);
14452 389 : new_var = DECL_VALUE_EXPR (new_var);
14453 389 : gcc_assert (TREE_CODE (new_var) == MEM_REF);
14454 389 : new_var = TREE_OPERAND (new_var, 0);
14455 389 : gcc_assert (DECL_P (new_var));
14456 389 : gimplify_expr (&x, &assign_body, NULL, is_gimple_val, fb_rvalue);
14457 778 : gimple_seq_add_stmt (&assign_body,
14458 389 : gimple_build_assign (new_var, x));
14459 : }
14460 : else
14461 : {
14462 1409 : tree type = TREE_TYPE (var);
14463 1409 : new_var = lookup_decl (var, ctx);
14464 1409 : if (omp_privatize_by_reference (var))
14465 : {
14466 1039 : type = TREE_TYPE (type);
14467 1039 : if (POINTER_TYPE_P (type)
14468 1039 : && TREE_CODE (type) != ARRAY_TYPE
14469 1398 : && ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_USE_DEVICE_ADDR
14470 36 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR)
14471 331 : || (omp_privatize_by_reference (var)
14472 331 : && omp_is_allocatable_or_ptr (var))))
14473 : {
14474 357 : tree v = create_tmp_var_raw (type, get_name (var));
14475 357 : gimple_add_tmp_var (v);
14476 357 : TREE_ADDRESSABLE (v) = 1;
14477 357 : x = fold_convert (type, x);
14478 357 : gimplify_expr (&x, &assign_body, NULL, is_gimple_val,
14479 : fb_rvalue);
14480 357 : gimple_seq_add_stmt (&assign_body,
14481 357 : gimple_build_assign (v, x));
14482 357 : x = build_fold_addr_expr (v);
14483 357 : do_optional_check = true;
14484 : }
14485 : }
14486 1409 : new_var = DECL_VALUE_EXPR (new_var);
14487 1409 : x = fold_convert (TREE_TYPE (new_var), x);
14488 1409 : gimplify_expr (&x, &assign_body, NULL, is_gimple_val, fb_rvalue);
14489 1409 : gimple_seq_add_stmt (&assign_body,
14490 1409 : gimple_build_assign (new_var, x));
14491 : }
14492 2411 : tree present;
14493 1002 : present = ((do_optional_check
14494 958 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR
14495 952 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IS_DEVICE_PTR)
14496 2342 : ? omp_check_optional_argument (OMP_CLAUSE_DECL (c), true)
14497 : : NULL_TREE);
14498 2411 : if (present)
14499 : {
14500 480 : tree null_label = create_artificial_label (UNKNOWN_LOCATION);
14501 480 : tree notnull_label = create_artificial_label (UNKNOWN_LOCATION);
14502 480 : tree opt_arg_label = create_artificial_label (UNKNOWN_LOCATION);
14503 480 : glabel *null_glabel = gimple_build_label (null_label);
14504 480 : glabel *notnull_glabel = gimple_build_label (notnull_label);
14505 480 : ggoto *opt_arg_ggoto = gimple_build_goto (opt_arg_label);
14506 480 : gimplify_expr (&x, &new_body, NULL, is_gimple_val,
14507 : fb_rvalue);
14508 480 : gimplify_expr (&present, &new_body, NULL, is_gimple_val,
14509 : fb_rvalue);
14510 480 : gcond *cond = gimple_build_cond_from_tree (present,
14511 : notnull_label,
14512 : null_label);
14513 480 : gimple_seq_add_stmt (&new_body, cond);
14514 480 : gimple_seq_add_stmt (&new_body, null_glabel);
14515 480 : gimplify_assign (new_var, null_pointer_node, &new_body);
14516 480 : gimple_seq_add_stmt (&new_body, opt_arg_ggoto);
14517 480 : gimple_seq_add_stmt (&new_body, notnull_glabel);
14518 480 : gimple_seq_add_seq (&new_body, assign_body);
14519 480 : gimple_seq_add_stmt (&new_body,
14520 480 : gimple_build_label (opt_arg_label));
14521 : }
14522 : else
14523 1931 : gimple_seq_add_seq (&new_body, assign_body);
14524 : break;
14525 : }
14526 : /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
14527 : so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
14528 : are already handled. Similarly OMP_CLAUSE_PRIVATE for VLAs
14529 : or references to VLAs. */
14530 141038 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
14531 115830 : switch (OMP_CLAUSE_CODE (c))
14532 : {
14533 : tree var, new_var, *allocate_ptr;
14534 : default:
14535 100575 : break;
14536 63520 : case OMP_CLAUSE_MAP:
14537 63520 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
14538 63520 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
14539 : {
14540 3664 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
14541 3664 : poly_int64 offset = 0;
14542 3664 : gcc_assert (prev);
14543 3664 : var = OMP_CLAUSE_DECL (c);
14544 3664 : if (DECL_P (var)
14545 3664 : && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
14546 1125 : && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
14547 : ctx))
14548 3762 : && varpool_node::get_create (var)->offloadable)
14549 : break;
14550 3662 : if (TREE_CODE (var) == INDIRECT_REF
14551 3662 : && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
14552 0 : var = TREE_OPERAND (var, 0);
14553 3662 : if (TREE_CODE (var) == COMPONENT_REF)
14554 : {
14555 0 : var = get_addr_base_and_unit_offset (var, &offset);
14556 0 : gcc_assert (var != NULL_TREE && DECL_P (var));
14557 : }
14558 3662 : else if (DECL_SIZE (var)
14559 3662 : && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
14560 : {
14561 710 : tree var2 = DECL_VALUE_EXPR (var);
14562 710 : gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
14563 710 : var2 = TREE_OPERAND (var2, 0);
14564 710 : gcc_assert (DECL_P (var2));
14565 : var = var2;
14566 : }
14567 3662 : tree new_var = lookup_decl (var, ctx), x;
14568 3662 : tree type = TREE_TYPE (new_var);
14569 3662 : bool is_ref;
14570 3662 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
14571 3662 : && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
14572 : == COMPONENT_REF))
14573 : {
14574 0 : type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
14575 0 : is_ref = true;
14576 0 : new_var = build2 (MEM_REF, type,
14577 : build_fold_addr_expr (new_var),
14578 : build_int_cst (build_pointer_type (type),
14579 : offset));
14580 : }
14581 3662 : else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
14582 : {
14583 0 : type = TREE_TYPE (OMP_CLAUSE_DECL (c));
14584 0 : is_ref = TREE_CODE (type) == REFERENCE_TYPE;
14585 0 : new_var = build2 (MEM_REF, type,
14586 : build_fold_addr_expr (new_var),
14587 : build_int_cst (build_pointer_type (type),
14588 : offset));
14589 : }
14590 : else
14591 3662 : is_ref = omp_privatize_by_reference (var);
14592 3662 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
14593 : is_ref = false;
14594 6695 : bool ref_to_array = false;
14595 6695 : bool ref_to_ptr = false;
14596 3233 : if (is_ref)
14597 : {
14598 200 : type = TREE_TYPE (type);
14599 200 : if (TREE_CODE (type) == ARRAY_TYPE)
14600 : {
14601 194 : type = build_pointer_type (type);
14602 194 : ref_to_array = true;
14603 : }
14604 : }
14605 3462 : else if (TREE_CODE (type) == ARRAY_TYPE)
14606 : {
14607 413 : tree decl2 = DECL_VALUE_EXPR (new_var);
14608 413 : gcc_assert (TREE_CODE (decl2) == MEM_REF);
14609 413 : decl2 = TREE_OPERAND (decl2, 0);
14610 413 : gcc_assert (DECL_P (decl2));
14611 413 : new_var = decl2;
14612 413 : type = TREE_TYPE (new_var);
14613 : }
14614 3049 : else if (TREE_CODE (type) == REFERENCE_TYPE
14615 3049 : && TREE_CODE (TREE_TYPE (type)) == POINTER_TYPE)
14616 : {
14617 156 : type = TREE_TYPE (type);
14618 156 : ref_to_ptr = true;
14619 : }
14620 3662 : x = build_receiver_ref (prev, false, ctx);
14621 3662 : x = fold_convert_loc (clause_loc, type, x);
14622 3662 : if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
14623 : {
14624 762 : tree bias = OMP_CLAUSE_SIZE (c);
14625 762 : if (DECL_P (bias))
14626 364 : bias = lookup_decl (bias, ctx);
14627 762 : bias = fold_convert_loc (clause_loc, sizetype, bias);
14628 762 : bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
14629 : bias);
14630 762 : x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
14631 762 : TREE_TYPE (x), x, bias);
14632 : }
14633 3662 : if (ref_to_array)
14634 194 : x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
14635 3662 : gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
14636 3662 : if ((is_ref && !ref_to_array)
14637 3656 : || ref_to_ptr)
14638 : {
14639 162 : tree t = create_tmp_var_raw (type, get_name (var));
14640 162 : gimple_add_tmp_var (t);
14641 162 : TREE_ADDRESSABLE (t) = 1;
14642 162 : gimple_seq_add_stmt (&new_body,
14643 162 : gimple_build_assign (t, x));
14644 162 : x = build_fold_addr_expr_loc (clause_loc, t);
14645 : }
14646 3662 : gimple_seq_add_stmt (&new_body,
14647 3662 : gimple_build_assign (new_var, x));
14648 3662 : prev = NULL_TREE;
14649 : }
14650 59856 : else if (OMP_CLAUSE_CHAIN (c)
14651 43250 : && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
14652 : == OMP_CLAUSE_MAP
14653 97677 : && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
14654 : == GOMP_MAP_FIRSTPRIVATE_POINTER
14655 34586 : || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
14656 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
14657 : prev = c;
14658 : break;
14659 226 : case OMP_CLAUSE_PRIVATE:
14660 226 : var = OMP_CLAUSE_DECL (c);
14661 226 : by_ref = omp_privatize_by_reference (var);
14662 226 : new_var = lookup_decl (var, ctx);
14663 226 : allocate_ptr = alloc_map.get (new_var);
14664 226 : if (is_variable_sized (var, by_ref)
14665 226 : || (!allocate_ptr && by_ref && !is_gimple_omp_oacc (ctx->stmt)))
14666 : {
14667 24 : if (allocate_ptr)
14668 : {
14669 12 : gimple_seq *allocate_seq = alloc_seq_map.get (new_var);
14670 12 : gcc_assert (allocate_seq);
14671 12 : gimple_seq_add_seq (&new_body, *allocate_seq);
14672 : }
14673 24 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
14674 24 : tree pvar = var;
14675 24 : if (!by_ref)
14676 : {
14677 3 : pvar = DECL_VALUE_EXPR (var);
14678 3 : gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
14679 3 : pvar = TREE_OPERAND (pvar, 0);
14680 : }
14681 24 : gcc_assert (DECL_P (pvar));
14682 24 : tree new_pvar = lookup_decl (pvar, ctx);
14683 24 : tree x;
14684 24 : if (!allocate_ptr)
14685 : {
14686 12 : tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
14687 12 : tree ty = TREE_TYPE (new_var);
14688 12 : if (by_ref)
14689 11 : ty = TREE_TYPE (ty);
14690 12 : x = TYPE_SIZE_UNIT (ty);
14691 12 : if (TREE_CONSTANT (x))
14692 : break;
14693 9 : tree al = size_int (TYPE_ALIGN (ty));
14694 9 : x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
14695 9 : x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
14696 : }
14697 : else
14698 12 : x = *allocate_ptr;
14699 21 : gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
14700 21 : gimple_seq_add_stmt (&new_body,
14701 21 : gimple_build_assign (new_pvar, x));
14702 : }
14703 : break;
14704 15275 : case OMP_CLAUSE_FIRSTPRIVATE:
14705 15275 : var = OMP_CLAUSE_DECL (c);
14706 15275 : by_ref = omp_privatize_by_reference (var);
14707 15275 : if (is_variable_sized (var, by_ref))
14708 : {
14709 35 : tree new_var = lookup_decl (var, ctx);
14710 35 : tree *allocate_ptr = alloc_map.get (new_var);
14711 35 : if (!allocate_ptr)
14712 : break;
14713 15 : gimple_seq *allocate_seq = alloc_seq_map.get (new_var);
14714 15 : gcc_assert (allocate_seq);
14715 15 : gimple_seq_add_seq (&new_body, *allocate_seq);
14716 :
14717 15 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
14718 15 : tree pvar = var;
14719 15 : if (!by_ref)
14720 : {
14721 2 : pvar = DECL_VALUE_EXPR (var);
14722 2 : gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
14723 2 : pvar = TREE_OPERAND (pvar, 0);
14724 : }
14725 15 : gcc_assert (DECL_P (pvar));
14726 15 : tree new_pvar = lookup_decl (pvar, ctx);
14727 15 : tree x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar),
14728 15 : *allocate_ptr);
14729 15 : gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
14730 15 : gimple_seq_add_stmt (&new_body,
14731 15 : gimple_build_assign (new_pvar, x));
14732 :
14733 15 : x = build_receiver_ref (var, true, ctx);
14734 15 : new_var = unshare_expr (new_var);
14735 15 : if (by_ref)
14736 13 : new_var = build_fold_indirect_ref (new_var);
14737 15 : x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
14738 15 : gimplify_and_add (x, &new_body);
14739 : }
14740 : }
14741 :
14742 25208 : gimple_seq fork_seq = NULL;
14743 25208 : gimple_seq join_seq = NULL;
14744 :
14745 25208 : if (offloaded && is_gimple_omp_oacc (ctx->stmt))
14746 : {
14747 : /* If there are reductions on the offloaded region itself, treat
14748 : them as a dummy GANG loop. */
14749 9395 : tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
14750 :
14751 9395 : gcall *private_marker = lower_oacc_private_marker (ctx);
14752 :
14753 9395 : if (private_marker)
14754 30 : gimple_call_set_arg (private_marker, 2, level);
14755 :
14756 9395 : lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
14757 : false, NULL, private_marker, NULL, &fork_seq,
14758 : &join_seq, ctx);
14759 : }
14760 :
14761 25208 : gimple_seq_add_seq (&new_body, fork_seq);
14762 25208 : gimple_seq_add_seq (&new_body, tgt_body);
14763 25208 : gimple_seq_add_seq (&new_body, join_seq);
14764 25208 : gimple_seq_add_seq (&new_body, alloc_dlist);
14765 :
14766 25208 : if (offloaded)
14767 : {
14768 21187 : new_body = maybe_catch_exception (new_body);
14769 21187 : gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
14770 : }
14771 25208 : gimple_omp_set_body (stmt, new_body);
14772 : }
14773 :
14774 37147 : gsi_insert_seq_before (gsi_p, gimple_omp_target_iterator_loops (stmt),
14775 : GSI_SAME_STMT);
14776 37147 : gimple_omp_target_set_iterator_loops (stmt, NULL);
14777 58334 : bind = gimple_build_bind (NULL, NULL,
14778 21187 : tgt_bind ? gimple_bind_block (tgt_bind)
14779 : : NULL_TREE);
14780 73902 : gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
14781 37147 : gimple_bind_add_seq (bind, ilist);
14782 37147 : gimple_bind_add_stmt (bind, stmt);
14783 37147 : gimple_bind_add_seq (bind, olist);
14784 :
14785 37147 : pop_gimplify_context (NULL);
14786 :
14787 37147 : if (dep_bind)
14788 : {
14789 392 : gimple_bind_add_seq (dep_bind, dep_ilist);
14790 392 : gimple_bind_add_stmt (dep_bind, bind);
14791 392 : gimple_bind_add_seq (dep_bind, dep_olist);
14792 392 : pop_gimplify_context (dep_bind);
14793 : }
14794 37147 : }
14795 :
14796 : /* Generate code to implement the action-clauses (destroy, init, use) of an
14797 : OpenMP interop construct. */
14798 :
14799 : static void
14800 492 : lower_omp_interop_action_clauses (gimple_seq *seq, vec<tree> &objs,
14801 : vec<tree> *interop_types = NULL,
14802 : vec<tree> *prefer_types = NULL)
14803 : {
14804 492 : if (objs.length () == 0)
14805 229 : return;
14806 :
14807 263 : enum omp_clause_code action = OMP_CLAUSE_CODE (objs[0]);
14808 263 : if (action == OMP_CLAUSE_INIT)
14809 402 : gcc_checking_assert (objs.length () == interop_types->length ()
14810 : && objs.length () == prefer_types->length ());
14811 : else
14812 129 : gcc_assert (prefer_types == NULL && interop_types == NULL);
14813 :
14814 263 : tree ret_objs = NULL_TREE, ret_interop_types = NULL_TREE,
14815 263 : ret_prefer_types = NULL_TREE;
14816 :
14817 : /* Build an array of interop objects. */
14818 :
14819 263 : tree type_obj_pref = build_array_type_nelts (ptr_type_node, objs.length ());
14820 263 : ret_objs = create_tmp_var (type_obj_pref, "interopobjs");
14821 :
14822 263 : bool have_pref_type = false;
14823 263 : if (action == OMP_CLAUSE_INIT)
14824 : {
14825 592 : for (tree pref_type : prefer_types)
14826 260 : if (pref_type != NULL_TREE)
14827 : {
14828 : have_pref_type = true;
14829 : break;
14830 : }
14831 134 : tree type_tgtsync
14832 134 : = build_array_type_nelts (integer_type_node, objs.length ());
14833 134 : ret_interop_types = create_tmp_var (type_tgtsync, "tgt_tgtsync");
14834 134 : if (have_pref_type)
14835 70 : ret_prefer_types = create_tmp_var (type_obj_pref, "pref_type");
14836 : else
14837 : {
14838 64 : ret_prefer_types = null_pointer_node;
14839 64 : prefer_types->truncate (0);
14840 : }
14841 : }
14842 :
14843 856 : for (size_t i = 0; !objs.is_empty (); i++)
14844 : {
14845 593 : tree offset = build_int_cst (integer_type_node, i);
14846 593 : tree init = build4 (ARRAY_REF, ptr_type_node, ret_objs, offset, NULL_TREE,
14847 : NULL_TREE);
14848 593 : tree obj = OMP_CLAUSE_DECL (objs.pop ());
14849 593 : if (TREE_CODE (TREE_TYPE (obj)) == REFERENCE_TYPE)
14850 6 : obj = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (obj)), obj);
14851 593 : if (action != OMP_CLAUSE_USE
14852 593 : && TREE_CODE (TREE_TYPE (obj)) != POINTER_TYPE)
14853 : /* For modifying actions, we need a pointer. */
14854 483 : obj = build_fold_addr_expr (obj);
14855 110 : else if (action == OMP_CLAUSE_USE
14856 110 : && TREE_CODE (TREE_TYPE (obj)) == POINTER_TYPE)
14857 : /* For use action, we need the value. */
14858 2 : obj = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (obj)), obj);
14859 593 : init = build2 (MODIFY_EXPR, ptr_type_node, init,
14860 : fold_convert (ptr_type_node, obj));
14861 593 : gimplify_and_add (init, seq);
14862 :
14863 593 : if (action == OMP_CLAUSE_INIT)
14864 : {
14865 384 : init = build4 (ARRAY_REF, integer_type_node, ret_interop_types,
14866 : offset, NULL_TREE, NULL_TREE);
14867 384 : init = build2 (MODIFY_EXPR, integer_type_node, init,
14868 384 : interop_types->pop ());
14869 384 : gimplify_and_add (init, seq);
14870 :
14871 384 : if (have_pref_type)
14872 : {
14873 194 : tree prefer_type = prefer_types->pop ();
14874 194 : tree pref = (prefer_type == NULL_TREE
14875 194 : ? null_pointer_node
14876 194 : : build_fold_addr_expr (prefer_type));
14877 194 : init = build4 (ARRAY_REF, ptr_type_node, ret_prefer_types, offset,
14878 : NULL_TREE, NULL_TREE);
14879 194 : init = build2 (MODIFY_EXPR, ptr_type_node, init, pref);
14880 194 : gimplify_and_add (init, seq);
14881 : }
14882 : }
14883 : }
14884 263 : if (action == OMP_CLAUSE_INIT)
14885 : {
14886 134 : if (have_pref_type)
14887 70 : ret_prefer_types = build_fold_addr_expr (ret_prefer_types);
14888 134 : ret_interop_types = build_fold_addr_expr (ret_interop_types);
14889 : }
14890 263 : ret_objs = build_fold_addr_expr (ret_objs);
14891 :
14892 660 : gcc_assert (objs.is_empty ()
14893 : && (!interop_types || interop_types->is_empty ())
14894 : && (!prefer_types || prefer_types->is_empty ()));
14895 :
14896 263 : objs.safe_push (ret_objs);
14897 263 : if (action == OMP_CLAUSE_INIT)
14898 : {
14899 134 : interop_types->safe_push (ret_interop_types);
14900 134 : prefer_types->safe_push (ret_prefer_types);
14901 : }
14902 : }
14903 :
14904 : /* Lower code for an OpenMP interop directive. */
14905 :
14906 : static void
14907 164 : lower_omp_interop (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14908 : {
14909 164 : push_gimplify_context ();
14910 :
14911 164 : tree block = make_node (BLOCK);
14912 164 : gbind *bind = gimple_build_bind (NULL, NULL, block);
14913 164 : gimple_seq bind_body = NULL;
14914 :
14915 : /* Emit call to GOMP_interop:
14916 : void
14917 : GOMP_interop (int device_num, int n_init, omp_interop_t **init,
14918 : const void *target_targetsync, const void *prefer_type,
14919 : int n_use, omp_interop_t *use, int n_destroy,
14920 : omp_interop_t **destroy, unsigned int flags,
14921 : void **depend) */
14922 :
14923 164 : tree flags = NULL_TREE;
14924 164 : tree depend = null_pointer_node;
14925 164 : tree device_num = NULL_TREE;
14926 :
14927 164 : auto_vec<tree> init_objs, use_objs, destroy_objs, prefer_type,
14928 164 : target_targetsync;
14929 164 : gimple_seq dep_ilist = NULL, dep_olist = NULL;
14930 164 : tree clauses = gimple_omp_interop_clauses (gsi_stmt (*gsi_p));
14931 868 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
14932 : {
14933 704 : switch (OMP_CLAUSE_CODE (c))
14934 : {
14935 384 : case OMP_CLAUSE_INIT:
14936 384 : {
14937 384 : init_objs.safe_push (c);
14938 384 : int target_targetsync_bits = 0;
14939 384 : if (OMP_CLAUSE_INIT_TARGET (c))
14940 229 : target_targetsync_bits |= GOMP_INTEROP_TARGET;
14941 384 : if (OMP_CLAUSE_INIT_TARGETSYNC (c))
14942 204 : target_targetsync_bits |= GOMP_INTEROP_TARGETSYNC;
14943 384 : tree t = build_int_cst (integer_type_node, target_targetsync_bits);
14944 384 : target_targetsync.safe_push (t);
14945 384 : prefer_type.safe_push (OMP_CLAUSE_INIT_PREFER_TYPE (c));
14946 : }
14947 384 : break;
14948 106 : case OMP_CLAUSE_USE:
14949 106 : use_objs.safe_push (c);
14950 106 : break;
14951 103 : case OMP_CLAUSE_DESTROY:
14952 103 : destroy_objs.safe_push (c);
14953 103 : break;
14954 50 : case OMP_CLAUSE_NOWAIT:
14955 50 : flags = build_int_cst (integer_type_node, GOMP_INTEROP_FLAG_NOWAIT);
14956 50 : break;
14957 35 : case OMP_CLAUSE_DEPEND:
14958 35 : {
14959 35 : tree *cp = gimple_omp_interop_clauses_ptr (gsi_stmt (*gsi_p));
14960 35 : lower_depend_clauses (cp, &dep_ilist, &dep_olist);
14961 35 : depend = OMP_CLAUSE_DECL (*cp);
14962 : }
14963 35 : break;
14964 26 : case OMP_CLAUSE_DEVICE:
14965 26 : device_num = OMP_CLAUSE_DEVICE_ID (c);
14966 26 : break;
14967 0 : default:
14968 0 : gcc_unreachable ();
14969 : }
14970 : }
14971 :
14972 164 : if (flags == NULL_TREE)
14973 114 : flags = build_int_cst (integer_type_node, 0);
14974 :
14975 164 : if (device_num == NULL_TREE)
14976 138 : device_num = build_int_cst (integer_type_node, GOMP_DEVICE_DEFAULT_OMP_61);
14977 :
14978 298 : tree n_init = build_int_cst (integer_type_node, init_objs.length ());
14979 234 : tree n_use = build_int_cst (integer_type_node, use_objs.length ());
14980 223 : tree n_destroy = build_int_cst (integer_type_node, destroy_objs.length ());
14981 :
14982 164 : lower_omp_interop_action_clauses (&bind_body, init_objs, &target_targetsync,
14983 : &prefer_type);
14984 164 : lower_omp_interop_action_clauses (&bind_body, use_objs);
14985 164 : lower_omp_interop_action_clauses (&bind_body, destroy_objs);
14986 :
14987 164 : gimple_seq_add_seq (&bind_body, dep_ilist);
14988 164 : tree fn = builtin_decl_explicit (BUILT_IN_GOMP_INTEROP);
14989 298 : tree init_arg = init_objs.length () ? init_objs.pop () : null_pointer_node;
14990 164 : tree target_targetsync_arg = target_targetsync.length ()
14991 134 : ? target_targetsync.pop ()
14992 164 : : null_pointer_node;
14993 164 : tree prefer_type_arg
14994 298 : = prefer_type.length () ? prefer_type.pop () : null_pointer_node;
14995 234 : tree use_arg = use_objs.length () ? use_objs.pop () : null_pointer_node;
14996 164 : tree destroy_arg
14997 223 : = destroy_objs.length () ? destroy_objs.pop () : null_pointer_node;
14998 164 : gcall *call
14999 164 : = gimple_build_call (fn, 11, device_num, n_init, init_arg,
15000 : target_targetsync_arg, prefer_type_arg, n_use, use_arg,
15001 : n_destroy, destroy_arg, flags, depend);
15002 164 : gimple_seq_add_stmt (&bind_body, call);
15003 164 : gimple_seq_add_seq (&bind_body, dep_olist);
15004 :
15005 164 : gsi_replace (gsi_p, bind, true);
15006 164 : gimple_bind_set_body (bind, bind_body);
15007 164 : pop_gimplify_context (bind);
15008 164 : gimple_bind_append_vars (bind, ctx->block_vars);
15009 164 : BLOCK_VARS (block) = ctx->block_vars;
15010 164 : }
15011 :
15012 : /* Expand code for an OpenMP teams directive. */
15013 :
15014 : static void
15015 5920 : lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15016 : {
15017 5920 : gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
15018 5920 : push_gimplify_context ();
15019 :
15020 5920 : tree block = make_node (BLOCK);
15021 5920 : gbind *bind = gimple_build_bind (NULL, NULL, block);
15022 5920 : gsi_replace (gsi_p, bind, true);
15023 5920 : gimple_seq bind_body = NULL;
15024 5920 : gimple_seq dlist = NULL;
15025 5920 : gimple_seq olist = NULL;
15026 :
15027 5920 : tree num_teams = omp_find_clause (gimple_omp_teams_clauses (teams_stmt),
15028 5920 : OMP_CLAUSE_NUM_TEAMS);
15029 5920 : tree num_teams_lower = NULL_TREE;
15030 5920 : if (num_teams == NULL_TREE)
15031 5300 : num_teams = build_int_cst (unsigned_type_node, 0);
15032 : else
15033 : {
15034 620 : num_teams_lower = OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (num_teams);
15035 620 : if (num_teams_lower)
15036 : {
15037 148 : num_teams_lower = fold_convert (unsigned_type_node, num_teams_lower);
15038 148 : gimplify_expr (&num_teams_lower, &bind_body, NULL, is_gimple_val,
15039 : fb_rvalue);
15040 : }
15041 620 : num_teams = OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (num_teams);
15042 620 : num_teams = fold_convert (unsigned_type_node, num_teams);
15043 620 : gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
15044 : }
15045 5920 : if (num_teams_lower == NULL_TREE)
15046 5772 : num_teams_lower = num_teams;
15047 5920 : tree thread_limit = omp_find_clause (gimple_omp_teams_clauses (teams_stmt),
15048 5920 : OMP_CLAUSE_THREAD_LIMIT);
15049 5920 : if (thread_limit == NULL_TREE)
15050 5446 : thread_limit = build_int_cst (unsigned_type_node, 0);
15051 : else
15052 : {
15053 474 : thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
15054 474 : thread_limit = fold_convert (unsigned_type_node, thread_limit);
15055 474 : gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
15056 : fb_rvalue);
15057 : }
15058 5920 : location_t loc = gimple_location (teams_stmt);
15059 5920 : tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS4);
15060 5920 : tree rettype = TREE_TYPE (TREE_TYPE (decl));
15061 5920 : tree first = create_tmp_var (rettype);
15062 5920 : gimple_seq_add_stmt (&bind_body,
15063 5920 : gimple_build_assign (first, build_one_cst (rettype)));
15064 5920 : tree llabel = create_artificial_label (loc);
15065 5920 : gimple_seq_add_stmt (&bind_body, gimple_build_label (llabel));
15066 5920 : gimple *call
15067 5920 : = gimple_build_call (decl, 4, num_teams_lower, num_teams, thread_limit,
15068 : first);
15069 5920 : gimple_set_location (call, loc);
15070 5920 : tree temp = create_tmp_var (rettype);
15071 5920 : gimple_call_set_lhs (call, temp);
15072 5920 : gimple_seq_add_stmt (&bind_body, call);
15073 :
15074 5920 : tree tlabel = create_artificial_label (loc);
15075 5920 : tree flabel = create_artificial_label (loc);
15076 5920 : gimple *cond = gimple_build_cond (NE_EXPR, temp, build_zero_cst (rettype),
15077 : tlabel, flabel);
15078 5920 : gimple_seq_add_stmt (&bind_body, cond);
15079 5920 : gimple_seq_add_stmt (&bind_body, gimple_build_label (tlabel));
15080 5920 : gimple_seq_add_stmt (&bind_body,
15081 5920 : gimple_build_assign (first, build_zero_cst (rettype)));
15082 :
15083 5920 : lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
15084 : &bind_body, &dlist, ctx, NULL);
15085 5920 : lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
15086 5920 : lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist,
15087 : NULL, ctx);
15088 5920 : gimple_seq_add_stmt (&bind_body, teams_stmt);
15089 :
15090 5920 : gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
15091 5920 : gimple_omp_set_body (teams_stmt, NULL);
15092 5920 : gimple_seq_add_seq (&bind_body, olist);
15093 5920 : gimple_seq_add_seq (&bind_body, dlist);
15094 5920 : gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
15095 5920 : gimple_seq_add_stmt (&bind_body, gimple_build_goto (llabel));
15096 5920 : gimple_seq_add_stmt (&bind_body, gimple_build_label (flabel));
15097 5920 : gimple_bind_set_body (bind, bind_body);
15098 :
15099 5920 : pop_gimplify_context (bind);
15100 :
15101 5920 : gimple_bind_append_vars (bind, ctx->block_vars);
15102 5920 : BLOCK_VARS (block) = ctx->block_vars;
15103 5920 : if (BLOCK_VARS (block))
15104 689 : TREE_USED (block) = 1;
15105 5920 : }
15106 :
15107 : /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
15108 : regimplified. If DATA is non-NULL, lower_omp_1 is outside
15109 : of OMP context, but with make_addressable_vars set. */
15110 :
15111 : static tree
15112 3203355 : lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
15113 : void *data)
15114 : {
15115 3203355 : tree t = *tp;
15116 :
15117 : /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
15118 3203355 : if ((VAR_P (t) || TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
15119 1491636 : && data == NULL
15120 1431186 : && DECL_HAS_VALUE_EXPR_P (t))
15121 : return t;
15122 :
15123 3098385 : if (make_addressable_vars
15124 423128 : && DECL_P (t)
15125 3303708 : && bitmap_bit_p (make_addressable_vars, DECL_UID (t)))
15126 : return t;
15127 :
15128 : /* If a global variable has been privatized, TREE_CONSTANT on
15129 : ADDR_EXPR might be wrong. */
15130 3095796 : if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
15131 108230 : recompute_tree_invariant_for_addr_expr (t);
15132 :
15133 3095796 : *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
15134 3095796 : return NULL_TREE;
15135 : }
15136 :
15137 : /* Data to be communicated between lower_omp_regimplify_operands and
15138 : lower_omp_regimplify_operands_p. */
15139 :
15140 : struct lower_omp_regimplify_operands_data
15141 : {
15142 : omp_context *ctx;
15143 : vec<tree> *decls;
15144 : };
15145 :
15146 : /* Helper function for lower_omp_regimplify_operands. Find
15147 : omp_member_access_dummy_var vars and adjust temporarily their
15148 : DECL_VALUE_EXPRs if needed. */
15149 :
15150 : static tree
15151 423655 : lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
15152 : void *data)
15153 : {
15154 423655 : tree t = omp_member_access_dummy_var (*tp);
15155 423655 : if (t)
15156 : {
15157 9 : struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
15158 9 : lower_omp_regimplify_operands_data *ldata
15159 : = (lower_omp_regimplify_operands_data *) wi->info;
15160 9 : tree o = maybe_lookup_decl (t, ldata->ctx);
15161 9 : if (o == NULL_TREE)
15162 5 : o = maybe_lookup_decl_in_outer_ctx (t, ldata->ctx);
15163 9 : if (o != t)
15164 : {
15165 9 : ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
15166 9 : ldata->decls->safe_push (*tp);
15167 9 : tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
15168 9 : SET_DECL_VALUE_EXPR (*tp, v);
15169 : }
15170 : }
15171 423655 : *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
15172 423655 : return NULL_TREE;
15173 : }
15174 :
15175 : /* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
15176 : of omp_member_access_dummy_var vars during regimplification. */
15177 :
15178 : static void
15179 107404 : lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
15180 : gimple_stmt_iterator *gsi_p)
15181 : {
15182 107404 : auto_vec<tree, 10> decls;
15183 107404 : if (ctx)
15184 : {
15185 104882 : struct walk_stmt_info wi;
15186 104882 : memset (&wi, '\0', sizeof (wi));
15187 104882 : struct lower_omp_regimplify_operands_data data;
15188 104882 : data.ctx = ctx;
15189 104882 : data.decls = &decls;
15190 104882 : wi.info = &data;
15191 104882 : walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
15192 : }
15193 107404 : gimple_regimplify_operands (stmt, gsi_p);
15194 322221 : while (!decls.is_empty ())
15195 : {
15196 9 : tree t = decls.pop ();
15197 9 : tree v = decls.pop ();
15198 9 : SET_DECL_VALUE_EXPR (t, v);
15199 : }
15200 107404 : }
15201 :
15202 : static void
15203 2501990 : lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15204 : {
15205 2501990 : gimple *stmt = gsi_stmt (*gsi_p);
15206 2501990 : struct walk_stmt_info wi;
15207 2501990 : gcall *call_stmt;
15208 :
15209 2501990 : if (gimple_has_location (stmt))
15210 2055460 : input_location = gimple_location (stmt);
15211 :
15212 2501990 : if (make_addressable_vars)
15213 154214 : memset (&wi, '\0', sizeof (wi));
15214 :
15215 : /* If we have issued syntax errors, avoid doing any heavy lifting.
15216 : Just replace the OMP directives with a NOP to avoid
15217 : confusing RTL expansion. */
15218 2501990 : if (seen_error () && is_gimple_omp (stmt))
15219 : {
15220 11337 : gsi_replace (gsi_p, gimple_build_nop (), true);
15221 11337 : return;
15222 : }
15223 :
15224 2490653 : switch (gimple_code (stmt))
15225 : {
15226 155454 : case GIMPLE_COND:
15227 155454 : {
15228 155454 : gcond *cond_stmt = as_a <gcond *> (stmt);
15229 88585 : if ((ctx || make_addressable_vars)
15230 159062 : && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
15231 : lower_omp_regimplify_p,
15232 : ctx ? NULL : &wi, NULL)
15233 135399 : || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
15234 : lower_omp_regimplify_p,
15235 : ctx ? NULL : &wi, NULL)))
15236 1247 : lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
15237 : }
15238 : break;
15239 20 : case GIMPLE_CATCH:
15240 20 : lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
15241 20 : break;
15242 0 : case GIMPLE_EH_FILTER:
15243 0 : lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
15244 0 : break;
15245 25908 : case GIMPLE_TRY:
15246 25908 : lower_omp (gimple_try_eval_ptr (stmt), ctx);
15247 25903 : lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
15248 25903 : break;
15249 0 : case GIMPLE_ASSUME:
15250 0 : lower_omp (gimple_assume_body_ptr (stmt), ctx);
15251 0 : break;
15252 5 : case GIMPLE_TRANSACTION:
15253 5 : lower_omp (gimple_transaction_body_ptr (as_a <gtransaction *> (stmt)),
15254 : ctx);
15255 5 : break;
15256 167961 : case GIMPLE_BIND:
15257 167961 : if (ctx && is_gimple_omp_oacc (ctx->stmt))
15258 : {
15259 17785 : tree vars = gimple_bind_vars (as_a <gbind *> (stmt));
15260 17785 : oacc_privatization_scan_decl_chain (ctx, vars);
15261 : }
15262 167961 : lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
15263 167954 : maybe_remove_omp_member_access_dummy_vars (as_a <gbind *> (stmt));
15264 167954 : break;
15265 19953 : case GIMPLE_OMP_PARALLEL:
15266 19953 : case GIMPLE_OMP_TASK:
15267 19953 : ctx = maybe_lookup_ctx (stmt);
15268 19953 : gcc_assert (ctx);
15269 19953 : if (ctx->cancellable)
15270 129 : ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
15271 19953 : lower_omp_taskreg (gsi_p, ctx);
15272 19953 : break;
15273 46859 : case GIMPLE_OMP_FOR:
15274 46859 : ctx = maybe_lookup_ctx (stmt);
15275 46859 : gcc_assert (ctx);
15276 46859 : if (ctx->cancellable)
15277 36 : ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
15278 46859 : lower_omp_for (gsi_p, ctx);
15279 46859 : break;
15280 386 : case GIMPLE_OMP_SECTIONS:
15281 386 : ctx = maybe_lookup_ctx (stmt);
15282 386 : gcc_assert (ctx);
15283 386 : if (ctx->cancellable)
15284 19 : ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
15285 386 : lower_omp_sections (gsi_p, ctx);
15286 386 : break;
15287 145 : case GIMPLE_OMP_SCOPE:
15288 145 : ctx = maybe_lookup_ctx (stmt);
15289 145 : gcc_assert (ctx);
15290 145 : lower_omp_scope (gsi_p, ctx);
15291 145 : break;
15292 659 : case GIMPLE_OMP_DISPATCH:
15293 659 : ctx = maybe_lookup_ctx (stmt);
15294 659 : gcc_assert (ctx);
15295 659 : lower_omp_dispatch (gsi_p, ctx);
15296 659 : break;
15297 164 : case GIMPLE_OMP_INTEROP:
15298 164 : ctx = maybe_lookup_ctx (stmt);
15299 164 : gcc_assert (ctx);
15300 164 : lower_omp_interop (gsi_p, ctx);
15301 164 : break;
15302 1127 : case GIMPLE_OMP_SINGLE:
15303 1127 : ctx = maybe_lookup_ctx (stmt);
15304 1127 : gcc_assert (ctx);
15305 1127 : lower_omp_single (gsi_p, ctx);
15306 1127 : break;
15307 658 : case GIMPLE_OMP_STRUCTURED_BLOCK:
15308 : /* We have already done error checking at this point, so these nodes
15309 : can be completely removed and replaced with their body. */
15310 658 : ctx = maybe_lookup_ctx (stmt);
15311 658 : gcc_assert (ctx);
15312 658 : lower_omp (gimple_omp_body_ptr (stmt), ctx);
15313 658 : gsi_replace_with_seq (gsi_p, gimple_omp_body (stmt), true);
15314 658 : break;
15315 1118 : case GIMPLE_OMP_MASTER:
15316 1118 : case GIMPLE_OMP_MASKED:
15317 1118 : ctx = maybe_lookup_ctx (stmt);
15318 1118 : gcc_assert (ctx);
15319 1118 : lower_omp_master (gsi_p, ctx);
15320 1118 : break;
15321 536 : case GIMPLE_OMP_TASKGROUP:
15322 536 : ctx = maybe_lookup_ctx (stmt);
15323 536 : gcc_assert (ctx);
15324 536 : lower_omp_taskgroup (gsi_p, ctx);
15325 536 : break;
15326 1124 : case GIMPLE_OMP_ORDERED:
15327 1124 : ctx = maybe_lookup_ctx (stmt);
15328 1124 : gcc_assert (ctx);
15329 1124 : lower_omp_ordered (gsi_p, ctx);
15330 1124 : break;
15331 1276 : case GIMPLE_OMP_SCAN:
15332 1276 : ctx = maybe_lookup_ctx (stmt);
15333 1276 : gcc_assert (ctx);
15334 1276 : lower_omp_scan (gsi_p, ctx);
15335 1276 : break;
15336 311 : case GIMPLE_OMP_CRITICAL:
15337 311 : ctx = maybe_lookup_ctx (stmt);
15338 311 : gcc_assert (ctx);
15339 311 : lower_omp_critical (gsi_p, ctx);
15340 311 : break;
15341 2478 : case GIMPLE_OMP_ATOMIC_LOAD:
15342 83 : if ((ctx || make_addressable_vars)
15343 2478 : && walk_tree (gimple_omp_atomic_load_rhs_ptr (
15344 : as_a <gomp_atomic_load *> (stmt)),
15345 : lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
15346 1389 : lower_omp_regimplify_operands (ctx, stmt, gsi_p);
15347 : break;
15348 37147 : case GIMPLE_OMP_TARGET:
15349 37147 : ctx = maybe_lookup_ctx (stmt);
15350 37147 : gcc_assert (ctx);
15351 37147 : lower_omp_target (gsi_p, ctx);
15352 37147 : break;
15353 8438 : case GIMPLE_OMP_TEAMS:
15354 8438 : ctx = maybe_lookup_ctx (stmt);
15355 8438 : gcc_assert (ctx);
15356 8438 : if (gimple_omp_teams_host (as_a <gomp_teams *> (stmt)))
15357 2518 : lower_omp_taskreg (gsi_p, ctx);
15358 : else
15359 5920 : lower_omp_teams (gsi_p, ctx);
15360 : break;
15361 134309 : case GIMPLE_CALL:
15362 134309 : tree fndecl;
15363 134309 : call_stmt = as_a <gcall *> (stmt);
15364 134309 : fndecl = gimple_call_fndecl (call_stmt);
15365 134309 : if (fndecl
15366 134309 : && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
15367 38552 : switch (DECL_FUNCTION_CODE (fndecl))
15368 : {
15369 703 : case BUILT_IN_GOMP_BARRIER:
15370 703 : if (ctx == NULL)
15371 : break;
15372 : /* FALLTHRU */
15373 935 : case BUILT_IN_GOMP_CANCEL:
15374 935 : case BUILT_IN_GOMP_CANCELLATION_POINT:
15375 935 : omp_context *cctx;
15376 935 : cctx = ctx;
15377 935 : if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
15378 43 : cctx = cctx->outer;
15379 935 : gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
15380 935 : if (!cctx->cancellable)
15381 : {
15382 655 : if (DECL_FUNCTION_CODE (fndecl)
15383 : == BUILT_IN_GOMP_CANCELLATION_POINT)
15384 : {
15385 0 : stmt = gimple_build_nop ();
15386 0 : gsi_replace (gsi_p, stmt, false);
15387 : }
15388 : break;
15389 : }
15390 280 : if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
15391 : {
15392 14 : fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
15393 14 : gimple_call_set_fndecl (call_stmt, fndecl);
15394 14 : gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
15395 : }
15396 280 : tree lhs;
15397 280 : lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
15398 280 : gimple_call_set_lhs (call_stmt, lhs);
15399 280 : tree fallthru_label;
15400 280 : fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
15401 280 : gimple *g;
15402 280 : g = gimple_build_label (fallthru_label);
15403 280 : gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
15404 280 : g = gimple_build_cond (NE_EXPR, lhs,
15405 280 : fold_convert (TREE_TYPE (lhs),
15406 : boolean_false_node),
15407 : cctx->cancel_label, fallthru_label);
15408 280 : gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
15409 280 : break;
15410 : default:
15411 : break;
15412 : }
15413 134274 : goto regimplify;
15414 :
15415 : case GIMPLE_ASSIGN:
15416 1452289 : for (omp_context *up = ctx; up; up = up->outer)
15417 : {
15418 683369 : if (gimple_code (up->stmt) == GIMPLE_OMP_ORDERED
15419 : || gimple_code (up->stmt) == GIMPLE_OMP_CRITICAL
15420 : || gimple_code (up->stmt) == GIMPLE_OMP_TASKGROUP
15421 : || gimple_code (up->stmt) == GIMPLE_OMP_SCOPE
15422 : || gimple_code (up->stmt) == GIMPLE_OMP_SECTION
15423 : || gimple_code (up->stmt) == GIMPLE_OMP_SCAN
15424 : || (gimple_code (up->stmt) == GIMPLE_OMP_TARGET
15425 229893 : && (gimple_omp_target_kind (up->stmt)
15426 : == GF_OMP_TARGET_KIND_DATA)))
15427 90715 : continue;
15428 592654 : else if (!up->lastprivate_conditional_map)
15429 : break;
15430 4089 : tree lhs = get_base_address (gimple_assign_lhs (stmt));
15431 4089 : if (TREE_CODE (lhs) == MEM_REF
15432 26 : && DECL_P (TREE_OPERAND (lhs, 0))
15433 4112 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs,
15434 : 0))) == REFERENCE_TYPE)
15435 19 : lhs = TREE_OPERAND (lhs, 0);
15436 4089 : if (DECL_P (lhs))
15437 3046 : if (tree *v = up->lastprivate_conditional_map->get (lhs))
15438 : {
15439 376 : tree clauses;
15440 376 : if (up->combined_into_simd_safelen1)
15441 : {
15442 54 : up = up->outer;
15443 54 : if (gimple_code (up->stmt) == GIMPLE_OMP_SCAN)
15444 3 : up = up->outer;
15445 : }
15446 376 : if (gimple_code (up->stmt) == GIMPLE_OMP_FOR)
15447 292 : clauses = gimple_omp_for_clauses (up->stmt);
15448 : else
15449 84 : clauses = gimple_omp_sections_clauses (up->stmt);
15450 376 : tree c = omp_find_clause (clauses, OMP_CLAUSE__CONDTEMP_);
15451 376 : if (!OMP_CLAUSE__CONDTEMP__ITER (c))
15452 342 : c = omp_find_clause (OMP_CLAUSE_CHAIN (c),
15453 : OMP_CLAUSE__CONDTEMP_);
15454 376 : gcc_assert (OMP_CLAUSE__CONDTEMP__ITER (c));
15455 376 : gimple *g = gimple_build_assign (*v, OMP_CLAUSE_DECL (c));
15456 376 : gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
15457 : }
15458 : }
15459 : /* FALLTHRU */
15460 :
15461 2018926 : default:
15462 2018926 : regimplify:
15463 1065012 : if ((ctx || make_addressable_vars)
15464 2094777 : && walk_gimple_op (stmt, lower_omp_regimplify_p,
15465 : ctx ? NULL : &wi))
15466 : {
15467 : /* Just remove clobbers, this should happen only if we have
15468 : "privatized" local addressable variables in SIMD regions,
15469 : the clobber isn't needed in that case and gimplifying address
15470 : of the ARRAY_REF into a pointer and creating MEM_REF based
15471 : clobber would create worse code than we get with the clobber
15472 : dropped. */
15473 104923 : if (gimple_clobber_p (stmt))
15474 : {
15475 155 : gsi_replace (gsi_p, gimple_build_nop (), true);
15476 155 : break;
15477 : }
15478 104768 : lower_omp_regimplify_operands (ctx, stmt, gsi_p);
15479 : }
15480 : break;
15481 : }
15482 : }
15483 :
15484 : static void
15485 410422 : lower_omp (gimple_seq *body, omp_context *ctx)
15486 : {
15487 410422 : location_t saved_location = input_location;
15488 410422 : gimple_stmt_iterator gsi;
15489 3274672 : for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
15490 2501990 : lower_omp_1 (&gsi, ctx);
15491 : /* During gimplification, we haven't folded statements inside offloading
15492 : or taskreg regions (gimplify.cc:maybe_fold_stmt); do that now. */
15493 410406 : if (target_nesting_level || taskreg_nesting_level)
15494 656469 : for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
15495 443336 : fold_stmt (&gsi);
15496 410406 : input_location = saved_location;
15497 410406 : }
15498 :
15499 : /* Main entry point. */
15500 :
15501 : static unsigned int
15502 3008128 : execute_lower_omp (void)
15503 : {
15504 3008128 : gimple_seq body;
15505 3008128 : int i;
15506 3008128 : omp_context *ctx;
15507 :
15508 : /* This pass always runs, to provide PROP_gimple_lomp.
15509 : But often, there is nothing to do. */
15510 3008128 : if (flag_openacc == 0 && flag_openmp == 0
15511 2953565 : && flag_openmp_simd == 0)
15512 : return 0;
15513 :
15514 56820 : all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
15515 : delete_omp_context);
15516 :
15517 56820 : body = gimple_body (current_function_decl);
15518 :
15519 56820 : scan_omp (&body, NULL);
15520 56820 : gcc_assert (taskreg_nesting_level == 0);
15521 82819 : FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
15522 25999 : finish_taskreg_scan (ctx);
15523 56820 : taskreg_contexts.release ();
15524 :
15525 56820 : if (all_contexts->root)
15526 : {
15527 25785 : if (make_addressable_vars)
15528 622 : push_gimplify_context ();
15529 25785 : lower_omp (&body, NULL);
15530 25781 : if (make_addressable_vars)
15531 622 : pop_gimplify_context (NULL);
15532 : }
15533 :
15534 56816 : if (all_contexts)
15535 : {
15536 56816 : splay_tree_delete (all_contexts);
15537 56816 : all_contexts = NULL;
15538 : }
15539 56816 : BITMAP_FREE (make_addressable_vars);
15540 56816 : BITMAP_FREE (global_nonaddressable_vars);
15541 :
15542 : /* If current function is a method, remove artificial dummy VAR_DECL created
15543 : for non-static data member privatization, they aren't needed for
15544 : debuginfo nor anything else, have been already replaced everywhere in the
15545 : IL and cause problems with LTO. */
15546 56816 : if (DECL_ARGUMENTS (current_function_decl)
15547 32459 : && DECL_ARTIFICIAL (DECL_ARGUMENTS (current_function_decl))
15548 66345 : && (TREE_CODE (TREE_TYPE (DECL_ARGUMENTS (current_function_decl)))
15549 : == POINTER_TYPE))
15550 8967 : remove_member_access_dummy_vars (DECL_INITIAL (current_function_decl));
15551 :
15552 57756 : for (auto task_stmt : task_cpyfns)
15553 480 : finalize_task_copyfn (task_stmt);
15554 56816 : task_cpyfns.release ();
15555 56816 : return 0;
15556 : }
15557 :
15558 : namespace {
15559 :
15560 : const pass_data pass_data_lower_omp =
15561 : {
15562 : GIMPLE_PASS, /* type */
15563 : "omplower", /* name */
15564 : OPTGROUP_OMP, /* optinfo_flags */
15565 : TV_NONE, /* tv_id */
15566 : PROP_gimple_any, /* properties_required */
15567 : PROP_gimple_lomp | PROP_gimple_lomp_dev, /* properties_provided */
15568 : 0, /* properties_destroyed */
15569 : 0, /* todo_flags_start */
15570 : 0, /* todo_flags_finish */
15571 : };
15572 :
15573 : class pass_lower_omp : public gimple_opt_pass
15574 : {
15575 : public:
15576 292371 : pass_lower_omp (gcc::context *ctxt)
15577 584742 : : gimple_opt_pass (pass_data_lower_omp, ctxt)
15578 : {}
15579 :
15580 : /* opt_pass methods: */
15581 3008128 : unsigned int execute (function *) final override
15582 : {
15583 3008128 : return execute_lower_omp ();
15584 : }
15585 :
15586 : }; // class pass_lower_omp
15587 :
15588 : } // anon namespace
15589 :
15590 : gimple_opt_pass *
15591 292371 : make_pass_lower_omp (gcc::context *ctxt)
15592 : {
15593 292371 : return new pass_lower_omp (ctxt);
15594 : }
15595 :
15596 : /* The following is a utility to diagnose structured block violations.
15597 : It is not part of the "omplower" pass, as that's invoked too late. It
15598 : should be invoked by the respective front ends after gimplification. */
15599 :
15600 : static splay_tree all_labels;
15601 :
15602 : /* Check for mismatched contexts and generate an error if needed. Return
15603 : true if an error is detected. */
15604 :
15605 : static bool
15606 559571 : diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
15607 : gimple *branch_ctx, gimple *label_ctx)
15608 : {
15609 559571 : gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
15610 559571 : gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
15611 :
15612 559571 : if (label_ctx == branch_ctx)
15613 : return false;
15614 :
15615 180 : const char* kind = NULL;
15616 :
15617 180 : if (flag_openacc)
15618 : {
15619 7 : if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
15620 16 : || (label_ctx && is_gimple_omp_oacc (label_ctx)))
15621 : {
15622 : gcc_checking_assert (kind == NULL);
15623 : kind = "OpenACC";
15624 : }
15625 : }
15626 : if (kind == NULL)
15627 : {
15628 164 : gcc_checking_assert (flag_openmp || flag_openmp_simd);
15629 : kind = "OpenMP";
15630 : }
15631 :
15632 : /* Previously we kept track of the label's entire context in diagnose_sb_[12]
15633 : so we could traverse it and issue a correct "exit" or "enter" error
15634 : message upon a structured block violation.
15635 :
15636 : We built the context by building a list with tree_cons'ing, but there is
15637 : no easy counterpart in gimple tuples. It seems like far too much work
15638 : for issuing exit/enter error messages. If someone really misses the
15639 : distinct error message... patches welcome. */
15640 :
15641 : #if 0
15642 : /* Try to avoid confusing the user by producing and error message
15643 : with correct "exit" or "enter" verbiage. We prefer "exit"
15644 : unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
15645 : if (branch_ctx == NULL)
15646 : exit_p = false;
15647 : else
15648 : {
15649 : while (label_ctx)
15650 : {
15651 : if (TREE_VALUE (label_ctx) == branch_ctx)
15652 : {
15653 : exit_p = false;
15654 : break;
15655 : }
15656 : label_ctx = TREE_CHAIN (label_ctx);
15657 : }
15658 : }
15659 :
15660 : if (exit_p)
15661 : error ("invalid exit from %s structured block", kind);
15662 : else
15663 : error ("invalid entry to %s structured block", kind);
15664 : #endif
15665 :
15666 : /* If it's obvious we have an invalid entry, be specific about the error. */
15667 180 : if (branch_ctx == NULL)
15668 53 : error ("invalid entry to %s structured block", kind);
15669 : else
15670 : {
15671 : /* Otherwise, be vague and lazy, but efficient. */
15672 127 : error ("invalid branch to/from %s structured block", kind);
15673 : }
15674 :
15675 180 : gsi_replace (gsi_p, gimple_build_nop (), false);
15676 180 : return true;
15677 : }
15678 :
15679 : /* Pass 1: Create a minimal tree of structured blocks, and record
15680 : where each label is found. */
15681 :
15682 : static tree
15683 3342816 : diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
15684 : struct walk_stmt_info *wi)
15685 : {
15686 3342816 : gimple *context = (gimple *) wi->info;
15687 3342816 : gimple *inner_context;
15688 3342816 : gimple *stmt = gsi_stmt (*gsi_p);
15689 :
15690 3342816 : *handled_ops_p = true;
15691 :
15692 3342816 : switch (gimple_code (stmt))
15693 : {
15694 318998 : WALK_SUBSTMTS;
15695 :
15696 83608 : case GIMPLE_OMP_PARALLEL:
15697 83608 : case GIMPLE_OMP_TASK:
15698 83608 : case GIMPLE_OMP_SCOPE:
15699 83608 : case GIMPLE_OMP_SECTIONS:
15700 83608 : case GIMPLE_OMP_SINGLE:
15701 83608 : case GIMPLE_OMP_SECTION:
15702 83608 : case GIMPLE_OMP_STRUCTURED_BLOCK:
15703 83608 : case GIMPLE_OMP_MASTER:
15704 83608 : case GIMPLE_OMP_MASKED:
15705 83608 : case GIMPLE_OMP_ORDERED:
15706 83608 : case GIMPLE_OMP_SCAN:
15707 83608 : case GIMPLE_OMP_CRITICAL:
15708 83608 : case GIMPLE_OMP_TARGET:
15709 83608 : case GIMPLE_OMP_TEAMS:
15710 83608 : case GIMPLE_OMP_TASKGROUP:
15711 : /* The minimal context here is just the current OMP construct. */
15712 83608 : inner_context = stmt;
15713 83608 : wi->info = inner_context;
15714 83608 : walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
15715 83608 : wi->info = context;
15716 83608 : break;
15717 :
15718 52723 : case GIMPLE_OMP_FOR:
15719 52723 : inner_context = stmt;
15720 52723 : wi->info = inner_context;
15721 : /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
15722 : walk them. */
15723 52723 : walk_gimple_seq (gimple_omp_for_pre_body (stmt),
15724 : diagnose_sb_1, NULL, wi);
15725 52723 : walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
15726 52723 : wi->info = context;
15727 52723 : break;
15728 :
15729 556415 : case GIMPLE_LABEL:
15730 1112830 : splay_tree_insert (all_labels,
15731 556415 : (splay_tree_key) gimple_label_label (
15732 556415 : as_a <glabel *> (stmt)),
15733 : (splay_tree_value) context);
15734 556415 : break;
15735 :
15736 : default:
15737 : break;
15738 : }
15739 :
15740 3342816 : return NULL_TREE;
15741 : }
15742 :
15743 : /* Pass 2: Check each branch and see if its context differs from that of
15744 : the destination label's context. */
15745 :
15746 : static tree
15747 3342816 : diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
15748 : struct walk_stmt_info *wi)
15749 : {
15750 3342816 : gimple *context = (gimple *) wi->info;
15751 3342816 : splay_tree_node n;
15752 3342816 : gimple *stmt = gsi_stmt (*gsi_p);
15753 :
15754 3342816 : *handled_ops_p = true;
15755 :
15756 3342816 : switch (gimple_code (stmt))
15757 : {
15758 318998 : WALK_SUBSTMTS;
15759 :
15760 83608 : case GIMPLE_OMP_PARALLEL:
15761 83608 : case GIMPLE_OMP_TASK:
15762 83608 : case GIMPLE_OMP_SCOPE:
15763 83608 : case GIMPLE_OMP_SECTIONS:
15764 83608 : case GIMPLE_OMP_SINGLE:
15765 83608 : case GIMPLE_OMP_SECTION:
15766 83608 : case GIMPLE_OMP_STRUCTURED_BLOCK:
15767 83608 : case GIMPLE_OMP_MASTER:
15768 83608 : case GIMPLE_OMP_MASKED:
15769 83608 : case GIMPLE_OMP_ORDERED:
15770 83608 : case GIMPLE_OMP_SCAN:
15771 83608 : case GIMPLE_OMP_CRITICAL:
15772 83608 : case GIMPLE_OMP_TARGET:
15773 83608 : case GIMPLE_OMP_TEAMS:
15774 83608 : case GIMPLE_OMP_TASKGROUP:
15775 83608 : wi->info = stmt;
15776 83608 : walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
15777 83608 : wi->info = context;
15778 83608 : break;
15779 :
15780 52723 : case GIMPLE_OMP_FOR:
15781 52723 : wi->info = stmt;
15782 : /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
15783 : walk them. */
15784 52723 : walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
15785 : diagnose_sb_2, NULL, wi);
15786 52723 : walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
15787 52723 : wi->info = context;
15788 52723 : break;
15789 :
15790 205914 : case GIMPLE_COND:
15791 205914 : {
15792 205914 : gcond *cond_stmt = as_a <gcond *> (stmt);
15793 205914 : tree lab = gimple_cond_true_label (cond_stmt);
15794 205914 : if (lab)
15795 : {
15796 205914 : n = splay_tree_lookup (all_labels,
15797 : (splay_tree_key) lab);
15798 411828 : diagnose_sb_0 (gsi_p, context,
15799 205914 : n ? (gimple *) n->value : NULL);
15800 : }
15801 205914 : lab = gimple_cond_false_label (cond_stmt);
15802 205914 : if (lab)
15803 : {
15804 205914 : n = splay_tree_lookup (all_labels,
15805 : (splay_tree_key) lab);
15806 411828 : diagnose_sb_0 (gsi_p, context,
15807 205914 : n ? (gimple *) n->value : NULL);
15808 : }
15809 : }
15810 : break;
15811 :
15812 111979 : case GIMPLE_GOTO:
15813 111979 : {
15814 111979 : tree lab = gimple_goto_dest (stmt);
15815 111979 : if (TREE_CODE (lab) != LABEL_DECL)
15816 : break;
15817 :
15818 111979 : n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
15819 111979 : diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
15820 : }
15821 111979 : break;
15822 :
15823 424 : case GIMPLE_SWITCH:
15824 424 : {
15825 424 : gswitch *switch_stmt = as_a <gswitch *> (stmt);
15826 424 : unsigned int i;
15827 1724 : for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
15828 : {
15829 1316 : tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
15830 1316 : n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
15831 1316 : if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
15832 : break;
15833 : }
15834 : }
15835 : break;
15836 :
15837 730 : case GIMPLE_ASM:
15838 730 : {
15839 730 : gasm *asm_stmt = as_a <gasm *> (stmt);
15840 745 : for (unsigned i = 0; i < gimple_asm_nlabels (asm_stmt); ++i)
15841 : {
15842 21 : tree lab = TREE_VALUE (gimple_asm_label_op (asm_stmt, i));
15843 21 : n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
15844 21 : if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
15845 : break;
15846 : }
15847 : }
15848 : break;
15849 :
15850 34427 : case GIMPLE_RETURN:
15851 34427 : diagnose_sb_0 (gsi_p, context, NULL);
15852 34427 : break;
15853 :
15854 : default:
15855 : break;
15856 : }
15857 :
15858 3342816 : return NULL_TREE;
15859 : }
15860 :
15861 : static unsigned int
15862 56829 : diagnose_omp_structured_block_errors (void)
15863 : {
15864 56829 : struct walk_stmt_info wi;
15865 56829 : gimple_seq body = gimple_body (current_function_decl);
15866 :
15867 56829 : all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
15868 :
15869 56829 : memset (&wi, 0, sizeof (wi));
15870 56829 : walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
15871 :
15872 56829 : memset (&wi, 0, sizeof (wi));
15873 56829 : wi.want_locations = true;
15874 56829 : walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
15875 :
15876 56829 : gimple_set_body (current_function_decl, body);
15877 :
15878 56829 : splay_tree_delete (all_labels);
15879 56829 : all_labels = NULL;
15880 :
15881 56829 : return 0;
15882 : }
15883 :
15884 : namespace {
15885 :
15886 : const pass_data pass_data_diagnose_omp_blocks =
15887 : {
15888 : GIMPLE_PASS, /* type */
15889 : "*diagnose_omp_blocks", /* name */
15890 : OPTGROUP_OMP, /* optinfo_flags */
15891 : TV_NONE, /* tv_id */
15892 : PROP_gimple_any, /* properties_required */
15893 : 0, /* properties_provided */
15894 : 0, /* properties_destroyed */
15895 : 0, /* todo_flags_start */
15896 : 0, /* todo_flags_finish */
15897 : };
15898 :
15899 : class pass_diagnose_omp_blocks : public gimple_opt_pass
15900 : {
15901 : public:
15902 292371 : pass_diagnose_omp_blocks (gcc::context *ctxt)
15903 584742 : : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
15904 : {}
15905 :
15906 : /* opt_pass methods: */
15907 3008142 : bool gate (function *) final override
15908 : {
15909 3008142 : return flag_openacc || flag_openmp || flag_openmp_simd;
15910 : }
15911 56829 : unsigned int execute (function *) final override
15912 : {
15913 56829 : return diagnose_omp_structured_block_errors ();
15914 : }
15915 :
15916 : }; // class pass_diagnose_omp_blocks
15917 :
15918 : } // anon namespace
15919 :
15920 : gimple_opt_pass *
15921 292371 : make_pass_diagnose_omp_blocks (gcc::context *ctxt)
15922 : {
15923 292371 : return new pass_diagnose_omp_blocks (ctxt);
15924 : }
15925 :
15926 :
15927 : #include "gt-omp-low.h"
|